ocaml / dune

A composable build system for OCaml.
https://dune.build/
MIT License
1.63k stars 409 forks source link

Undesired conflict between vendored library and public library by the same name #4070

Open fpottier opened 3 years ago

fpottier commented 3 years ago

Expected Behavior

Hi, my scenario is this. In Menhir's repository, I have included a copy of the library pprint, and have designated it as "vendored".

(For the record, I am doing this because I want to avoid declaring a dependency of Menhir on pprint. If the dependency required a specific version of pprint, then that might be inconvenient for the end user, and if it did not require a specific version, then I would lose control over exactly what code is being compiled, something I want to avoid. Plus, I prefer to avoid all dependencies altogether.)

Now, one of Menhir's tests requires the external library sek, which itself happens to depend on pprint.

This test can be built by typing make speed at the root of Menhir's repository.

I would naively expect that this test can be built by using two copies of pprint (the one that is vendored inside Menhir, and the one that exists on the system and that is used to build sek). Because the Menhir executable and the test executable are distinct, the two libraries would not even end up linked together inside the same executable.

Actual Behavior

In practice, this fails with the following message:

master $ make speed
Error: Conflict between the following libraries:
- "pprint" in _build/default/pprint/src
- "pprint" in /Users/fpottier/.opam/4.11.1/lib/pprint
  -> required by library "sek" in /Users/fpottier/.opam/4.11.1/lib/sek
-> required by executable gene in test/dynamic/speed/src/code/dune:9

I tried making the vendored pprint private, by removing (public_name pprint) from its dune file, but that does not work; it causes the vendored library to become effectively invisible.

Is there support in Dune for what I am trying to achieve? How should I go about it? Thanks!

PS: It comes to my mind that if I renamed the vendored pprint to some other name, say vendored_pprint, then the conflict should disappear. But I would prefer to avoid this ugly workaround if possible.

ejgallego commented 3 years ago

My understanding is that vendoring libraries inside libraries is still not properly supported, as indeed that seems like a worrying thing to do in general due to lack of sharing on the ecosystem, see discussion in https://github.com/ocaml/dune/issues/3335 ; this may change in the future.

As of today you need to perform some mangling manually as you hint in the last paragraph, but one has to be careful as there could be problems linking the same library twice due to resources, etc...

fpottier commented 3 years ago

Thanks @ejgallego for your reply and for pointing to this other thread! Note that I am not vendoring in a library in a library (I think). I am only vendoring a library (pprint) inside an executable (Menhir).

ejgallego commented 3 years ago

You have a pointer to a tree so we could have a look?

fpottier commented 3 years ago

Sure, git clone git@gitlab.inria.fr:fpottier/menhir.git, then cd menhir && make speed.

ejgallego commented 3 years ago

Thanks! I'm not expert in this part of the code, but see https://github.com/ocaml/dune/pull/587

You can thus use:

(executable
  (name gene)
  (allow_overlapping_dependencies)
  (libraries unix sek menhirLib)
)

to avoid this check, so not really related to vendoring but to the lib db checks.

You need to add it to the 3 executables :/

ejgallego commented 3 years ago

[unrelated comment on make speed, why do you use --force? Do the rule / dune setup fail to rerun the test when the deps change ?]

fpottier commented 3 years ago

I have gone ahead and renamed my vendored library from pprint to vendored_pprint, so the conflict detected by Dune is now avoided. I have done the same for a couple other libraries that are vendored inside Menhir. This is not great, but works, for now.