From eaf9683010ca37785f377bce65f69eb211b8267d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonin=20D=C3=A9cimo?= Date: Tue, 4 Apr 2023 17:04:33 +0200 Subject: [PATCH 1/3] Add a -build-tree option to ocamldep ocamldep generates the list of dependencies of a given OCaml target file. The new -build-tree option adds a facility to add a (separate) prefix to the targets and the dependencies in its make output. This allows make to write targets in an other location than just the current working directory. Dependencies of the target that are also build artifacts are also found in this location. This is useful for out-of-source builds and cross-compilation. ocamldep outputs a trailing directory separator if the given string doesn't contain one, and respects -slash and -no-slash options. No other processing is made on the string. It is for instance possible to give a Makefile variable instead of a path. --- Changes | 4 ++++ driver/makedepend.ml | 37 +++++++++++++++++++++++++---------- man/ocamldep.1 | 3 +++ manual/src/cmds/ocamldep.etex | 3 +++ 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/Changes b/Changes index 5fde9be80e02..8a131128ae3d 100644 --- a/Changes +++ b/Changes @@ -156,6 +156,10 @@ Working version (Tim McGilchrist and Sebastien Hinderer, review by Sebastien Hinderer, Gabriel Scherer and Antonin Décimo) +- #12239: Add -source-tree and -build-tree options to ocamldep to + specify where to find dependencies and where to output a target. + (Antonin Décimo, review by Sébastien Hinderer, Nicolás Ojeda Bär) + ### Manual and documentation: - #13694: Fix name for caml_hash_variant in the C interface. diff --git a/driver/makedepend.ml b/driver/makedepend.ml index ecd74183043a..1b8df0419f70 100644 --- a/driver/makedepend.ml +++ b/driver/makedepend.ml @@ -34,6 +34,7 @@ let nocwd = ref false let one_line = ref false let allow_approximation = ref false let debug = ref false +let build_tree = ref "" (* [(dir, contents)] where [contents] is returned by [Sys.readdir dir]. *) let load_path = ref ([] : (string * string array) list) @@ -190,25 +191,39 @@ let print_filename s = let print_dependencies target_files deps = let pos = ref 0 in - let print_on_same_line item = + let artifacts = [".cmi"; ".cmo"; ".cmx"; ".cmxs"; ".o"] in + let print_build_tree, build_tree_len = + match !build_tree with + | "" -> Fun.id, 0 + | prefix -> + let len = String.length prefix in + let dir_sep = if Sys.os_type <> "Windows" || !Clflags.force_slash then + '/' else '\\' in + let s, len = if String.get prefix (len - 1) = dir_sep then + prefix, len + else prefix ^ String.make 1 dir_sep, len + 1 in + (fun () -> print_string s; pos := !pos + len), len + in + let print_on_same_line ~is_artifact item = if !pos <> 0 then print_string " "; + if is_artifact then print_build_tree (); print_filename item; pos := !pos + String.length item + 1; - in - let print_on_new_line item = + and print_on_new_line ~is_artifact item = print_string escaped_eol; + if is_artifact then print_build_tree (); print_filename item; pos := String.length item + 4; in let print_compact item = - if !one_line || (!pos + 1 + String.length item <= 77) - then print_on_same_line item - else print_on_new_line item - in - let print_dep item = + if !one_line || (!pos + 1 + build_tree_len + String.length item <= 77) + then print_on_same_line ~is_artifact:true item + else print_on_new_line ~is_artifact:true item + and print_dep item = + let is_artifact = List.mem (Filename.extension item) artifacts in if !one_line - then print_on_same_line item - else print_on_new_line item + then print_on_same_line ~is_artifact item + else print_on_new_line ~is_artifact item in List.iter print_compact target_files; print_string " "; print_string depends_on; @@ -624,6 +639,8 @@ let run_main argv = " (Windows) Preserve any backslash \\ in file paths"; "-sort", Arg.Set sort_files, " Sort files according to their dependencies"; + "-build-tree", Arg.String(fun s -> build_tree := s), + " Tree where build artifacts are written"; "-version", Arg.Unit print_version, " Print version and exit"; "-vnum", Arg.Unit print_version_num, diff --git a/man/ocamldep.1 b/man/ocamldep.1 index 166936b73153..db310e8a536e 100644 --- a/man/ocamldep.1 +++ b/man/ocamldep.1 @@ -187,6 +187,9 @@ Under Unix, this option does nothing. .B \-sort Sort files according to their dependencies. .TP +.B \-build\-tree \ path +Tree where build artifacts are written. +.TP .B \-version Print version string and exit. .TP diff --git a/manual/src/cmds/ocamldep.etex b/manual/src/cmds/ocamldep.etex index 1213cb9b1b26..4bdac1f4b1d4 100644 --- a/manual/src/cmds/ocamldep.etex +++ b/manual/src/cmds/ocamldep.etex @@ -138,6 +138,9 @@ nothing. \item["-sort"] Sort files according to their dependencies. +\item["-build-tree" \var{path}] +Tree where build artifacts are written. + \item["-version"] Print version string and exit. From 1d9bdd8317cca52fcd87c70f4a45b967dc6b11ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonin=20D=C3=A9cimo?= Date: Fri, 16 Jun 2023 16:37:35 +0200 Subject: [PATCH 2/3] Add a -source-tree option to ocamldep If ocamldep is invoked without `-all`, then the output doesn't refer to source files and there is no need for `-source-tree`. If `-all` is used, though, then rules output by ocamldep will refer to source files and, currently, they will contain the paths to the source files relative to where ocamldep is run from. Defining `-source-tree` allows to run the build from a different directory than of which ocamldep was run. --- driver/makedepend.ml | 16 ++++++++++++---- man/ocamldep.1 | 3 +++ manual/src/cmds/ocamldep.etex | 3 +++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/driver/makedepend.ml b/driver/makedepend.ml index 1b8df0419f70..9a9cd2584dd8 100644 --- a/driver/makedepend.ml +++ b/driver/makedepend.ml @@ -34,6 +34,7 @@ let nocwd = ref false let one_line = ref false let allow_approximation = ref false let debug = ref false +let source_tree = ref "" let build_tree = ref "" (* [(dir, contents)] where [contents] is returned by [Sys.readdir dir]. *) @@ -192,8 +193,8 @@ let print_filename s = let print_dependencies target_files deps = let pos = ref 0 in let artifacts = [".cmi"; ".cmo"; ".cmx"; ".cmxs"; ".o"] in - let print_build_tree, build_tree_len = - match !build_tree with + let print_prefix prefix = + match !prefix with | "" -> Fun.id, 0 | prefix -> let len = String.length prefix in @@ -204,14 +205,19 @@ let print_dependencies target_files deps = else prefix ^ String.make 1 dir_sep, len + 1 in (fun () -> print_string s; pos := !pos + len), len in + let print_build_tree, build_tree_len = print_prefix build_tree + and print_source_tree, _ = print_prefix source_tree + in let print_on_same_line ~is_artifact item = if !pos <> 0 then print_string " "; - if is_artifact then print_build_tree (); + if is_artifact then print_build_tree () + else print_source_tree (); print_filename item; pos := !pos + String.length item + 1; and print_on_new_line ~is_artifact item = print_string escaped_eol; - if is_artifact then print_build_tree (); + if is_artifact then print_build_tree () + else print_source_tree (); print_filename item; pos := String.length item + 4; in @@ -641,6 +647,8 @@ let run_main argv = " Sort files according to their dependencies"; "-build-tree", Arg.String(fun s -> build_tree := s), " Tree where build artifacts are written"; + "-source-tree", Arg.String(fun s -> source_tree := s), + " Tree where dependencies are found"; "-version", Arg.Unit print_version, " Print version and exit"; "-vnum", Arg.Unit print_version_num, diff --git a/man/ocamldep.1 b/man/ocamldep.1 index db310e8a536e..248f3d7ec70b 100644 --- a/man/ocamldep.1 +++ b/man/ocamldep.1 @@ -190,6 +190,9 @@ Sort files according to their dependencies. .B \-build\-tree \ path Tree where build artifacts are written. .TP +.B \-source\-tree \ path +Tree where dependencies are found. +.TP .B \-version Print version string and exit. .TP diff --git a/manual/src/cmds/ocamldep.etex b/manual/src/cmds/ocamldep.etex index 4bdac1f4b1d4..505d980cb15c 100644 --- a/manual/src/cmds/ocamldep.etex +++ b/manual/src/cmds/ocamldep.etex @@ -141,6 +141,9 @@ Sort files according to their dependencies. \item["-build-tree" \var{path}] Tree where build artifacts are written. +\item["-source-tree" \var{path}] +Tree where dependencies are found. + \item["-version"] Print version string and exit. From 247c0933af1c82b859c31103052ff215c8dee562 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonin=20D=C3=A9cimo?= Date: Fri, 16 Jun 2023 17:07:03 +0200 Subject: [PATCH 3/3] Test ocamldep new -build-tree and -source-tree options --- testsuite/tests/tool-ocamldep-tree/lib.ml | 1 + .../tests/tool-ocamldep-tree/main.compilers.reference | 11 +++++++++++ testsuite/tests/tool-ocamldep-tree/main.ml | 9 +++++++++ 3 files changed, 21 insertions(+) create mode 100644 testsuite/tests/tool-ocamldep-tree/lib.ml create mode 100644 testsuite/tests/tool-ocamldep-tree/main.compilers.reference create mode 100644 testsuite/tests/tool-ocamldep-tree/main.ml diff --git a/testsuite/tests/tool-ocamldep-tree/lib.ml b/testsuite/tests/tool-ocamldep-tree/lib.ml new file mode 100644 index 000000000000..e9066706584f --- /dev/null +++ b/testsuite/tests/tool-ocamldep-tree/lib.ml @@ -0,0 +1 @@ +let message = "Hello, world!" diff --git a/testsuite/tests/tool-ocamldep-tree/main.compilers.reference b/testsuite/tests/tool-ocamldep-tree/main.compilers.reference new file mode 100644 index 000000000000..a5ef78c8f17d --- /dev/null +++ b/testsuite/tests/tool-ocamldep-tree/main.compilers.reference @@ -0,0 +1,11 @@ +$(OD)/lib.cmo $(OD)/lib.cmi : \ + $(srcdir)/lib.ml +$(OD)/lib.cmx $(OD)/lib.o $(OD)/lib.cmi : \ + $(srcdir)/lib.ml +$(OD)/main.cmo $(OD)/main.cmi : \ + $(OD)/lib.cmi \ + $(srcdir)/main.ml +$(OD)/main.cmx $(OD)/main.o $(OD)/main.cmi : \ + $(OD)/lib.cmi \ + $(OD)/lib.cmx \ + $(srcdir)/main.ml diff --git a/testsuite/tests/tool-ocamldep-tree/main.ml b/testsuite/tests/tool-ocamldep-tree/main.ml new file mode 100644 index 000000000000..9c0978a65bf2 --- /dev/null +++ b/testsuite/tests/tool-ocamldep-tree/main.ml @@ -0,0 +1,9 @@ +(* TEST + modules = "lib.ml main.ml"; + setup-ocamlc.byte-build-env; + commandline = "-depend -all -source-tree $(srcdir) -build-tree $(OD) lib.ml main.ml"; + ocamlc.byte; + check-ocamlc.byte-output; + *) + +let () = print_endline Lib.message