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

Resolve the Cygwin bin directory above Windows system32 directory #5832

Merged
merged 5 commits into from
Apr 8, 2024

Conversation

dra27
Copy link
Member

@dra27 dra27 commented Feb 11, 2024

OpamProcess.cygwin_create_process_env contains some ad hoc logic which ensures that the Cygwin bin directory appears before the Windows system32 directory in Path and adjusts it if necessary. This allows the user to put c:\cygwin64\bin routinely at the end of Path so that Cygwin utilities don't shadow anything (including, importantly, the Microsoft linker link.exe if using the MSVC port of OCaml). However, when invoking a Cygwin executable directly, this results in /usr/bin appearing at the end of PATH, which is confusing - especially if the executable (or script) expects to invoke bash. Hence the workaround.

There are, however, more things than just bash.exe where Cygwin executables may want their own version to apply when executing and it's possible for other directories to shadow Cygwin as well.

Enter #5545, and opam's internally managed Cygwin. This inserts a PATH =+ update to append the Cygwin bin directory to the end when executing build and install commands, etc. This environment update interacts surprisingly with OpamProcess.cygwin_create_process_env. ["bash" "-c" "..."] "executes" using WSL yet ["sh" "-c" "bash -c \"foo\""] executes using Cygwin's bash, for example. The resolution problems can be clearly seen using where-["where" "bash"]showsC:\Windows\system32\bash.exebeing first but["sh" "-c" "where bash"]shows Cygwin'sbash.exe` being first.

This PR generalises the adjustment being made to Path by introducing a new kind of environment update. This update is only available internally via the constructor Cygwin (i.e. it cannot appear in opam files, nor can it be written/read from environment files). It places the directory given as far down the list of directories in Path so that bash.exe, tar.exe and sort.exe (and git.exe, if Cygwin's git is being used) still resolve to the Cygwin copy. In practice, this means that the bin directory will never be placed after C:\Window\system32 (as before) but also means, for example, that it would not be moved after a Scoop bin directory (which may contain bash.exe or git.exe), etc.

With this slightly more principled mechanism in place, the ad hoc adjustment in OpamProcess.cygwin_create_process_env is removed (i.e. if the user puts C:\cygwin64\bin into Path, they are now responsible for putting it in the right place; when opam puts its own .cygwin\root\bin diectory into Path, it ensures that it puts it into the correct place.)

@dra27 dra27 added this to For beta2 in Opam 2.2.0 Feb 11, 2024
@dra27 dra27 added this to the 2.2.0~beta2 milestone Feb 11, 2024
@kit-ty-kate kit-ty-kate added PR: WIP Not for merge at this stage AREA: PORTABILITY labels Mar 5, 2024
@kit-ty-kate kit-ty-kate linked an issue Mar 8, 2024 that may be closed by this pull request
@dra27 dra27 removed the PR: WIP Not for merge at this stage label Mar 27, 2024
@dra27 dra27 requested a review from rjbou March 27, 2024 17:13
@dra27 dra27 marked this pull request as ready for review March 27, 2024 17:13
src/format/dune Outdated Show resolved Hide resolved
@dra27
Copy link
Member Author

dra27 commented Mar 27, 2024

First two commits are optional (and could be moved elsewhere). Could do with some more comments, possibly a test. I've been testing with this:

opam-version: "2.0"
synopsis: "Show the environment"
description: "Yet another environment debug package"
maintainer: "David Allsopp <[email protected]>"
authors: "David Allsopp"
license: "ISC"
homepage: "https://opam.ocaml.org"
bug-reports: "https://github.com/ocaml/opam/issues"
flags: conf
build: [
  ["cmd" "/c" "echo %%PATH%%"] # *** 1 ***
  ["cmd" "/c" "echo ============================================"]
  ["sh" "-c" "env | grep '^PATH='"] # *** 2 ***
  ["cmd" "/c" "echo ============================================"]
  ["cmd" "/c" "env | findstr /R ^^PATH="] # *** 3 ****
  ["cmd" "/c" "echo ============================================"]
  ["where" "bash"] # *** 4 ***
]

but that's not readily convertable to a test script. Before this PR:

  1. Has cygbin at the end of PATH
  2. Has cygbin just before C:\Windows\system32\ in PATH
  3. Is the same as 1 (so cygbin at the end of PATH)
  4. Has C:\Windows\system32\bash.exe first if you have WSL installed 💀

With this PR, 1, 2 and 3 all have cygbin just before C:\Windows\system32\ and 4 has bash.exe in cygbin first, regardless of whether you have WSL installed 😇

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.

Aside from the question of where the TypeGymnastics module/test should live (I would personally prefer for it to be in a new tests/libtests directory or something like that), LGTM.

@dra27
Copy link
Member Author

dra27 commented Mar 27, 2024

Yes, I think in my mind the "type gymnastics" test was going to be part of the (dev) build to be sure at all times. Then I used a test stanza and didn't think just to move it to tests! I'll do that 🙂

Copy link
Collaborator

@rjbou rjbou left a comment

Choose a reason for hiding this comment

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

On the idea and the code, LGTM! I've put some comments in the review.
and... what a type gymnastic xD


(** Like [get_opam_raw], but returns the list of updates instead of the new
environment. *)
(** Returns the list of updates from the switch's cache file. *)
val get_opam_raw_updates:
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not sure about removing these ones, they are part of the library (and exported) since a long time.
We can at least add a comment in the ml file that they are not used.

Copy link
Member Author

Choose a reason for hiding this comment

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

Commit removed

src/format/opamTypes.mli Show resolved Hide resolved
src/client/opamConfigCommand.ml Outdated Show resolved Hide resolved
src/state/opamEnv.ml Outdated Show resolved Hide resolved
src/format/opamFile.mli Outdated Show resolved Hide resolved
tests/lib/dune Show resolved Hide resolved
tests/lib/dune Show resolved Hide resolved
@rjbou
Copy link
Collaborator

rjbou commented Apr 5, 2024

Tested locally, it works well. For a CI test, it needs its proper jobs, to have an environment 100% controlled (git, bash, cygwin, etc.), it can't be on reftests.

Makes it slightly easier to run the tests separately.
@dra27
Copy link
Member Author

dra27 commented Apr 7, 2024

For the testing, my feeling was indeed that to do it via reftests would be very contrived. What we might be able to do in CI in general is to put a "poisoned" tar.exe in PATH in a directory after the Visual Studio bin directories. The MSVC build would then fairly naturally test this - if opam puts Cygwin's bin before the Visual Studio directories, link would fail and if it puts it after the poisoned directory, extraction will fail (so a canary-style test rather than a unit test)

src/format/opamTypesBase.ml Outdated Show resolved Hide resolved
Allow the possibility to partition the constructors for environment
updates to have some operations which cannot come from opam files nor be
synthesised to environment files.
The Cygwin environment update moves the directory as far down PATH as
possible without allowing bash, tar, sort or, if installed, git to
become shadowed.
Assume instead that the user will have configured PATH correctly,
knowing that if opam has added Cygwin's bin to PATH, it will have put it
in the correct place.
Copy link
Collaborator

@rjbou rjbou left a comment

Choose a reason for hiding this comment

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

LGTM! Thanks!

@kit-ty-kate
Copy link
Member

Thanks!!

@kit-ty-kate kit-ty-kate merged commit 9941a43 into ocaml:master Apr 8, 2024
29 checks passed
Opam 2.2.0 automation moved this from For beta2 to Done Apr 8, 2024
@dra27 dra27 deleted the bubbling-cygwin branch May 3, 2024 10:31
dra27 added a commit to dra27/opam that referenced this pull request May 3, 2024
Formed part of work on ocaml#5832, but they were not critical, so were
dropped. Possibly worth considering:
- Removal of unused API functions (because supporting them is effort)
- Use of private records is generally more hygienic (and done elsewhere
  already)
@dra27 dra27 mentioned this pull request Jun 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Opam 2.2.0
  
Done
Development

Successfully merging this pull request may close these issues.

prims.c:1619:3: error: missing terminating " character
3 participants