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

Fix ocamlpath order in findlib init #16428

Merged
merged 1 commit into from
Sep 2, 2022

Conversation

SkySkimmer
Copy link
Contributor

Fix #16406

@SkySkimmer SkySkimmer requested a review from a team as a code owner August 29, 2022 11:14
@SkySkimmer
Copy link
Contributor Author

Anyone know how to make a good test for this?
cc @silene @ppedrot @gares

@gares
Copy link
Member

gares commented Aug 29, 2022

I don't have the time, sorry

The way I experience the bug is to run make install and have a plugin installed in ~/.opam/, then change the plugin (adding an assert false), run make, and see things working (since the old copy is found). IMO this is what we should reproduce, but if you start to export OCAMLPATH then you kind of bias the test.

@silene
Copy link
Contributor

silene commented Aug 29, 2022

I think it is impossible to test it in Coq itself. But here is how I tested my patch manually:

foo.ml:

let _ = Mltop.add_known_module "coq-foo.foo"
let () = Printf.printf "foo 1\n%!"

foo.v:

Declare ML Module "coq-foo.foo".

META.coq-foo:

package "foo" (
  directory = "."
  description = "Coq Foo"
  plugin(native) = "foo.cmxs"
)
directory = "."
ocamlfind ocamlopt -package coq-core.toplevel -rectypes -thread -shared foo.ml -o foo.cmxs
coqc -I . foo.v
DIR=$(ocamlfind printconf destdir)/coq-foo
mkdir $DIR
cp foo.cmxs $DIR/
grep -v 'directory *=' META.coq-foo > $DIR/META
coqc foo.v
sed -i -e 's/foo 1/foo 2/' foo.ml
ocamlfind ocamlopt -package coq-core.toplevel -rectypes -thread -shared foo.ml -o foo.cmxs
coqc -I . foo.v

@ejgallego
Copy link
Member

Anyone know how to make a good test for this?
cc @silene @ppedrot @gares

I think you can set the right env variables (see http://projects.camlcity.org/projects/dl/findlib-1.9.5/doc/ref-html/lib/Findlib.html) to have an alternate tree / config for findlib in the test suite which is reproducible.

try Sys.getenv "OCAMLPATH" ^ ocamlpathsep ^ ocamlpath
with Not_found -> ocamlpath in
let env_ocamlpath = try Sys.getenv "OCAMLPATH" :: ml_load_path with Not_found -> ml_load_path in
let env_ocamlpath = String.concat ocamlpathsep (List.rev env_ocamlpath) in
Copy link
Contributor

Choose a reason for hiding this comment

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

As mentioned in the issue, using List.rev is an unfortunate choice, since it causes -I directories to be scanned right-to-left, while the vast majority of compilers (e.g., gcc, ocamlc) use a left-to-right policy.

  • "Directories specified with -I options are scanned in left-to-right order."
  • "Directories added with -I are searched [...] in the order in which they were given on the command line"

@SkySkimmer
Copy link
Contributor Author

I guess we don't document the effect of order for -I so either is technically correct, but shouldn't we keep the past behaviour?

@SkySkimmer
Copy link
Contributor Author

Changed: when passed -I A -I B we produce A:B:$OCAMLPATH:$default_dirs (default_dirs is the list of install locations for the core plugins and other such stuff)

@@ -448,7 +448,12 @@ let build_load_path opts =
else
let coqenv = Boot.Env.init () in
Coqloadpath.init_load_path ~coqenv in
ml_path @ opts.pre.ml_includes ,
let ocamlpathsep = if Sys.unix then ':' else ';' in
let env_ocamlpath =
Copy link
Member

Choose a reason for hiding this comment

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

Didn't we say that when -boot is set, we don't use OCAMLPATH?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is the opposite of what I understood.
-boot is about not binding the stdlib, so it is unrelated to OCAMLPATH

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, OCAMLPATH should always be used (e.g., critical on Nix). Otherwise, dependencies will not be found.

@silene
Copy link
Contributor

silene commented Aug 31, 2022

Changed: when passed -I A -I B we produce A:B:$OCAMLPATH:$default_dirs (default_dirs is the list of install locations for the core plugins and other such stuff)

Will that not break the compilation of Coq when there is already a release of Coq installed on the system? Indeed, the currently compiled Coq will look for its plugins in $OCAMLPATH instead of $default_dirs and thus will find the wrong versions. (I am assuming that the not yet installed plugins are in $default_dirs.) If so, the order should be A:B:$default_dirs:$OCAMLPATH.

@ejgallego
Copy link
Member

@silene compilation of Coq has moved to using less implicit stuff, so indeed the standard library is compiled using-boot and explicit -I paths.

@ejgallego
Copy link
Member

Dune is also scheduled to use -boot for all user developments soon, this allows, among other things, for a crude way to hide selectively what is installed in user-contrib.

@gares
Copy link
Member

gares commented Aug 31, 2022

Isn't dune setting OCAMLPATH to point to the _build directory?

@ejgallego
Copy link
Member

Isn't dune setting OCAMLPATH to point to the _build directory?

Yes, as part of the workspace configuration.

try String.split_on_char ocamlpathsep (Sys.getenv "OCAMLPATH")
with Not_found -> []
in
opts.pre.ml_includes @ env_ocamlpath @ ml_path ,
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it on purpose that the content of $OCAMLPATH is passed to Mltop.add_ml_dir? This seems like a very bad idea.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, I think this part should be reverted until we remove the legacy loading method in 8.17

Copy link
Member

Choose a reason for hiding this comment

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

This point came up at the call, but nobody could find the problem. What is it?

Copy link
Member

Choose a reason for hiding this comment

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

What problem?

Copy link
Member

Choose a reason for hiding this comment

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

the content of $OCAMLPATH is passed to Mltop.add_ml_dir? This seems like a very bad idea.

what is the problem when doing that?

Copy link
Contributor

Choose a reason for hiding this comment

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

The problem is that, on some systems (e.g., Nix), $OCAMLPATH contains the whole world. Thus, when trying to load a legacy plugin, Coq will scan a bunch of directories that are completely unrelated to Coq. (Notice that this pull request scans env_ocamlpath before ml_path, where the legacy plugins lie.) In fact, if by sheer luck Coq were to actually find a plugin with the searched name in one of these directories, it is guaranteed to be a broken one.

Copy link
Member

Choose a reason for hiding this comment

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

OK, then I think @SkySkimmer should avoid this, and that requires changing the API IMO, since you need to separate the paths from OCAMPATH from the others.

I keep the occasion, in case Nix people are listening, to remind that OCAMLPATH is there to let one override the system config, not a place to store it. If they want to stay with env variables, they should add a nix specific one to findlib, eg NIX_OCAMLPATH, and have findlib honor both, giving OCAMLPATH precedence.

Copy link
Contributor

Choose a reason for hiding this comment

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

You only need to change the API if you want $OCAMLPATH to be searched after opts.pre.ml_includes but before ml_path. But why do you even want that in the first place? Why should the Coq directories in ml_path not take precedence over OCAMLPATH?

Copy link
Member

@gares gares Sep 1, 2022

Choose a reason for hiding this comment

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

remind that OCAMLPATH is there to let one override

because of this? (we may even use this in the CI)

Copy link
Member

@Zimmi48 Zimmi48 Sep 1, 2022

Choose a reason for hiding this comment

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

Responding to the off-topic comment:

I keep the occasion, in case Nix people are listening, to remind that OCAMLPATH is there to let one override the system config, not a place to store it. If they want to stay with env variables, they should add a nix specific one to findlib, eg NIX_OCAMLPATH, and have findlib honor both, giving OCAMLPATH precedence.

Nix is using this "trick" in many programming languages that have a PATH environment variable, and has done so successfully for years. If Nix users had had to request changes to most of their programming tools to be able to work, it would have been less successful. The fact that Nix is becoming more and more important and has more and more users does not justify (IMHO) to introduce Nix-specific quirks in generic tools.

@SkySkimmer
Copy link
Contributor Author

changed: findlib sees A:B:$default_dirs:$OCAMLPATH, legacy loading doesn't see OCAMLPATH

@gares
Copy link
Member

gares commented Sep 1, 2022

Hum, this way OCAMLPATH cannot be used to override default_dirs, but just to extend them. Was there a problem with default_dirs being last?

@Zimmi48
Copy link
Member

Zimmi48 commented Sep 1, 2022

Hum, this way OCAMLPATH cannot be used to override default_dirs, but just to extend them. Was there a problem with default_dirs being last?

#16428 (comment)

But I guess, this particular problem was actually resolved by #16428 (comment)

@gares
Copy link
Member

gares commented Sep 1, 2022

Hum, so?

@ejgallego ejgallego self-assigned this Sep 1, 2022
@ejgallego ejgallego added this to the 8.16.0 milestone Sep 1, 2022
@ejgallego ejgallego added the kind: fix This fixes a bug or incorrect documentation. label Sep 1, 2022
@ejgallego ejgallego added the part: build The build system. label Sep 1, 2022
@ejgallego
Copy link
Member

@SkySkimmer adding a test wouldn't hurt, we can simulate a "global" install using the findlib variables, then we can test precedence properly.

@SkySkimmer
Copy link
Contributor Author

If you want to write a test feel free, I don't have quite enough understanding to do it myself.

@ejgallego
Copy link
Member

If you want to write a test feel free, I don't have quite enough understanding to do it myself.

I'll open an issue, I don't have time to write the test now, but happy to sheperd.

@@ -184,6 +184,9 @@ and ``coqtop``, unless stated otherwise:
(``.cmo`` or ``.cmxs``). Subdirectories are not included.
See the command :cmd:`Declare ML Module`.

Directories added with ``-I`` are searched after the current directory,
in the order in which they were given on the command line
Copy link
Contributor

Choose a reason for hiding this comment

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

Since there is some missing punctuation, we might just as well be comprehensive.

Suggested change
in the order in which they were given on the command line
in the order in which they were given on the command line,
before OCaml's default directories.

Copy link
Member

Choose a reason for hiding this comment

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

I think neither comma is needed.

@ejgallego
Copy link
Member

@coqbot: merge now

@coqbot-app coqbot-app bot merged commit 6d2a9f2 into coq:master Sep 2, 2022
ppedrot added a commit to ppedrot/coq that referenced this pull request Sep 2, 2022
ppedrot added a commit to ppedrot/coq that referenced this pull request Sep 4, 2022
@SkySkimmer SkySkimmer deleted the ocamlpath-order branch September 5, 2022 08:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: fix This fixes a bug or incorrect documentation. part: build The build system.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Incorrect search order of plugins for Findlib
7 participants