-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a test case for custom preprocessor #334
Conversation
CI results are in: this works on Windows under OCaml 4.x, and fails on Windows under OCaml 5.x. So this may be an upstream-OCaml issue, but I haven't tried to investigate and will happily leave this to @hhugo. |
Yet I can't install camlp4 on my machine on ocaml 4.14.1. I need to investigate, The CI failure on OCaml 5 could be due to missing parches in the sunset repo.. |
For the record, here is the error I get locally trying to install camlp4.
I found the following piece of code in camlp4 myocamlbuil that I don't really understand but I'd be nice to address it. Maybe @dra27 can help ? let hot_camlp4boot_dep, hot_camlp4boot_cmd =
if use_external_camlp4boot then
(None, "camlp4boot")
else
let exe =
"camlp4boot" ^
if C.ocamlnat then
(* If we are using a native plugin, we might as well use a native
preprocessor. *)
".native"
else
".byte"
in
let dep = "camlp4"/"boot"/exe in
let cmd =
let ( / ) = Filename.concat in
(*
* Workaround ocamlbuild problems on Windows by double-escaping.
* On systems using forward-slash, the calls to String.escaped will be
* no-ops anyway and the code will continue to work even once ocamlbuild
* correctly escapes output (the issue is trying to escape output for both cmd
* and bash)
*)
String.escaped (String.escaped ("camlp4"/"boot"/exe))
in
(Some dep, cmd)
in
let hot_camlp4boot_cmd =
if not windows then
hot_camlp4boot_cmd
else
let buf = Buffer.create (String.length hot_camlp4boot_cmd + 5) in
for i = 0 to String.length hot_camlp4boot_cmd - 1 do
match hot_camlp4boot_cmd.[i] with
| '/' ->
Buffer.add_string buf "\\";
| x -> Buffer.add_char buf x;
done;
Buffer.contents buf
in |
The patch against the compiler gives some information about what's going on.
|
This makes sense, the failing command in the testsuite does contain a forward slash:
On the other hand, the comment you quote mentions "unless you quote it explicitly", and it looks like an attempt at quoting was made here, there are in fact three quotes right after the |
After digging a bit, I wish I never did !!!
going the other way
I still need to figure out some steps.. |
5382e0f
to
b0dc7f6
Compare
I believe this PR is now ready for review. We're now checking in the CI that camlp4 can be installed with the current ocamlbuild and we're running the |
7a29cc4
to
6f64501
Compare
f920726
to
4fa6a78
Compare
Rebased |
src/command.ml
Outdated
| Quote s -> put_space (); put_filename (aux encode s) | ||
and do_specs = function | ||
| [] -> () | ||
| (A "-pp" as pp) :: Quote q :: rest -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels very fishy to me to special-case -pp
for special quoting rule. Why not apply this logic to all Quote
arguments?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we change the definition of Quote ?
It's currently
| Quote of spec (** A string that should be quoted like a filename but isn't really one. *)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that Quote
is in fact used for arguments that are themselves commands or prefixes of command, meant to be passed to the shell at some point. We could indeed change the (fairly unclear) documentation to reflect this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
testsuite/internal.ml
Outdated
~targets:("main.native", []) | ||
~post_cmd:( | ||
if Sys.win32 | ||
then "bash --norc -c ./main.native" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is odd that we have to do this here. Should the function that runs post_cmd
be calling My_std.sys_command
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The testsuite doesn't currently have access to ocamlbuild the lib. Should I make the change ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm okay with keeping this file separate from the ocamlbuild logic, as an external driver, but I would rather have the Windows-testing logic in ocamlbuild_test.ml
rather than in each caller of the test
function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
src/command.ml
Outdated
aux (fun x -> | ||
if ((!first && (first := false; String.contains x '/')) || not (Shell.is_simple_filename x)) | ||
then (My_std.quote_cmd ("\"" ^ x ^ "\"")) | ||
else x) q |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic here is fairly complex and also not clearly correct: if q
is to be interpreted as a command, then we need different quoting rules for the first argument of q
, which is not necessarily an argument on which the encode
function will be called. So encode
will run on a follow-up argument and the logic does not match the intent.
An alternative proposal would be as follows: on Windows, ensure that is_simple_filename
fails on filenames that contain a /
. Does that suffice to prevent the issue that you are guarding against here? (I would be happy to keep your nice, descriptive comment that explains why we need to protect certain occurrences of /
, which could move to Shell if we do it this way.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like moving this to Shell because it should only apply inside cmd.
I've change the logic to apply no only on the first encoded element.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remember that windows has more constraint on command line size.
This use case was found in camlp4 and is likely broken on windows. Let's try to fix.
This PR adds a special handling for
A '-pp'; Quote q
. The commandq
will be executed bycmd.exe
inocamlc/ocamldep/..
and needs to be escaped as such.Based on #338 and #339
Should fix #89