pax_global_header00006660000000000000000000000064147671052250014523gustar00rootroot0000000000000052 comment=abb287e2df94221d3c47f1408afb96d318d5426f camlp5-camlp5-buildscripts-abb287e/000077500000000000000000000000001476710522500172645ustar00rootroot00000000000000camlp5-camlp5-buildscripts-abb287e/.github/000077500000000000000000000000001476710522500206245ustar00rootroot00000000000000camlp5-camlp5-buildscripts-abb287e/.github/workflows/000077500000000000000000000000001476710522500226615ustar00rootroot00000000000000camlp5-camlp5-buildscripts-abb287e/.github/workflows/ci-debug.yml000066400000000000000000000027151476710522500250700ustar00rootroot00000000000000name: CI-DEBUG # on: [push, pull_request] on: [workflow_dispatch] jobs: build: strategy: fail-fast: false # Test Linux, macOS and Windows with the oldest and newest supported OCaml # and trunk. matrix: os: # - macos-latest # - ubuntu-latest - windows-latest ocaml-version: # - "4.14" - "5.3" # include: # - os: ubuntu-latest # ocaml-version: "4.10" # - os: macos-13 # ocaml-version: "4.10" # - os: macos-latest # ocaml-version: "4.10" runs-on: ${{ matrix.os }} steps: - name: Checkout code uses: actions/checkout@v4 - name: Set-up OCaml ${{ matrix.ocaml-version }} uses: ocaml/setup-ocaml@v3 with: ocaml-compiler: ${{ matrix.ocaml-version }} - name: Setup Dependencies run: | opam install . --deps-only --with-doc --with-test opam pin add camlp5-buildscripts . --no-action - name: Build it with make run: | opam exec -- make sys - name: Test it with make run: | opam exec -- make test # opam exec -- make clean - name: Install it with opam run: | opam install --strict camlp5-buildscripts - name: Archive test results if: always() uses: actions/upload-artifact@v4 with: name: test-results path: test/* camlp5-camlp5-buildscripts-abb287e/.github/workflows/ci.yml000066400000000000000000000024371476710522500240050ustar00rootroot00000000000000name: CI # on: [push, pull_request] on: [workflow_dispatch] jobs: build: strategy: fail-fast: false # Test Linux, macOS and Windows with the oldest and newest supported OCaml # and trunk. matrix: os: - macos-latest - ubuntu-latest - windows-latest ocaml-version: - "4.14" - "5.3" include: - os: ubuntu-latest ocaml-version: "4.10" - os: macos-13 ocaml-version: "4.10" - os: macos-latest ocaml-version: "4.10" runs-on: ${{ matrix.os }} steps: - name: Checkout code uses: actions/checkout@v4 - name: Set-up OCaml ${{ matrix.ocaml-version }} uses: ocaml/setup-ocaml@v3 with: ocaml-compiler: ${{ matrix.ocaml-version }} - name: Setup Dependencies run: | opam install . --deps-only --with-doc --with-test opam pin add camlp5-buildscripts . --no-action - name: Build it with make run: | opam exec -- make sys - name: Test it with make run: | opam exec -- make test opam exec -- make clean - name: Install it with opam run: | opam install --strict camlp5-buildscripts camlp5-camlp5-buildscripts-abb287e/.gitignore000066400000000000000000000000371476710522500212540ustar00rootroot00000000000000*.cm* local-install *.bak *.NEWcamlp5-camlp5-buildscripts-abb287e/CHANGES000066400000000000000000000025701476710522500202630ustar00rootroot00000000000000camlp5-buildscripts Version 0.06 -------------------------------- * [19 Mar 2025] Windows fixup: this time, fixing path-separator (thanks, @tobil4sk) camlp5-buildscripts Version 0.05 -------------------------------- * [19 Mar 2025] more fixups to try to make this work on Windows camlp5-buildscripts Version 0.04 ------------------- * [13 Dec 2024] tiny fixup for Makefile, to support Windows. Thanks to @tobil4sk for this! camlp5-buildscripts Version 0.03 ------------------- * [22 Jul 2023] Stupid, stupid, stupid error in ya-wrap-ocamlfind (was ignoring return-code from invoked command) This caused errors in builds in pa_ppx* packages to be silently ignored. Ugh. What idiocy. Fixed. This means that older pa_ppx* packages cannot build with this package/version. But it's only b/c they enable "debugging preprocessing" by default. If that's disabled, then they build fine. But still, what a mess. That this is such a tiny error is even more maddening. camlp5-buildscripts Version 0.02 ------------------- * [30 Jan 2023] some small changes ya-wrap-ocamlfind: change syntax of header comment to "(**pp ... *)" join_meta: reverse order of subdirs for wrap-subdirs, so more comprehensible to invokers all: change bootstrap to not generate static blocks, switch to pa_ppx_regexp camlp5-buildscripts Version 0.01 ------------------- * [30 Jan 2023] First release camlp5-camlp5-buildscripts-abb287e/LICENSE000066400000000000000000000020531476710522500202710ustar00rootroot00000000000000MIT License Copyright (c) 2023 chetmurthy Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. camlp5-camlp5-buildscripts-abb287e/Makefile000066400000000000000000000012041476710522500207210ustar00rootroot00000000000000 SYSDIRS= src TESTDIRS= test OCAMLFIND=ocamlfind all: sys set -e; for i in $(TESTDIRS); do cd $$i; $(MAKE) all; cd ..; done sys: set -e; for i in $(SYSDIRS); do cd $$i; $(MAKE) all; cd ..; done test: all set -e; for i in $(TESTDIRS); do cd $$i; $(MAKE) test; cd ..; done bootstrap: $(MAKE) -C pa_ppx_src bootstrap install: all $(OCAMLFIND) remove camlp5-buildscripts || true $(OCAMLFIND) install camlp5-buildscripts local-install/lib/camlp5-buildscripts/* uninstall: $(OCAMLFIND) remove camlp5-buildscripts || true clean:: set -e; for i in $(SYSDIRS) $(TESTDIRS); do cd $$i; $(MAKE) clean; cd ..; done rm -rf docs local-install camlp5-camlp5-buildscripts-abb287e/README.asciidoc000066400000000000000000000075241476710522500217310ustar00rootroot00000000000000camlp5-buildscripts: Sysadmin scripts for Camlp5 projects ========================================================= Sysadmin scripts written in OCaml (and Perl precursors), for use with Camlp5 and Camlp5-based projects. These will allow removing dependency on Perl for these projects. == Invocation The scripts are not installed in a bin-directory, but rather in the package's directory. So to invoke, we use the ocamlfind "exe" syntax. For example, to invoke "fixin": ``` ocamlfind camlp5-buildscripts/fixin .... args .... ``` == The Scripts `fixin`:: "fixes" the `#!` line of a script so that it points at an executable on the current `PATH`. That is, if the #! line is ``` #!perl ``` then it will be rewritten to the full-path of the `perl` that is found on the current `PATH`. `join_meta`:: Joins up a bunch of `META` files into a single `META` file. The idea is, you have a bunch of subdirectories, each of which installs a subpackage. One of those subpackages might actually be the "main" package, and you want the other subdirectories' META files to become subpackages in the new META file you're constructing. And at the same time, you'll want to rewrite names of those subpackages. For example, if your target package is `pa_ppx_regexp`, and you have two subdirectories: * `pa_perl` which installs a package `pa_ppx_regexp` * `runtime` which installs a package `pa_ppx_regexp_runtime` then you might want to build a composite `META` file that is based on that of `pa_perl`, but has `runtime`'s `META` file as a subpackage, named `"runtime"`. And then you'd want to replace all instances of `pa_ppx_regexp_runtime` with `pa_ppx_regexp.runtime` (notice "_" changes to ".") but only in `require` statements. `join_meta` does the above. Its usage: ``` join_meta -destdir -direct-include directly include /META file -wrap-subdir : include /META file wrapped as subpackage -rewrite : rewrite packages named to in `require' statements -help Display this list of options --help Display this list of options ``` It assumes that every subdirectory has a `META` file already-created, and joins them up, outputing the result to stdout. `ya-wrap-ocamlfind`:: "yet another ocamlfind wrapper". No doco yet. `LAUNCH`:: `LAUNCH` assumes there is an environment variable `TOP` that is either a relative or absolute reference to the top-level directory of the current project. It adds `$(TOP)/local-install/bin` to the `PATH` and sets `OCAMLPATH` to `$(TOP)/local-install/lib:` . This is useful for running `ocamlfind` commands that use the `$(TOP)/local-install` directory as a local installation-directory (hence no need to pollute global install-directories with package installation during complex multi-step builds. This means that when running tests (and multistep builds), we can assume that already-built packages are "installed" and can use `ocamlfind` to access them. `LAUNCH` is invoked thus: ``` ocamlfind camlp5-buildscripts/LAUNCH -v -- ``` Note that the `--` is mandatory. == Maintenance There are two directories containing these scripts: `pa_ppx_src` and `src`. The former directory contains scripts that are written using `pa_ppx_regexp` and whatever other PPX rewriters one might desire. The latter directory contains those same scripts, but after expansion via `not-ocamlfind preprocess` The "make all install" process only builds the scripts in `src`, so PPX rewriters are not necessary to build and install this project -- which is the point, so that this project can be used as build-scripts in `camlp5` and various PPX rewriter projects. There is a "bootstrap" target in the toplevel that will update the scripts in `src` if they are out-of-date w.r.t. the versions in `pa_ppx_src`, but it should be a no-op unless being used by the maintainer of this package. camlp5-camlp5-buildscripts-abb287e/opam000066400000000000000000000020441476710522500201430ustar00rootroot00000000000000version: "0.06" synopsis: "Camlp5 Build scripts (written in OCaml)" description: """ These are build-scripts that are helpful in building Camlp5 and packages based on Camlp5. As such, they need to *not* depend on Camlp5. The command are *not* installed in a bin-directory, but in the package-directory, hence invoked via the "ocamlfind package/exe" method. """ opam-version: "2.0" x-maintenance-intent: [ "(latest)" ] maintainer: "Chet Murthy " authors: ["Chet Murthy"] homepage: "https://github.com/camlp5/camlp5-buildscripts" license: "BSD-3-Clause" bug-reports: "https://github.com/camlp5/camlp5-buildscripts/issues" dev-repo: "git+https://github.com/camlp5/camlp5-buildscripts.git" doc: "https://github.com/camlp5/camlp5-buildscripts/doc" depends: [ "ocaml" { >= "4.10.0" } "not-ocamlfind" { >= "0.01" } "mdx" { with-test & >= "2.2.1" } "fmt" "re" { >= "1.10.4" } "bos" { >= "0.2.1" } ] build: [ [make "sys"] [make "test"] {with-test} ] install: [make "install"] url { src: "" checksum: [ "sha512=" ] } camlp5-camlp5-buildscripts-abb287e/pa_ppx_src/000077500000000000000000000000001476710522500214225ustar00rootroot00000000000000camlp5-camlp5-buildscripts-abb287e/pa_ppx_src/LAUNCH.ml000066400000000000000000000031451476710522500227310ustar00rootroot00000000000000 open Rresult open Bos open Fpath let push l x = (l := x :: !l) let verbose = ref false ;; let veryverbose = ref false ;; let cmd = ref [] ;; Arg.(parse [ "-v", (Set verbose),"verbose output" ; "-vv", Set veryverbose, "very verbose output" ; "--", (Rest (fun s -> cmd := !cmd @ [s])),"the command" ] (fun s -> cmd := !cmd @ [s]) "LAUNCH [-v] [--] " ) ;; let ( let* ) x f = Rresult.(>>=) x f let main () = let* top = match OS.Env.var "TOP" with Some v -> Ok v | None -> Error (`Msg "LAUNCH: environment variable TOP *must* be set to use this wrapper") in let path_var_separator = match Sys.os_type with | "Unix" -> ":" | _ -> ";" in let* path = OS.Env.req_var "PATH" in let newpath = [%pattern {|${top}/local-install/bin${path_var_separator}${path}|}] in let* () = OS.Env.set_var "PATH" (Some newpath) in let newcamlpath = [%pattern {|${top}/local-install/lib${path_var_separator}|}] in let* () = OS.Env.set_var "OCAMLPATH" (Some newcamlpath) in match !cmd with exe::_ -> if !verbose then Fmt.(pf stderr "LAUNCH: command %a\n%!" (list ~sep:(const string " ") Dump.string) !cmd) ; if !veryverbose then Fmt. (pf stderr "LAUNCH: env PATH=%a OCAMLPATH=%a %a\n%!" Dump.string newpath Dump.string newcamlpath (list ~sep:(const string " ") Dump.string) !cmd); Ok (Unix.execvp exe (Array.of_list !cmd)) | _ -> Error (`Msg "LAUNCH: at least one argument (the command-name) must be provided") ;; try R.failwith_error_msg (main ()) with exc -> Fmt.(pf stderr "%a\n%!" exn exc) camlp5-camlp5-buildscripts-abb287e/pa_ppx_src/Makefile000066400000000000000000000004541476710522500230650ustar00rootroot00000000000000 NOT_OCAMLFIND=not-ocamlfind bootstrap: ../src/join_meta.ml ../src/ya_wrap_ocamlfind.ml ../src/fixin.ml ../src/LAUNCH.ml ../src/%.ml: %.ml $(NOT_OCAMLFIND) preprocess -package pa_ppx_regexp,camlp5.pr_o -ppopt -pa_ppx_regexp-nostatic -syntax camlp5o $< > $@.NEW && \ mv $@.NEW $@ .SUFFIXES: .ml camlp5-camlp5-buildscripts-abb287e/pa_ppx_src/fixin.ml000066400000000000000000000033251476710522500230740ustar00rootroot00000000000000(** -syntax camlp5o *) let push l x = (l := x :: !l) open Rresult open Bos let read_fully ifile = OS.File.read ifile let write_fully ~mode ofile txt = OS.File.write ~mode ofile txt let ( let* ) x f = Rresult.(>>=) x f ;; let verbose = ref true ;; let files = ref [] ;; Arg.(parse [ "-s", (Arg.Clear verbose), ("silence verbosity") ] (fun s -> push files s) "fixin [-s] ") ;; let path_var_separator = match Sys.os_type with | "Unix" -> ':' | _ -> ';' let search_path = let dirs = String.split_on_char path_var_separator (Sys.getenv "PATH") in List.map Fpath.v dirs let fix_interpreter ~f (exedir, exename) = let open Fpath in let exename = v exename in let candidates = List.map (fun dir -> append dir exename) search_path in match List.find_opt OS.File.is_executable candidates with None -> if !verbose then Fmt.(pf stderr "Can't find %a in PATH, %a unchanged\n%!" pp exename pp f) ; to_string (append (v exedir) exename) | Some v -> if !verbose then Fmt.(pf stderr "Changing %a to %a\n%!" pp f pp v) ; to_string v let fixin_contents ~f txt = let txt = [%subst {|^#!([\S]+/)?([\S]+)|} / {|"#!" ^ (fix_interpreter ~f ($1$, $2$))|} /s e] txt in Ok txt let fixin1 f = let open Fpath in let f = v f in let newf = add_ext "NEW" f in let bakf = add_ext "bak" f in let* st = OS.Path.stat f in let mode = st.Unix.st_perm in let* contents = read_fully f in let* contents = fixin_contents ~f contents in let* () = write_fully ~mode newf contents in let* () = OS.Path.move ~force:true f bakf in let* () = OS.Path.move ~force:true newf f in Ok () ;; !files |> List.iter (fun f -> fixin1 f |> R.failwith_error_msg ) ;; camlp5-camlp5-buildscripts-abb287e/pa_ppx_src/join_meta.ml000066400000000000000000000047721476710522500237330ustar00rootroot00000000000000(** -syntax camlp5o *) open Rresult open Bos open Fpath let read_fully ifile = OS.File.read ifile let ( let* ) x f = Rresult.(>>=) x f ;; let push l x = (l := x :: !l) let read_ic_fully ?(msg="") ?(channel=stdin) () = let fd = Unix.descr_of_in_channel channel in if Unix.isatty fd && msg <> "" then begin Printf.printf "%s\n" msg ; flush stdout ; end ; let b = Buffer.create 23 in let rec rrec () = match try Some(input_char channel) with End_of_file -> None with None -> Buffer.contents b | Some c -> Buffer.add_char b c ; rrec () in rrec() let pkgmap = ref [] let direct_include = ref "" let wrap_subdirs = ref [] let split2 ~msg s = match [%match {|^([^:]+):([^:]+)$|} / strings (!1,!2)] s with Some (name, subdir) -> (name, subdir) | _ -> failwith Fmt.(str "%s: invalid arg <<%s>>" msg s) ;; Arg.(parse [ "-direct-include", (Arg.Set_string direct_include), (" directly include /META file") ;"-wrap-subdir", (Arg.String (fun s -> push wrap_subdirs (split2 ~msg:"wrap-subdir" s))), (": include /META file wrapped as subpackage ") ;"-rewrite", (Arg.String (fun s -> push pkgmap (split2 ~msg:"rewrite" s))), (": rewrite packages named to in `require' statements") ] (fun _ -> failwith "join_meta: no anonymous args supported") "join_meta -destdir ") ;; let indent n txt = let pfx = String.make n ' ' in [%subst {|^|} / {|${pfx}|} / g m] txt let fix txt = let l = [%split {|\s*,\s*|}] txt in let f s = match List.assoc s !pkgmap with exception Not_found -> s | v -> v in let ol = l |> List.map (fun p -> [%subst {|^([^.]+)|} / {| f $1$ |} / e] p ) in String.concat "," ol let fix0 txt = [%subst {|"([^"]+)"|} / {| "\"" ^ fix($1$) ^ "\"" |} / e] txt let fixdeps txt = [%subst {|^(.*require.*)$|} / {| fix0($1$) |} / m g e] txt let capturex (cmd, args) = let channel = Unix.open_process_args_in cmd args in let txt = read_ic_fully ~channel () in close_in channel ; txt ;; if !direct_include <> "" then print_string (indent 2 (fixdeps(R.failwith_error_msg (read_fully (v [%pattern {|./${!direct_include}/META|}]))))) ;; !wrap_subdirs |> List.rev |> List.iter (fun (name, subdir) -> let txt = indent 2 (fixdeps(R.failwith_error_msg (read_fully (v [%pattern {|./${subdir}/META|}])))) in print_string [%pattern {| package "${name}" ( ${txt} ) |}] ) ;; camlp5-camlp5-buildscripts-abb287e/pa_ppx_src/ya_wrap_ocamlfind.ml000066400000000000000000000027001476710522500254310ustar00rootroot00000000000000(** -syntax camlp5o *) let rec split_args cmd = function | "--" :: files -> List.rev cmd, files | [file] -> List.rev cmd, [file] | arg :: args -> split_args (arg :: cmd) args | [] -> failwith "please supply input arguments" let split_args = split_args [] let envsubst s = let envlookup vname = match Sys.getenv_opt vname with Some v -> v | None -> failwith [%pattern {|ya_wrap_ocamlfind: environment variable <<${vname}>> not found|}] in let f s1 s2 = if s1 <> "" then envlookup s1 else if s2 <> "" then envlookup s2 else assert false in [%subst {|(?:\$\(([^)]+)\)|\$\{([^}]+)\})|} / {| f $1$ $2$ |} / g e] s let discover_args f = let f' = open_in f in let rec drec () = let line1 = input_line f' in match ([%match {|^\s+$|} / pred] line1, [%match {|^#.*$|} / pred] line1, [%match {|^\(\*\*pp (.*?)\*\)|} / strings !1] line1) with | (true, _, _) -> drec () | (_, true, _) -> drec () | (_, _, None) -> "" | (_, _, Some params) -> envsubst params in let rv = drec () in close_in f'; rv let () = let cmd, files = Array.to_list Sys.argv |> List.tl |> split_args in let cmd = Filename.quote_command (List.hd cmd) (List.tl cmd) in List.iter (fun f -> let extra = discover_args f in let cmd = [%pattern {|${cmd} ${extra} ${f}|}] in Printf.fprintf stderr "%s\n%!" cmd; let rc = Sys.command cmd in if rc <> 0 then exit rc ) files camlp5-camlp5-buildscripts-abb287e/src/000077500000000000000000000000001476710522500200535ustar00rootroot00000000000000camlp5-camlp5-buildscripts-abb287e/src/.gitignore000066400000000000000000000000511476710522500220370ustar00rootroot00000000000000fixin join_meta ya-wrap-ocamlfind LAUNCH camlp5-camlp5-buildscripts-abb287e/src/LAUNCH.PL000077500000000000000000000012771476710522500212740ustar00rootroot00000000000000#!/usr/bin/env perl use strict ; use IPC::System::Simple qw(systemx runx capturex $EXITVAL); use String::ShellQuote ; use File::Basename; our $verbose = 0 ; { my $wd = dirname(dirname($0)) ; my $top = $ENV{'TOP'} || $wd; my %newenv ; $newenv{'PATH'} = "$top/local-install/bin:$ENV{'PATH'}" ; $newenv{'OCAMLPATH'} = "$top/local-install/lib:" ; local %ENV = (%ENV, %newenv) ; v_systemx([0], [@ARGV]) ; } sub v_systemx { croak( "v_systemx: must specify exit codes") unless (ref($_[0]) eq 'ARRAY') ; my $codes = shift ; my @cmd = @{ shift @_ } ; my %args = @_ ; print STDERR join(' ', map { shell_quote($_) } @cmd)."\n" if $main::verbose ; return runx($codes, @cmd) ; } camlp5-camlp5-buildscripts-abb287e/src/LAUNCH.ml000066400000000000000000000032551476710522500213640ustar00rootroot00000000000000 open Rresult open Bos open Fpath let push l x = l := x :: !l let verbose = ref false let veryverbose = ref false let cmd = ref [] let _ = Arg. (parse ["-v", Set verbose, "verbose output"; "-vv", Set veryverbose, "very verbose output"; "--", Rest (fun s -> cmd := !cmd @ [s]), "the command"] (fun s -> cmd := !cmd @ [s]) "LAUNCH [-v] [--] ") let ( let* ) x f = Rresult.(>>=) x f let main () = let* top = match OS.Env.var "TOP" with Some v -> Ok v | None -> Error (`Msg "LAUNCH: environment variable TOP *must* be set to use this wrapper") in let path_var_separator = match Sys.os_type with "Unix" -> ":" | _ -> ";" in let* path = OS.Env.req_var "PATH" in let newpath = String.concat "" [top; "/local-install/bin"; path_var_separator; ""; path] in let* () = OS.Env.set_var "PATH" (Some newpath) in let newcamlpath = String.concat "" [top; "/local-install/lib"; path_var_separator] in let* () = OS.Env.set_var "OCAMLPATH" (Some newcamlpath) in match !cmd with exe :: _ -> if !verbose then Fmt. (pf stderr "LAUNCH: command %a\n%!" (list ~sep:(const string " ") Dump.string) !cmd); if !veryverbose then Fmt. (pf stderr "LAUNCH: env PATH=%a OCAMLPATH=%a %a\n%!" Dump.string newpath Dump.string newcamlpath (list ~sep:(const string " ") Dump.string) !cmd); Ok (Unix.execvp exe (Array.of_list !cmd)) | _ -> Error (`Msg "LAUNCH: at least one argument (the command-name) must be provided") let _ = try R.failwith_error_msg (main ()) with exc -> Fmt.(pf stderr "%a\n%!" exn exc) camlp5-camlp5-buildscripts-abb287e/src/Makefile000066400000000000000000000016271476710522500215210ustar00rootroot00000000000000ifeq ($(OS),Windows_NT) WD=$(shell cygpath --absolute --windows .) EXE=.exe else WD=$(shell pwd) EXE= endif TOP=.. NOT_OCAMLFIND=not-ocamlfind OCAMLFIND=ocamlfind PACKAGES=re,fmt,unix,bos BIN=ya-wrap-ocamlfind$(EXE) fixin$(EXE) join_meta$(EXE) LAUNCH$(EXE) all: $(BIN) $(MAKE) DESTDIR=$(WD)/$(TOP)/local-install/ install ya-wrap-ocamlfind$(EXE): ya_wrap_ocamlfind.ml $(OCAMLFIND) ocamlc -linkpkg -linkall -package $(PACKAGES) $< -o $@ join_meta$(EXE): join_meta.ml $(OCAMLFIND) ocamlc -linkpkg -linkall -package $(PACKAGES) $< -o $@ fixin$(EXE): fixin.ml $(OCAMLFIND) ocamlc -linkpkg -linkall -package $(PACKAGES) $< -o $@ LAUNCH$(EXE): LAUNCH.ml $(OCAMLFIND) ocamlc -linkpkg -linkall -package $(PACKAGES) $< -o $@ install:: mkdir -p $(DESTDIR)/lib touch META $(NOT_OCAMLFIND) reinstall-if-diff camlp5-buildscripts -destdir $(DESTDIR)/lib META $(BIN) rm -f META clean:: rm -f *.bak *.cm* $(BIN) META camlp5-camlp5-buildscripts-abb287e/src/fixin.PL000077500000000000000000000037261476710522500214400ustar00rootroot00000000000000#!/usr/bin/perl # Usage: fixin [-s] [files] # Configuration constants. $does_shbang = 1; # Does kernel recognize #! hack? $verbose = 1; # Default to verbose # Construct list of directories to search. @absdirs = reverse grep(m!^/!, split(/:/, $ENV{'PATH'}, 999)); # Process command line arguments. if ($ARGV[0] eq '-s') { shift; $verbose = 0; } die "Usage: fixin [-s] [files]\n" unless @ARGV || !-t; @ARGV = '-' unless @ARGV; # Now do each file. FILE: foreach $filename (@ARGV) { open(IN, $filename) || ((warn "Can't process $filename: $!\n"), next); $_ = ; next FILE unless /^#!/; # Not a shbang file. # Now figure out the interpreter name. chop($cmd = $_); $cmd =~ s/^#! *//; ($cmd,$arg) = split(' ', $cmd, 2); $cmd =~ s!^.*/!!; # Now look (in reverse) for interpreter in absolute PATH. $found = ''; foreach $dir (@absdirs) { if (-x "$dir/$cmd") { warn "Ignoring $found\n" if $verbose && $found; $found = "$dir/$cmd"; } } # Figure out how to invoke interpreter on this machine. if ($found) { warn "Changing $filename to $found\n" if $verbose; if ($does_shbang) { $_ = "#!$found"; $_ .= ' ' . $arg if $arg ne ''; $_ .= "\n"; } else { $_ = <$filename") || die "Can't create new $filename: $!\n"; ($dev,$ino,$mode) = stat IN; $mode = 0755 unless $dev; chmod $mode, $filename; select(OUT); } # Print out the new #! line (or equivalent). print; # Copy the rest of the file. while () { print; } close IN; close OUT; } camlp5-camlp5-buildscripts-abb287e/src/fixin.ml000066400000000000000000000037301476710522500215250ustar00rootroot00000000000000(** -syntax camlp5o *) let push l x = l := x :: !l open Rresult open Bos let read_fully ifile = OS.File.read ifile let write_fully ~mode ofile txt = OS.File.write ~mode ofile txt let ( let* ) x f = Rresult.(>>=) x f let verbose = ref true let files = ref [] let _ = Arg. (parse ["-s", Arg.Clear verbose, "silence verbosity"] (fun s -> push files s) "fixin [-s] ") let path_var_separator = match Sys.os_type with "Unix" -> ':' | _ -> ';' let search_path = let dirs = String.split_on_char path_var_separator (Sys.getenv "PATH") in List.map Fpath.v dirs let fix_interpreter ~f (exedir, exename) = let open Fpath in let exename = v exename in let candidates = List.map (fun dir -> append dir exename) search_path in match List.find_opt OS.File.is_executable candidates with None -> if !verbose then Fmt. (pf stderr "Can't find %a in PATH, %a unchanged\n%!" pp exename pp f); to_string (append (v exedir) exename) | Some v -> if !verbose then Fmt.(pf stderr "Changing %a to %a\n%!" pp f pp v); to_string v let fixin_contents ~f txt = let txt = Re.replace ~all:false (Re.Perl.compile_pat ~opts:[`Dotall] "^#!([\\S]+/)?([\\S]+)") ~f:(fun __g__ -> "#!" ^ fix_interpreter ~f ((match Re.Group.get_opt __g__ 1 with None -> "" | Some s -> s), (match Re.Group.get_opt __g__ 2 with None -> "" | Some s -> s))) txt in Ok txt let fixin1 f = let open Fpath in let f = v f in let newf = add_ext "NEW" f in let bakf = add_ext "bak" f in let* st = OS.Path.stat f in let mode = st.Unix.st_perm in let* contents = read_fully f in let* contents = fixin_contents ~f contents in let* () = write_fully ~mode newf contents in let* () = OS.Path.move ~force:true f bakf in let* () = OS.Path.move ~force:true newf f in Ok () let _ = !files |> List.iter (fun f -> fixin1 f |> R.failwith_error_msg) camlp5-camlp5-buildscripts-abb287e/src/join_meta.ml000066400000000000000000000071541476710522500223610ustar00rootroot00000000000000(** -syntax camlp5o *) open Rresult open Bos open Fpath let read_fully ifile = OS.File.read ifile let ( let* ) x f = Rresult.(>>=) x f let push l x = l := x :: !l let read_ic_fully ?(msg = "") ?(channel = stdin) () = let fd = Unix.descr_of_in_channel channel in if Unix.isatty fd && msg <> "" then begin Printf.printf "%s\n" msg; flush stdout end; let b = Buffer.create 23 in let rec rrec () = match try Some (input_char channel) with End_of_file -> None with None -> Buffer.contents b | Some c -> Buffer.add_char b c; rrec () in rrec () let pkgmap = ref [] let direct_include = ref "" let wrap_subdirs = ref [] let split2 ~msg s = match (let __re__ = Re.Perl.compile_pat ~opts:[] "^([^:]+):([^:]+)$" in fun __subj__ -> match Option.map (fun __g__ -> Re.Group.get __g__ 1, Re.Group.get __g__ 2) (Re.exec_opt __re__ __subj__) with exception Not_found -> None | rv -> rv) s with Some (name, subdir) -> name, subdir | _ -> failwith Fmt.(str "%s: invalid arg <<%s>>" msg s) let _ = Arg. (parse ["-direct-include", Arg.Set_string direct_include, " directly include /META file"; "-wrap-subdir", Arg.String (fun s -> push wrap_subdirs (split2 ~msg:"wrap-subdir" s)), ": include /META file wrapped as subpackage "; "-rewrite", Arg.String (fun s -> push pkgmap (split2 ~msg:"rewrite" s)), ": rewrite packages named to in `require' statements"] (fun _ -> failwith "join_meta: no anonymous args supported") "join_meta -destdir ") let indent n txt = let pfx = String.make n ' ' in Re.replace ~all:true (Re.Perl.compile_pat ~opts:[`Multiline] "^") ~f:(fun __g__ -> String.concat "" [pfx]) txt let fix txt = let l = (let __re__ = Re.Perl.compile_pat ~opts:[] "\\s*,\\s*" in fun __subj__ -> Re.split __re__ __subj__) txt in let f s = match List.assoc s !pkgmap with exception Not_found -> s | v -> v in let ol = l |> List.map (fun p -> Re.replace ~all:false (Re.Perl.compile_pat ~opts:[] "^([^.]+)") ~f:(fun __g__ -> f (match Re.Group.get_opt __g__ 1 with None -> "" | Some s -> s)) p) in String.concat "," ol let fix0 txt = Re.replace ~all:false (Re.Perl.compile_pat ~opts:[] "\"([^\"]+)\"") ~f:(fun __g__ -> "\"" ^ fix (match Re.Group.get_opt __g__ 1 with None -> "" | Some s -> s) ^ "\"") txt let fixdeps txt = Re.replace ~all:true (Re.Perl.compile_pat ~opts:[`Multiline] "^(.*require.*)$") ~f:(fun __g__ -> fix0 (match Re.Group.get_opt __g__ 1 with None -> "" | Some s -> s)) txt let capturex (cmd, args) = let channel = Unix.open_process_args_in cmd args in let txt = read_ic_fully ~channel () in close_in channel; txt let _ = if !direct_include <> "" then print_string (indent 2 (fixdeps (R.failwith_error_msg (read_fully (v (String.concat "" ["./"; !direct_include; "/META"])))))) let _ = (!wrap_subdirs |> List.rev) |> List.iter (fun (name, subdir) -> let txt = indent 2 (fixdeps (R.failwith_error_msg (read_fully (v (String.concat "" ["./"; subdir; "/META"]))))) in print_string (String.concat "" ["\npackage \""; name; "\" (\n"; txt; "\n)\n"])) camlp5-camlp5-buildscripts-abb287e/src/ya-wrap-ocamlfind.PL000077500000000000000000000016441476710522500236320ustar00rootroot00000000000000#!/usr/bin/env perl use strict ; use String::ShellQuote ; our @cmd ; our @files ; while (@ARGV) { if ($ARGV[0] eq "--") { shift @ARGV ; @files = @ARGV ; last ; } elsif (int(@ARGV) == 1) { @files = @ARGV ; last ; } else { push(@cmd, shift @ARGV) ; } } { @cmd = map { shell_quote($_) } @cmd ; foreach my $f (@files) { my $extra = discover_args($f) ; my $cmd = "@cmd $extra $f\n" ; print STDERR $cmd ; system($cmd) ; } } sub discover_args { my $f = shift ; open(F, "<$f") || die "$0: cannot open $f for read (to sense extra args)" ; my $line1 = ; close(F) ; if ($line1 =~ m,^\(\*\*(.*?)\*\),) { my $extra = $1 ; $extra =~ s/(?:\$\(([^)]+)\)|\$\{([^}]+)\})/ envsubst($1, $2) /ge ; return $extra ; } else { return "" ; } } sub envsubst { my $varna = shift ; die "env var $varna is not set" unless exists $ENV{$varna} ; return $ENV{$varna} ; } camlp5-camlp5-buildscripts-abb287e/src/ya_wrap_ocamlfind.ml000066400000000000000000000042171476710522500240670ustar00rootroot00000000000000(** -syntax camlp5o *) let rec split_args cmd = function "--" :: files -> List.rev cmd, files | [file] -> List.rev cmd, [file] | arg :: args -> split_args (arg :: cmd) args | [] -> failwith "please supply input arguments" let split_args = split_args [] let envsubst s = let envlookup vname = match Sys.getenv_opt vname with Some v -> v | None -> failwith (String.concat "" ["ya_wrap_ocamlfind: environment variable <<"; vname; ">> not found"]) in let f s1 s2 = if s1 <> "" then envlookup s1 else if s2 <> "" then envlookup s2 else assert false in Re.replace ~all:true (Re.Perl.compile_pat ~opts:[] "(?:\\$\\(([^)]+)\\)|\\$\\{([^}]+)\\})") ~f:(fun __g__ -> f (match Re.Group.get_opt __g__ 1 with None -> "" | Some s -> s) (match Re.Group.get_opt __g__ 2 with None -> "" | Some s -> s)) s let discover_args f = let f' = open_in f in let rec drec () = let line1 = input_line f' in match (let __re__ = Re.Perl.compile_pat ~opts:[] "^\\s+$" in fun __subj__ -> Re.execp __re__ __subj__) line1, (let __re__ = Re.Perl.compile_pat ~opts:[] "^#.*$" in fun __subj__ -> Re.execp __re__ __subj__) line1, (let __re__ = Re.Perl.compile_pat ~opts:[] "^\\(\\*\\*pp (.*?)\\*\\)" in fun __subj__ -> match Option.map (fun __g__ -> Re.Group.get __g__ 1) (Re.exec_opt __re__ __subj__) with exception Not_found -> None | rv -> rv) line1 with true, _, _ -> drec () | _, true, _ -> drec () | _, _, None -> "" | _, _, Some params -> envsubst params in let rv = drec () in close_in f'; rv let () = let (cmd, files) = (Array.to_list Sys.argv |> List.tl) |> split_args in let cmd = Filename.quote_command (List.hd cmd) (List.tl cmd) in List.iter (fun f -> let extra = discover_args f in let cmd = String.concat "" [cmd; " "; extra; " "; f] in Printf.fprintf stderr "%s\n%!" cmd; let rc = Sys.command cmd in if rc <> 0 then exit rc) files camlp5-camlp5-buildscripts-abb287e/test/000077500000000000000000000000001476710522500202435ustar00rootroot00000000000000camlp5-camlp5-buildscripts-abb287e/test/.gitignore000066400000000000000000000000231476710522500222260ustar00rootroot00000000000000_build *.corrected camlp5-camlp5-buildscripts-abb287e/test/LAUNCH.md000066400000000000000000000002441476710522500215370ustar00rootroot00000000000000```sh $ ../src/LAUNCH echo foo Failure("LAUNCH: environment variable TOP *must* be set to use this wrapper") ``` ```sh $ env TOP=.. ../src/LAUNCH echo foo foo ``` camlp5-camlp5-buildscripts-abb287e/test/Makefile000066400000000000000000000003151476710522500217020ustar00rootroot00000000000000 TESTS=LAUNCH join_meta ya-wrap-ocamlfind all: test: $(TESTS) %: %.md rm -f $<.corrected ocaml-mdx test $< test '!' -f $<.corrected || diff -I '```' -Bwiu $< $<.corrected clean:: rm -f *.corrected camlp5-camlp5-buildscripts-abb287e/test/join_meta.md000066400000000000000000000024201476710522500225300ustar00rootroot00000000000000```sh $ ../src/join_meta -rewrite pa_ppx_regexp_runtime:pa_ppx_regexp.runtime -direct-include t/join_meta/pa_perl -wrap-subdir runtime:t/join_meta/runtime # Specifications for the "pa_ppx_regexp" preprocessor: requires = "camlp5,fmt,re,pa_ppx.base,pa_ppx_regexp.runtime,camlp5.parser_quotations" version = "0.01" description = "pa_ppx_regexp: pa_ppx_regexp rewriter" # For linking package "link" ( requires = "camlp5,fmt,re,pa_ppx.base.link,camlp5.parser_quotations.link" archive(byte) = "pa_ppx_regexp.cma" archive(native) = "pa_ppx_regexp.cmxa" ) # For the toploop: archive(byte,toploop) = "pa_ppx_regexp.cma" # For the preprocessor itself: requires(syntax,preprocessor) = "camlp5,fmt,re,pa_ppx.base,camlp5.parser_quotations" archive(syntax,preprocessor,-native) = "pa_ppx_regexp.cma" archive(syntax,preprocessor,native) = "pa_ppx_regexp.cmxa" package "runtime" ( # Specifications for the "pa_ppx_regexp_runtime" package: requires = "fmt" version = "0.01" description = "pa_ppx_regexp runtime support" # For linking archive(byte) = "pa_ppx_regexp_runtime.cma" archive(native) = "pa_ppx_regexp_runtime.cmxa" # For the toploop: archive(byte,toploop) = "pa_ppx_regexp_runtime.cma" ) ``` camlp5-camlp5-buildscripts-abb287e/test/t/000077500000000000000000000000001476710522500205065ustar00rootroot00000000000000camlp5-camlp5-buildscripts-abb287e/test/t/join_meta/000077500000000000000000000000001476710522500224535ustar00rootroot00000000000000camlp5-camlp5-buildscripts-abb287e/test/t/join_meta/pa_perl/000077500000000000000000000000001476710522500240755ustar00rootroot00000000000000camlp5-camlp5-buildscripts-abb287e/test/t/join_meta/pa_perl/META000066400000000000000000000013001476710522500245400ustar00rootroot00000000000000 # Specifications for the "pa_ppx_regexp" preprocessor: requires = "camlp5,fmt,re,pa_ppx.base,pa_ppx_regexp_runtime,camlp5.parser_quotations" version = "0.01" description = "pa_ppx_regexp: pa_ppx_regexp rewriter" # For linking package "link" ( requires = "camlp5,fmt,re,pa_ppx.base.link,camlp5.parser_quotations.link" archive(byte) = "pa_ppx_regexp.cma" archive(native) = "pa_ppx_regexp.cmxa" ) # For the toploop: archive(byte,toploop) = "pa_ppx_regexp.cma" # For the preprocessor itself: requires(syntax,preprocessor) = "camlp5,fmt,re,pa_ppx.base,camlp5.parser_quotations" archive(syntax,preprocessor,-native) = "pa_ppx_regexp.cma" archive(syntax,preprocessor,native) = "pa_ppx_regexp.cmxa" camlp5-camlp5-buildscripts-abb287e/test/t/join_meta/pa_ppx_regexp_runtime/000077500000000000000000000000001476710522500270575ustar00rootroot00000000000000camlp5-camlp5-buildscripts-abb287e/test/t/join_meta/pa_ppx_regexp_runtime/META000066400000000000000000000004761476710522500275370ustar00rootroot00000000000000 # Specifications for the "pa_ppx_regexp_runtime" package: requires = "fmt" version = "0.01" description = "pa_ppx_regexp runtime support" # For linking archive(byte) = "pa_ppx_regexp_runtime.cma" archive(native) = "pa_ppx_regexp_runtime.cmxa" # For the toploop: archive(byte,toploop) = "pa_ppx_regexp_runtime.cma" camlp5-camlp5-buildscripts-abb287e/test/t/join_meta/runtime/000077500000000000000000000000001476710522500241365ustar00rootroot00000000000000camlp5-camlp5-buildscripts-abb287e/test/t/join_meta/runtime/META000066400000000000000000000004761476710522500246160ustar00rootroot00000000000000 # Specifications for the "pa_ppx_regexp_runtime" package: requires = "fmt" version = "0.01" description = "pa_ppx_regexp runtime support" # For linking archive(byte) = "pa_ppx_regexp_runtime.cma" archive(native) = "pa_ppx_regexp_runtime.cmxa" # For the toploop: archive(byte,toploop) = "pa_ppx_regexp_runtime.cma" camlp5-camlp5-buildscripts-abb287e/test/t/ya-wrap-ocamlfind/000077500000000000000000000000001476710522500240205ustar00rootroot00000000000000camlp5-camlp5-buildscripts-abb287e/test/t/ya-wrap-ocamlfind/after-cppo.ml000066400000000000000000000001751476710522500264150ustar00rootroot00000000000000# 1 "test_utils.ml" (**pp -syntax camlp5o -package $(PAPACKAGES) *) (* Copyright 2019 Chetan Murthy, All rights reserved. *) camlp5-camlp5-buildscripts-abb287e/test/t/ya-wrap-ocamlfind/before-cppo.ml000066400000000000000000000002441476710522500265530ustar00rootroot00000000000000#ifdef PAPPX (**pp -syntax camlp5o -package $(PAPACKAGES) *) #else (**pp -package $(PPXPACKAGES) *) #endif (* Copyright 2019 Chetan Murthy, All rights reserved. *) camlp5-camlp5-buildscripts-abb287e/test/t/ya-wrap-ocamlfind/simple.ml000066400000000000000000000000421476710522500256370ustar00rootroot00000000000000(**pp -syntax goober *) let x = 1 camlp5-camlp5-buildscripts-abb287e/test/t/ya-wrap-ocamlfind/use_str.ml000066400000000000000000000000721476710522500260350ustar00rootroot00000000000000(**pp -package str *) open Str let re = Str.regexp "foo" camlp5-camlp5-buildscripts-abb287e/test/ya-wrap-ocamlfind.md000066400000000000000000000041461476710522500241040ustar00rootroot00000000000000```sh $ ../src/ya-wrap-ocamlfind echo t/ya-wrap-ocamlfind/simple.ml 'echo' -syntax goober t/ya-wrap-ocamlfind/simple.ml -syntax goober t/ya-wrap-ocamlfind/simple.ml ``` ```sh $ rm -f t/ya-wrap-ocamlfind/use_str.cm* $ ../src/ya-wrap-ocamlfind ocamlfind ocamlc -c t/ya-wrap-ocamlfind/use_str.ml 'ocamlfind' 'ocamlc' '-c' -package str t/ya-wrap-ocamlfind/use_str.ml $ ls t/ya-wrap-ocamlfind/use_str.cm* t/ya-wrap-ocamlfind/use_str.cmi t/ya-wrap-ocamlfind/use_str.cmo ``` ```sh $ rm -f t/ya-wrap-ocamlfind/use_str.cm* $ TOP=.. ../src/LAUNCH -v -- ../src/ya-wrap-ocamlfind ocamlfind ocamlc -c t/ya-wrap-ocamlfind/use_str.ml LAUNCH: command "../src/ya-wrap-ocamlfind" "ocamlfind" "ocamlc" "-c" "t/ya-wrap-ocamlfind/use_str.ml" 'ocamlfind' 'ocamlc' '-c' -package str t/ya-wrap-ocamlfind/use_str.ml $ ls t/ya-wrap-ocamlfind/use_str.cm* t/ya-wrap-ocamlfind/use_str.cmi t/ya-wrap-ocamlfind/use_str.cmo ``` ```sh $ PAPACKAGES=foo,bar ../src/ya-wrap-ocamlfind echo t/ya-wrap-ocamlfind/after-cppo.ml 'echo' -syntax camlp5o -package foo,bar t/ya-wrap-ocamlfind/after-cppo.ml -syntax camlp5o -package foo,bar t/ya-wrap-ocamlfind/after-cppo.ml ``` ```sh $ rm -rf _build && mkdir -p _build ``` ```sh $ cppo -D PAPPX t/ya-wrap-ocamlfind/before-cppo.ml > _build/cppo.pappx.ml $ PAPACKAGES=foo,bar PPXPACKAGES=buzz,fuzz ../src/ya-wrap-ocamlfind echo _build/cppo.pappx.ml 'echo' -syntax camlp5o -package foo,bar _build/cppo.pappx.ml -syntax camlp5o -package foo,bar _build/cppo.pappx.ml $ cat _build/cppo.pappx.ml # 2 "t/ya-wrap-ocamlfind/before-cppo.ml" (**pp -syntax camlp5o -package $(PAPACKAGES) *) # 6 "t/ya-wrap-ocamlfind/before-cppo.ml" (* Copyright 2019 Chetan Murthy, All rights reserved. *) ``` ```sh $ cppo -U PAPPX t/ya-wrap-ocamlfind/before-cppo.ml > _build/cppo.ppx.ml $ PAPACKAGES=foo,bar PPXPACKAGES=buzz,fuzz ../src/ya-wrap-ocamlfind echo _build/cppo.ppx.ml 'echo' -package buzz,fuzz _build/cppo.ppx.ml -package buzz,fuzz _build/cppo.ppx.ml $ cat _build/cppo.ppx.ml # 4 "t/ya-wrap-ocamlfind/before-cppo.ml" (**pp -package $(PPXPACKAGES) *) # 6 "t/ya-wrap-ocamlfind/before-cppo.ml" (* Copyright 2019 Chetan Murthy, All rights reserved. *) ```