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

Enable CI on windows and fix it. #329

Merged
merged 16 commits into from
May 28, 2024
Merged

Enable CI on windows and fix it. #329

merged 16 commits into from
May 28, 2024

Conversation

hhugo
Copy link
Collaborator

@hhugo hhugo commented May 27, 2024

This is a somewhat minimal list of changes to make the testsuite pass on windows.
If you look at the CI jobs, you should see that the testsuite pass under windows.

Includes:

Probably fix #316

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.

This looks okay overall, see one question on the stderr rediction.

I'm not fond of the generalized use of explicit newline quoting in string literals in the testsuite, I find that it really hurts readability. Can we use quoted string literals instead?

flag [\"library\"; \"ocaml\"; \"record_foo_stubs\"]\n\
(S ([A \"-cclib\"; A \"-lfoo_stubs\"]));\n\
| _ -> ()\n\
end\n\
Copy link
Member

Choose a reason for hiding this comment

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

Urgh, can you use quoted literals instead to avoid the many escapes here? (If there is a problem with \r\n somehow, we could inject a small helper function that removes the \r.)

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 pushed 0f2342a

src/my_std.ml Outdated
@@ -279,7 +279,7 @@ let sys_command =
match Sys.os_type with
| "Win32" -> fun cmd ->
if cmd = "" then 0 else
let cmd = "bash --norc -c " ^ Filename.quote cmd in
let cmd = "bash --norc -c " ^ Filename.quote cmd ^ " 2>&1" in
Copy link
Member

Choose a reason for hiding this comment

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

Can you explain why we need this change?

Copy link
Collaborator Author

@hhugo hhugo May 27, 2024

Choose a reason for hiding this comment

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

I'm not happy with this change but it makes the testsuite pass.

I think the explanation is as follow:

  • if is_degraded or Sys.win32 is true, execute_many falls back to sys_command to implement execute_many.
  • otherwise, the logic from Ocamlbuild_executor.execute is used, which reads both stderr and stdout into a job_buffer.
  • The testuite sometime expect some output on stdout.

I'm still looking for a better solution.

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 moved the stderr redirection to command.ml where I think it belongs and added a small comment.

Copy link
Member

Choose a reason for hiding this comment

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

I went to look at the code of ocamlbuild_executor to understand what is going on. ocamlbuild_executor does not just redirect stderr into stdout, it lets the command write to different places and then on job termination it adds stdout, then stderr, to the job buffer, in that order. The change that you implemented does not match this behavior, it only works for commands that have only stdout or only stderr output.

Copy link
Member

Choose a reason for hiding this comment

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

Out of curiosity: in the execute_many definition, have you tried removing the "or we are on Windows" condition, to get the ocamlbuild_executor logic to run also on Windows? When ocamlbuild was first written, I think the Windows support in stdlib and Unix was weaker than it is now, there is a small chance that removing those alternate paths could work today.

(We could probably also get rid of the "is_degraded" notion, which I think was designed to let ocamlbuild build the compiler in constrained environments. ocamlbuild is not considered as build system for the OCaml compiler anymore, so maybe we could forget about this case altogether. But this is more work than I was considering putting in ocamlbuild again.)

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 tried removing the special case for windows in execute_many but it fails in various ways. It seems that the patch https://raw.githubusercontent.com/ocaml-opam/opam-repository-mingw/354a87b397856f2a70024c5c83fc5001074935b6/packages/ocamlbuild/ocamlbuild.0.14.2/files/ocamlbuild-0.14.2.patch is doing that better. I could look at merging that patch but I'd rather first have a working CI for windows

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 went to look at the code of ocamlbuild_executor to understand what is going on. ocamlbuild_executor does not just redirect stderr into stdout, it lets the command write to different places and then on job termination it adds stdout, then stderr, to the job buffer, in that order. The change that you implemented does not match this behavior, it only works for commands that have only stdout or only stderr output.

Looking at the code quickly, my impression is that it can interleave stdout and stderr. In the main loop, you can see

chrfds, do_read ~loop:false;

which tries to read any both stdout and stderr and push the content to job_buffer.

Maybe I'm misunderstanding the logic.

Copy link
Member

Choose a reason for hiding this comment

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

Ok, this suggests that I misunderstood, and there may be no good way to ensure that we get the same output. In that context I am okay with your current choice even though it is sort of a hack.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Out of curiosity: in the execute_many definition, have you tried removing the "or we are on Windows" condition, to get the ocamlbuild_executor logic to run also on Windows? When ocamlbuild was first written, I think the Windows support in stdlib and Unix was weaker than it is now, there is a small chance that removing those alternate paths could work today.

(We could probably also get rid of the "is_degraded" notion, which I think was designed to let ocamlbuild build the compiler in constrained environments. ocamlbuild is not considered as build system for the OCaml compiler anymore, so maybe we could forget about this case altogether. But this is more work than I was considering putting in ocamlbuild again.)

Done in #333 and #332

Copy link
Member

@kit-ty-kate kit-ty-kate left a comment

Choose a reason for hiding this comment

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

Looks fine on first glance with my minimal Windows experience.

cc-ing more experienced Windows users @dra27 @jonahbeckford

src/shell.ml Outdated
@@ -39,7 +39,7 @@ let run args target =
let cmd = String.concat " " (List.map quote_filename_if_needed args) in
if !*My_unix.is_degraded || Sys.os_type = "Win32" then
begin
Log.event cmd target Tags.empty;
if false then Log.event cmd target Tags.empty;
Copy link
Member

Choose a reason for hiding this comment

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

Why is this disabled?

Suggested change
if false then Log.event cmd target Tags.empty;
Log.event cmd target Tags.empty;

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It make the testsuite fail because it output cmd on stdout.
I wonder if we should prefix the command with "+ " similar to what is done in non-degraded mode. The testsuite filters theses lines out already.

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 added the + prefix

testsuite/ocamlbuild_test.ml Outdated Show resolved Hide resolved
testsuite/ocamlbuild_test.ml Outdated Show resolved Hide resolved
@gasche
Copy link
Member

gasche commented May 28, 2024

Ideally what I would like to do is to get good Windows support without making the codebase worse than it already is. I think that the current PR you propose is okay in this respect, the changes are relatively minimal and at the same time justified, and the risk of regression for non-Windows users is low. I propose to merge it and build up from there.

On the other hand I am more worried about the fdopen patches in #330, which look like a mix of good ideas (I like getting rid of the "or is win32" case in the "is degraded?" test), inscrutable hacks, and things in the middle, and was never really tested on non-Windows systems if I understand correctly. Taking the good pieces out of it is an excellent idea, and maybe all of it is good and I just don't understand it yet. But making our codebase harder to understand (obscure changes with little explanations and no commit message) is getting convenience right now but also even more pain later, so I would not be in favor.

Note: I noticed the same Be consistent! comment in the present PR and in the .patch file somewhere. Are you the author of all the changes in the current PR? If not, are reused fragments properly credited and do they have a compatible software license?

@hhugo
Copy link
Collaborator Author

hhugo commented May 28, 2024

00b92ab was extracted from an old PR #70 -> 62c40ca because I was seeing the issue mentioned in this PR.

@gasche
Copy link
Member

gasche commented May 28, 2024

Could you cherry-pick that commit (or amend the author information on your own commit) to properly credit fdopen in the metadata?

@hhugo
Copy link
Collaborator Author

hhugo commented May 28, 2024

Could you cherry-pick that commit (or amend the author information on your own commit) to properly credit fdopen in the metadata?

Done

@gasche
Copy link
Member

gasche commented May 28, 2024

@kit-ty-kate are you okay with merging this? My reasoning is: the patch looks okay, the potential for non-Windows regression is minimal, and I want to make it as easy as reasonably possible for @hhugo (or of course anyone else) to improve the state of ocamlbuild on Windows.

@hhugo
Copy link
Collaborator Author

hhugo commented May 28, 2024

(@dbuenzli, just for information, do you have any plan to drop your dependency on ocamlbuild ?, any ETA ?)

@gasche gasche merged commit 6c6d471 into ocaml:master May 28, 2024
20 checks passed
@gasche
Copy link
Member

gasche commented May 28, 2024

I went ahead and merged. Thanks @hhugo!

@gasche
Copy link
Member

gasche commented May 28, 2024

(It may be possible to close the issues that you helpfully linked, but at least the most recent one had more changes that were more contentious, and might deserve a discussion of their own. I hope that the part that you included solves most of the issues with less risk of regression.)

@dbuenzli
Copy link
Collaborator

any ETA ?

Not really, but I'd say within two or three years.

@kit-ty-kate
Copy link
Member

kit-ty-kate commented May 28, 2024

@kit-ty-kate are you okay with merging this? My reasoning is: the patch looks okay, the potential for non-Windows regression is minimal, and I want to make it as easy as reasonably possible for @hhugo (or of course anyone else) to improve the state of ocamlbuild on Windows.

Merging is fine as long as we remember to not release before getting the double-check/approval of the two people i've cc'd above. I'd like to especially double-check the change made to plugin-lib/ocamlbuild_unix_plugin.ml and src/command.ml, which seem a bit fragile, especially as:

  • bash could be present in the environment, without it being linked to an MSYS2 or Cygwin installation (e.g. some programs like some git installation ship with bash.exe)
  • I'm not certain the quoting used is always correct with cmd.exe but I may be wrong. In particular I would like to understand this comment from 8 years ago: quick windows fixes for 4.03 #70 (comment)
  • Calls to bash uses --noprofile in Import fdopen patch for windows #330, is there a reason why this has not been done here too? EDIT: nevermind i see why (-c vs interactive)

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.

Windows/Cygwin: hygienic check fails for some packages
5 participants