Skip to content

[WIP] Implement responsefiles support PR7050#843

Merged
gasche merged 6 commits intoocaml:trunkfrom
bschommer:responsefile
Oct 12, 2016
Merged

[WIP] Implement responsefiles support PR7050#843
gasche merged 6 commits intoocaml:trunkfrom
bschommer:responsefile

Conversation

@bschommer
Copy link
Contributor

Follow up to PR #748 against trunk.

The function read_arg, read_arg0, write_arg and write_arg0 read
and write command line arguments to a file which are either
separated by a NUL character or by new lines.
@gasche
Copy link
Member

gasche commented Oct 10, 2016

This PR implements functions for parsing of argument files. Do you plan to eventually add commits that combine this with the new Expand support to actually provide -args/args0 arguments to the compiler tools, or would that be out of the scope of the current PR?

The -arg/-args0 switch allow it to pass additional command line
arguments in files newline/NUL separated.
@bschommer
Copy link
Contributor Author

I added the functions to the compiler command line arguments.

Copy link
Member

@damiendoligez damiendoligez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added some change suggestions.

About the scope: I think it makes sense to add the options to all tools.

\ and instead fix invalid formats.)"
;;

let mk_expand_responsefile f =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please respect the format: these functions have the same name as the options they describe, with dashes replaced by underscores, so this should be mk_args and the next one should be mk_args0.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is changed.

val _nopervasives : unit -> unit
val _dtimings : unit -> unit

val _expand_responsefile: string -> string array
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same remark about the function names.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is changed.

stdlib/arg.ml Outdated
try
let c = input_char ic in
if c = sep then begin
stash inw; read true
Copy link
Member

@damiendoligez damiendoligez Oct 11, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be read false, right?
In fact you should drop inw altogether because we decided we want to allow empty arguments. Just add a test at EOF to stash only when the buffer is not empty.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is changed.

stdlib/arg.ml Outdated
first:=false
else
output_char oc sep in
Array.iter (fun s -> sep (); output_string oc s) args;
Copy link
Member

@damiendoligez damiendoligez Oct 11, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get rid of the ugly first reference and output a "separator" after each arg. Formally, they are terminators, with the last one optional.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is changed.

stdlib/arg.mli Outdated
at the next element. *)

val read_arg: string -> string array
(** [Arg.read_arg file] reads new line separated command line arguments from
Copy link
Member

@damiendoligez damiendoligez Oct 11, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to your implementation, they are not "new line separated" but "linefeed-separated". What happened to the suggestion of ignoring CR in this case?

Also, this should be terminated rather than separated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is changed.

stdlib/arg.mli Outdated
file [file]. *)

val read_arg0: string -> string array
(** Identical to {!Arg.read_arg} but assumes NUL separated command line
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same remark about separated vs terminated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is changed.

stdlib/arg.mli Outdated
arguments *)

val write_arg: string -> string array -> unit
(** [Arg.write_arg file args] writes the arguments [args] newline separated into
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

terminated

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is changed.

stdlib/arg.mli Outdated
use the function {!Args.write_arg0} instead *)

val write_arg0: string -> string array -> unit
(** Identical to {!Arg.write_arg} but uses NUL as separator instead *)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

terminator

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is changed.

;;

test_rw args1;;
test_rw args2;;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should also test with an empty argument list and a list that contains empty arguments.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is added.

The read_aux function trims the cr character for the new-line
based method and the write functions are simplified without an
additional sep function.

The argument names are changed to match the default naming format
and the documentation is updated to match the implementation
behavior.

Also two new tests for reading and writing empty command lines as
well as a command lines containing empty arguments are added.
@bschommer
Copy link
Contributor Author

For the other tools: I will have a look but as @diml noted ocamldebug for example needs special care.

The parse_expand function does the same as parse and parse_dynamic
but allows Expand. However it does not update current to avoid
the problem that the array is modified.

This function is used for the ocamlopt, ocamlc, ocamlcp,
ocamloptp and ocamldep.
@bschommer
Copy link
Contributor Author

I added ocamldep to the list of supported tools. I also added a simple wrapper around parse_and_expand_argv_dynamic that also prints error/help messages to Arg. In order to avoid the problems with current and the changed array the function does not modify Arg.current is not modified.

Now also the tools dumpobj, objinfo, ocamlprof, primreq and
read_cmt accept response files.
@damiendoligez
Copy link
Member

For the other tools: I will have a look but as @diml noted ocamldebug for example needs special care.

I did not mean to push hard for supporting all tools, but since you asked about scope (in #748 (comment)) I wanted to give a positive answer. I'd be happy with a partial implementation anyway.

Copy link
Member

@damiendoligez damiendoligez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks OK to me now.

@bschommer
Copy link
Contributor Author

bschommer commented Oct 12, 2016

List of missing tools/programs:

  • ocaml
  • ocamldebug
  • ocamlyacc
  • ocamlex
  • ocamldoc
  • cvt_emit
  • cmpbyt
  • ocamlmklib
  • ocamlmktop
  • stripdebug

@bschommer
Copy link
Contributor Author

bschommer commented Oct 12, 2016

For stripdebug, cvt_emit, cmpbyt and ocamlyacc, ocamllex it does not make sense to add it since they expect a constant number of options.

ocamlmktop only passes the commands on.

ocamldebug, ocaml, ocamldoc and ocamlmklib all have either hand written parse functions or require some preprocessing of the arguments and I'm unsure if it works for them without problem.

@bschommer
Copy link
Contributor Author

I did not mean to push hard for supporting all tools, but since you asked about scope (in #748 (comment)) I wanted to give a positive answer. I'd be happy with a partial implementation anyway.

No problem, most of them are pretty straightforward.

@gasche
Copy link
Member

gasche commented Oct 12, 2016

I think that it would be nice to have support in ocaml and ocamlnat as well (you may have noticed that I mistakenly advertised it to Coq developers; I thought that the functorized argument-parsing machinery would provide the feature for the toplevels as well). It could be useful for the Coq use-case, as it allows as a debugging technique to "Drop" to the OCaml toplevel.

(Command-line is in the files toplevel/topmain.ml (for ocaml) and toplevel/opttopmain.ml (for ocamlnat). The native toplevel is not officially supported but it's on the path to redemption these days, so it's nice to keep it in synch.)

@bschommer
Copy link
Contributor Author

I will have a look at ocaml and ocamlnat.

@bschommer
Copy link
Contributor Author

bschommer commented Oct 12, 2016

It seems like it is not possible without some unsafe operations:

let override_sys_argv args =
  let len = Array.length args in
  if Array.length Sys.argv < len then invalid_arg "Toploop.override_sys_argv";
  Array.blit args 0 Sys.argv 0 len;
  Obj.truncate (Obj.repr Sys.argv) len;
  Arg.current := 0

@gasche
Copy link
Member

gasche commented Oct 12, 2016

The toplevel uses a horrible hack so that the first argument is the name of the executed file instead of the toplevel binary (I suppose). But how does this prevent handling Expand nodes in the argument array after this hack has been applied? I don't understand why there is a conflict here.

@bschommer
Copy link
Contributor Author

bschommer commented Oct 12, 2016

override_sys_argv actually copies the rest of the un-parsed arguments into Sys.argv and then truncates Sys.argv. However Expand may increase the array beyond the length of Sys.argv and the copy would only work if the size is increased instead of making it smaller.

@gasche
Copy link
Member

gasche commented Oct 12, 2016

So if I understand correctly, the toplevel parses the provided argument list, then it stops on the first anonymous argument that is a source file (.ml extension), and considers that the remaining arguments are to be processed by the script itself upon execution, so it rewrites Sys.argv in place to have just the remaining argument as the control is passed to the script.

As it rewrites the arguments, it checks that the new argument-list is smaller than the previous one (as it is supposed to be a suffix of it). This could fail in general if one of the Expand node would generate a source file argument. (Note that if the Expand nodes don't generate source files argument, this would succeed, as the suffix would remain the same).

I'm confident there is a reasonable solution (for example we could just disable the size check that is certainly there for debugging), but it also seems to require a bit more work than I hoped. Would you agree with merging the current PR, and eventually support the toplevel in a following PR?

(I'm not implying that you personally have to do the toplevel-related work. If I have time I could try to implement it myself. Let us know what you want to do.)

@bschommer
Copy link
Contributor Author

That is fine with me.

@gasche
Copy link
Member

gasche commented Oct 12, 2016

Could you add a Changes entry? Suggestion:

### Compiler user-interface and warnings:

[...]

- MPR#7050, GPR#748 GPR#843: new `-arg/-arg0 <file>` parameters to provide
  extra command-line arguments in a file -- see documentation.
  User programs may implement similar options
  using the new `Arg.Expand` constructor.
  (Bernhard Schommer, review by Jérémie Dimino, Gabriel Scherer
   and Damien Doligez, discussion with Alain Frisch and Xavier Leroy,
   feature request from the Coq team)

@gasche gasche merged commit 9b08f08 into ocaml:trunk Oct 12, 2016
@gasche
Copy link
Member

gasche commented Oct 12, 2016

Thanks a lot for your hard work! Do you plan to look at the toplevel?

@bschommer
Copy link
Contributor Author

I will have a look at it. Basically it seems that instead of truncate one needs some kind of adjust primitive. When I find a solution I will open a new PR.

@bschommer bschommer deleted the responsefile branch October 12, 2016 16:02
@gasche
Copy link
Member

gasche commented Oct 12, 2016

(I now understand that relaxing the check is not enough as truncate actually requires a smaller value. Maybe the toplevel could just forbid source script names from within the return of Expand?)

@gasche
Copy link
Member

gasche commented Oct 26, 2016

@alainfrisch rightly pointed out that this feature was not documented (it's not in the manual or in the compiler manpages). I am planning on opening a Mantis ticket to track that need (tomorrow). @bschommer, would you be willing to send a patch for that?

end else begin
Buffer.add_char buf c; read ()
end
with End_of_file ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, this try...with breaks tail-recursion and would lead to stack overflow if the file is large enough. Will submit a PR to address that shortly.

camlspotter pushed a commit to camlspotter/ocaml that referenced this pull request Oct 17, 2017
[WIP] Implement responsefiles support PR7050
stedolan pushed a commit to stedolan/ocaml that referenced this pull request Oct 25, 2022
sadiqj pushed a commit to sadiqj/ocaml that referenced this pull request Feb 21, 2023
stedolan pushed a commit to stedolan/ocaml that referenced this pull request Mar 21, 2023
25188da flambda-backend: Missed comment from PR802 (ocaml#887)
9469765 flambda-backend: Improve the semantics of asynchronous exceptions (new simpler version) (ocaml#802)
d9e4dd0 flambda-backend: Fix `make runtest` on NixOS (ocaml#874)
4bbde7a flambda-backend: Simpler symbols (ocaml#753)
ef37262 flambda-backend: Add opaqueness to Obj.magic under Flambda 2 (ocaml#862)
a9616e9 flambda-backend: Add build system hooks for ocaml-jst (ocaml#869)
045ef67 flambda-backend: Allow the compiler to build with stock Dune (ocaml#868)
3cac5be flambda-backend: Simplify Makefile logic for natdynlinkops (ocaml#866)
c5b12bf flambda-backend: Remove unnecessary install lines (ocaml#860)
ff12bbe flambda-backend: Fix unused variable warning in st_stubs.c (ocaml#861)
c84976c flambda-backend: Static check for noalloc: attributes (ocaml#825)
ca56052 flambda-backend: Build system refactoring for ocaml-jst (ocaml#857)
39eb7f9 flambda-backend: Remove integer comparison involving nonconstant polymorphic variants (ocaml#854)
c102688 flambda-backend: Fix soundness bug by using currying information from typing (ocaml#850)
6a96b61 flambda-backend: Add a primitive to enable/disable the tick thread (ocaml#852)
f64370b flambda-backend: Make Obj.dup use a new primitive, %obj_dup (ocaml#843)
9b78eb2 flambda-backend: Add test for ocaml#820 (include functor soundness bug) (ocaml#841)
8f24346 flambda-backend: Add `-dtimings-precision` flag (ocaml#833)
65c2f22 flambda-backend: Add test for ocaml#829 (ocaml#831)
7b27a49 flambda-backend: Follow-up PR#829 (comballoc fixes for locals) (ocaml#830)
ad7ec10 flambda-backend: Use a custom condition variable implementation (ocaml#787)
3ee650c flambda-backend: Fix soundness bug in include functor (ocaml#820)
2f57378 flambda-backend: Static check noalloc (ocaml#778)
aaad625 flambda-backend: Emit begin/end region only when stack allocation is enabled (ocaml#812)
17c7173 flambda-backend: Fix .cmt for included signatures (ocaml#803)
e119669 flambda-backend: Increase delays in tests/lib-threads/beat.ml (ocaml#800)
ccc356d flambda-backend: Prevent dynamic loading of the same .cmxs twice in private mode, etc. (ocaml#784)
14eb572 flambda-backend: Make local extension point equivalent to local_ expression (ocaml#790)
487d11b flambda-backend: Fix tast_iterator and tast_mapper for include functor. (ocaml#795)
a50a818 flambda-backend: Reduce closure allocation in List (ocaml#792)
96c9c60 flambda-backend: Merge ocaml-jst
a775b88 flambda-backend: Fix ocaml/otherlibs/unix 32-bit build (ocaml#767)
f7c2679 flambda-backend: Create object files internally to avoid invoking GAS (ocaml#757)
c7a46bb flambda-backend: Bugfix for Cmmgen.expr_size with locals (ocaml#756)
b337cb6 flambda-backend: Fix build_upstream for PR749 (ocaml#750)
8e7e81c flambda-backend: Differentiate is_int primitive between generic and variant-only versions (ocaml#749)

git-subtree-dir: ocaml
git-subtree-split: 25188da
EmileTrotignon pushed a commit to EmileTrotignon/ocaml that referenced this pull request Jan 12, 2024
* better header package search box styles

* placeholder in gray

Co-authored-by: Sabine Schmaltz <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants