Skip to content
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

No longer call into cmd.exe to execute a posix shell on windows #339

Merged
merged 10 commits into from
Jun 23, 2024
Merged

Conversation

hhugo
Copy link
Collaborator

@hhugo hhugo commented Jun 20, 2024

based on top of #338
Inspired by #330.
Sys.command, Unix.open_process_in, Unix.open_process_full all go through cmd.exe to execute the given command.
In our case, it means we call cmd.exe to call bash.
This is unnecessary, and complicate things. We can directly call a posix shell and not have to worry about another layer of escaping.

In this PR, we use open_process_args* funtions to avoid going through cmd.exe

Copy link
Member

@dra27 dra27 left a comment

Choose a reason for hiding this comment

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

Couple of suggestions, but this looks very sensible. I'd definitely recommend the cygcheck trick - if ocamlbuild is run from cmd/powershell then by default bash is often going to be WSL, so it may be a good fallback ocamlbuild just to fail at that point (rather than run WSL's bash and the results be very surprising).

When ocamlbuild runs within an opam package (which is where it should be running 99% of the time), everything'll work as expected.

src/my_std.ml Outdated Show resolved Hide resolved
let rec iter = function
| [] -> [| "bash.exe" ; "--norc" ; "--noprofile" |]
| hd::tl ->
let dash = Filename.concat hd "dash.exe" in
Copy link
Member

Choose a reason for hiding this comment

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

A possible stronger trick for this, to avoid calling either WSL or the bash which gets exposed by Git-for-Windows (e.g. in Scoop, or when selecting the not-recommended "make all the utilities available" option).

First of all attempt to resolve cygcheck.exe. If that resolves, look for the shells in that directory (note that both MSYS2 and Cygwin have a cygcheck binary).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Are you suggesting

  1. to only do the cygcheck trick and fail if not found or
  2. to fallback to the current logic ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I implemented 2. for now

src/my_std.ml Outdated Show resolved Hide resolved
src/my_std.ml Outdated Show resolved Hide resolved
Copy link
Member

@gasche gasche left a comment

Choose a reason for hiding this comment

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

I haven't read the Windows details in details, but I agree with the idea of reusing tricky code from opam, so I'm in favor. (prepare_command_for_windows is a nice abstraction.) See minor review comment.

src/my_std.ml Outdated
@@ -275,13 +275,80 @@ let sys_file_exists x =
try Array.iter (fun x -> if x = basename then raise Exit) a; false
with Exit -> true

(* https://github.com/ocaml/opam/blame/master/src/core/opamStd.ml *)
Copy link
Member

Choose a reason for hiding this comment

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

(Luckily opam uses the same license so reusing code as-is is just fine.)

@hhugo could you maybe tweak your URL to contain a hash of a recent commit, instead of master? This would be helpful if someone in the future wants to now whether our local copy should be updated.

(I would have considered moving the copied-almost-exactly-as-is code to a separate file, to make such future tracking easier, but oh well.)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I've updated the comment

@hhugo
Copy link
Collaborator Author

hhugo commented Jun 22, 2024

There was some logic elsewhere to read the PATH (that was not handling quoted path).
I've unified things in d834dd0

if Sys.win32
then
let args = My_std.prepare_command_for_windows cmd in
open_process_args_full args.(0) args (Unix.environment ())
Copy link
Member

Choose a reason for hiding this comment

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

Why are you calling Unix.environment () again here, what is the expected difference with just env?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

no reason, I've changed it back.

@gasche gasche merged commit d42f4a7 into master Jun 23, 2024
15 checks passed
@hhugo hhugo deleted the win2 branch June 23, 2024 07:43
This was referenced Jun 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants