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

Dependency error with "dune -p" and "infer true" for menhir #1504

Closed
grayswandyr opened this issue Oct 25, 2018 · 25 comments · Fixed by ocaml/opam-repository#13444
Closed

Dependency error with "dune -p" and "infer true" for menhir #1504

grayswandyr opened this issue Oct 25, 2018 · 25 comments · Fixed by ocaml/opam-repository#13444

Comments

@grayswandyr
Copy link

Hello,
I have an issue that I think comes from Dune (well at least an error message in its source code). The code in question is at: https://github.com/grayswandyr/electrod/tree/release/0.2.0
It happens on 4.07.1 while it compiles well on 4.06.1 for instance, I had never encountered this essage with Jbuilder/Dune on previous major releases of OCaml (I haven't tested 4.07.0). The error message says:

Module Parser in directory _build/default/src depends on Libelectrod.
This doesn't make sense to me.

Libelectrod is the main module of the library and is the only module exposed 
outside of the library. Consequently, it should be the one depending 
on all the other modules in the library.

Alas, this message doesn't really make sens to me either ;-)
Any help appreciated!

grayswandyr added a commit to grayswandyr/opam-repository that referenced this issue Oct 27, 2018
Remove 4.07 as a possible platform, due to an issue with 4.07 or Dune that I don't understand.
See ocaml/dune#1504
@grayswandyr
Copy link
Author

OK so I was wrong, it doesn't come from 4.07.1. Actually it happens when the infer option of menhir is true and dune is called with -p. If, for the code linked above, the dune file contains (infer false) for the first and third Menhir rules, then the build succeeds; otherwise it fails with -p and succeeds without it.
(I renamed this issue.)

@grayswandyr grayswandyr changed the title Dependency error not present in 4.06.1 and before Dependency error with "dune -p" and "infer true" for menhir Oct 27, 2018
@ghost
Copy link

ghost commented Oct 29, 2018

I can't reproduce this issue. I'm using dune 1.4.0 and menhir 20181026. The following works for me:

$ git rev-parse HEAD
4f140068122bf00923161145f65944f500be1dc0
$ dune build -p electrod

@grayswandyr
Copy link
Author

grayswandyr commented Oct 29, 2018

Ouch. This is what I get:

$ dune --version
1.4.0
$ make clean 
$ opam switch
#  switch   compiler                    description
   4.06.1   ocaml-base-compiler.4.06.1  4.06.1
→  4.07.1   ocaml-base-compiler.4.07.1  4.07.1
   default  ocaml-system.4.05.0         default
$ git rev-parse HEAD
4f140068122bf00923161145f65944f500be1dc0
$ make clean
$ opam update

<><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><>
[default] no changes from https://opam.ocaml.org
$ opam upgrade -y
Already up-to-date.
Nothing to do.
$ dune build -p electrod 
Module Parser in directory _build/default/src depends on Libelectrod.
This doesn't make sense to me.

Libelectrod is the main module of the library and is the only module exposed 
outside of the library. Consequently, it should be the one depending 
on all the other modules in the library.
$ vi src/dune // adding infer false
$ git diff
diff --git a/src/dune b/src/dune
index b3a4d85..428d743 100644
--- a/src/dune
+++ b/src/dune
@@ -48,7 +48,7 @@
 
 ;;; Electrod parser
 
-(menhir (modules Parser))
+(menhir (infer false) (modules Parser))
 
 ;;; SMV trace parser
 
@@ -57,6 +57,7 @@
   (modules Smv_trace_tokens))
 
 (menhir 
+ (infer false)
  (merge_into Smv_trace_parser)
   (flags (--external-tokens Smv_trace_tokens))
   (modules Smv_trace_parser Smv_trace_tokens))
$ make clean
$ dune build -p electrod // OK
$

@ghost
Copy link

ghost commented Oct 30, 2018

I can reproduce this with 4.06.1 but not with 4.07.1, so this seems indeed linked to the version of the compiler. Looking at the diff between Parser.ml generated with 4.06.1 and 4.07.1, the former produces references to Libelectrod__Gen_goal.block while the latter produces references to Libelectrod.Gen_goal.block. Ideally, it should produce a reference to Gen_goal.block. Not sure how to fix this issue :/

@grayswandyr
Copy link
Author

So I guess it must be types inferred by Menhir piggybacking on the compiler, right? We should perhaps Cc François Pottier?
Meanwhile, I can always add infer false to create my OPAM packages to have them pass linting. IIUC, inference is only useful at development time anyway and only serves to provide the developer with better error messages. As of now, my parser works correctly so that's OK for the time being.

@ghost
Copy link

ghost commented Oct 30, 2018

Basically menhir reads the output of ocamlc -i and in this case the output of ocamlc -i contains references to Libelectrod.Gen_goal and these are not allowed. What I don't understand is why the path is not shortened to Gen_goal by ocamlc -i because of -short-paths. This looks like a bug in the compiler.

@grayswandyr
Copy link
Author

At any rate, I can't reproduce the part where I said that the bug only happens with the -p option.
OTOH I confirm that it works for me with 4.06.1 and not 4.07.1, so oddly enough the converse of your own testing.

@ghost
Copy link

ghost commented Oct 31, 2018

Actually, I observe the same as you:

  • the build succeeds with 4.06.1
  • the build fails with 4.07.1

@ghost
Copy link

ghost commented Oct 31, 2018

BTW, a workaround is to write the following at the beginning of Parser.mly:

module Libelectrod = struct end

@grayswandyr
Copy link
Author

Good idea! However the problem is still here with the Smv_trace_parser and this one creates a functorized parser for with the workaround doesn't seem to work out of the box. I don't have time to investigate, so meanwhile I'll stick to my infer false solution. Thanks for your help.
Now I guess other people are likely to encounter the same problem but I don't know the compiler enough to look into this.

@ifazk
Copy link

ifazk commented Nov 15, 2018

I've run into the same issue, but with 4.07.0+flambda and dune 1.5.1. Running dune rules shows some weird dependencies for building the inferred mli (my module's name is Parse instead of Libelectrod).

((deps
  ((paths
    ((External /home/ikabir/.opam/4.07.0+flambda/bin/ocamlc.opt)
     ...
     (In_build_dir default/src/parse/.parse.objs/parse.cmi)
     (In_build_dir default/src/parse/.parse.objs/parse__Position.cmi)
     (In_build_dir default/src/parse/.parse.objs/parse__Types.cmi)
     (In_build_dir default/src/parse/parser__mock.ml.pp.mock)))
   (vars ())))
 (targets ((In_build_dir default/src/parse/parser__mock.mli.inferred)))
 (context default)
 (action
  (chdir
   _build/default
   (with-stdout-to
    src/parse/parser__mock.mli.inferred
    (chdir
     .
     (run
      /home/ikabir/.opam/4.07.0+flambda/bin/ocamlc.opt
      -w
      @a-4-29-40-41-42-44-45-48-58-59-60-40
      -strict-sequence
      -strict-formats
      -short-paths
      -keep-locs
      -g
      -I
      src/parse/.parse.objs
      -I
      ...
      -open
      Parse
      -i
      -impl
      src/parse/parser__mock.ml.pp.mock))))))

The two parts that seem incorrect to me are are:

  • (In_build_dir default/src/parse/.parse.objs/parse.cmi) in the dependencies
  • -open Parse in the action

@ghost
Copy link

ghost commented Nov 15, 2018

This needs to be reported on the OCaml bug tracker, as this seems to be a bug in -short-paths

@ifazk
Copy link

ifazk commented Nov 15, 2018

@diml, are you going to report it? If not, can you give us a bit more information about how dune uses -short-paths and what is going wrong so that we can report it?

@ghost
Copy link

ghost commented Nov 19, 2018

@ifazk if you could report it that would be cool. The problem is the following: in parser.mly, the code references a module X. X is an alias defined in lib__.ml as follow:

module X = Lib__X

and the Lib__ module is implicitly opened when compiling any file of the library. Menhir produces a .ml file from parser.mly that contains the user code mentioning X, for instance it might be referencing a type X.t. Menhir calls ocamlc -i -open Lib__ ... on this file and reads the output. It is expected that the output of ocamlc -i still references X.t. This is the case with OCaml < 4.07. However, with 4.07, it references Lib.X instead. This is an issue as such references to the Lib module are not allowed from inside the library.

@ifazk
Copy link

ifazk commented Nov 30, 2018

Sorry for the delayed follow up, but I have been trying to create a minimal example that show the differences between < 4.07 and >= 4.07. Here's what i have:

(* lib__m2.mli *)
type t
(* lib__m2.ml *)
type t = int
(* lib__.ml *)
module M2 = Lib__m2
(* parser.ml *)
type t = M2.t

Now when i run the following for both 4.06.1 and 4.07.0,

ocamlc -c lib__m2.mli lib__m2.ml lib__.ml
ocamlc -i -open Lib__ parser.ml

I get same the output

type t = Lib__.M2.t

Should I be doing something else for Lib__ to not be displayed in 4.06?

@ghost
Copy link

ghost commented Dec 3, 2018

can you try with -short-paths?

@ifazk
Copy link

ifazk commented Dec 21, 2018

Some updates:

  • I have been running into the issue for both 4.06.1 and 4.07.1 when using dune 1.6.2 and menhir 20181113.
  • Builds work under --profile dev but not under --profile release. See https://github.com/ifazk/itis/tree/dune for an example project where dune build --profile dev @install works, but dune build --profile release @install does not (for 4.06.0, 4.06.1, 4.07.0, and 4.07.1 with latest packages).
  • I wasn't able to trigger the -short-paths bug manually. See below for details.

Setup (same as before):

(* lib__m2.mli *)
type t
(* lib__m2.ml *)
type t = int
(* lib__.ml *)
module M2 = Lib__m2
(* parser.ml *)
type t = M2.t

I get the same results for both 4.06.1 and 4.07.1:

ocamlc -c lib__m2.mli lib__m2.ml lib__.ml
ocamlc -i -open Lib__ parser.ml
type t = Lib__.M2.t
ocamlc -c lib__m2.mli lib__m2.ml lib__.ml
ocamlc -i -short-paths -open Lib__ parser.ml
type t = M2.t
ocamlc -c -short-paths lib__m2.mli lib__m2.ml lib__.ml
ocamlc -i -short-paths -open Lib__ parser.ml
type t = M2.t

@ghost
Copy link

ghost commented Jan 7, 2019

I've lost track of this conversation, the problem only appears when the infer mode is selected, right? Maybe we should just disable infer by default. /cc @fpottier

@grayswandyr
Copy link
Author

Alas, the effect of this option is very useful and I seem to remember it was strongly encouraged to be set to true in the Menhir manual. Now Menhir was recently updated on this front with other related options so I guess indeed @fpottier could be of some help here.

@ifazk
Copy link

ifazk commented Jan 7, 2019

For me, the problem only appears when I try to build with --profile release, so I'm not convinced that this is necessarily a infer mode problem. Building with --profile dev works under current defaults.

@ghost
Copy link

ghost commented Jan 7, 2019

@ifazk, the conclusion I draw from your results is that the issue is related to -short-paths. Note that -short-paths is used by default with --profile dev but not with --profile release.

@ghost
Copy link

ghost commented Jan 7, 2019

Maybe we could always pass -short-paths when calling ocamlc -i. Could you try with the following patch:

diff --git a/src/module_compilation.ml b/src/module_compilation.ml
index 40903b72..fd6a449d 100644
--- a/src/module_compilation.ml
+++ b/src/module_compilation.ml
@@ -214,6 +214,7 @@ let ocamlc_i ?sandbox ?(flags=[]) ~dep_graphs cctx (m : Module.t) ~output =
           | Some (m : Module.t) ->
             As ["-open"; Module.Name.to_string (Module.name m)])
        ; As flags
+       ; A "-short-paths"
        ; A "-i"; Ml_kind.flag Impl; Dep src
        ]
      >>^ (fun act -> Action.with_stdout_to output act)

?

@ifazk
Copy link

ifazk commented Jan 7, 2019

The patch worked for my project!

@fpottier
Copy link
Collaborator

fpottier commented Jan 7, 2019

@diml's last suggestion sounds reasonable to me (although I don't really know what -short-paths is supposed to do). Ideally, infer mode should remain enabled by default.

@ghost
Copy link

ghost commented Jan 7, 2019

@fpottier, when several names are available for a given type, -short-paths causes the compiler to choose the nicest one, which is often the shortest one. So for instance if the compiler has the choice between Lib__.M2.t and M2.t, whith -short-paths it will print M2.t while without -short-paths the choice depend on internal implementation details and is likely to not be the one the user would like to see. -short-paths should really be the default, though it used to be slow and in some cases it was making unexpected choices.

I'll create a PR with the suggested patch.

@ghost ghost closed this as completed in #1743 Jan 7, 2019
ghost pushed a commit that referenced this issue Jan 7, 2019
Fixes #1504

Signed-off-by: Jeremie Dimino <jeremie@dimino.org>
rgrinberg pushed a commit that referenced this issue Jan 8, 2019
Fixes #1504

Signed-off-by: Jeremie Dimino <jeremie@dimino.org>
rgrinberg added a commit to rgrinberg/opam-repository that referenced this issue Jan 8, 2019
CHANGES:

- Fix merlin handling of private module visibility (ocaml/dune#1653 @bobot)

- skip directories when looking up programs in the PATH (ocaml/dune#1628, fixes
  ocaml/dune#1616, @diml)

- Fix preprocessing for libraries with `(include_subdirs ..)` (ocaml/dune#1624, fix ocaml/dune#1626,
  @nojb, @rgrinberg)

- Do not generate targets for archive that don't match the `modes` field.
  (ocaml/dune#1632, fix ocaml/dune#1617, @rgrinberg)

- When executing actions, open files lazily and close them as soon as
  possible in order to reduce the maximum number of file descriptors
  opened by Dune (ocaml/dune#1635, ocaml/dune#1643, fixes ocaml/dune#1633, @jonludlam, @rgrinberg,
  @diml)

- Do not generate targets for archive that don't match the `modes` field.
  (ocaml/dune#1632, fix ocaml/dune#1617, @rgrinberg)

- Get the correct environment node for multi project workspaces (ocaml/dune#1648,
  @rgrinberg)

- Fix an issue causing menhir generated parsers to fail to build in
  some cases. The fix is to systematically use `-short-paths` when
  calling `ocamlc -i` (ocaml/dune#1743, fix ocaml/dune#1504, @diml)
rgrinberg added a commit to rgrinberg/opam-repository that referenced this issue Jan 9, 2019
CHANGES:

- Fix merlin handling of private module visibility (ocaml/dune#1653 @bobot)

- skip directories when looking up programs in the PATH (ocaml/dune#1628, fixes
  ocaml/dune#1616, @diml)

- Fix preprocessing for libraries with `(include_subdirs ..)` (ocaml/dune#1624, fix ocaml/dune#1626,
  @nojb, @rgrinberg)

- Do not generate targets for archive that don't match the `modes` field.
  (ocaml/dune#1632, fix ocaml/dune#1617, @rgrinberg)

- When executing actions, open files lazily and close them as soon as
  possible in order to reduce the maximum number of file descriptors
  opened by Dune (ocaml/dune#1635, ocaml/dune#1643, fixes ocaml/dune#1633, @jonludlam, @rgrinberg,
  @diml)

- Do not generate targets for archive that don't match the `modes` field.
  (ocaml/dune#1632, fix ocaml/dune#1617, @rgrinberg)

- Get the correct environment node for multi project workspaces (ocaml/dune#1648,
  @rgrinberg)

- Fix an issue causing menhir generated parsers to fail to build in
  some cases. The fix is to systematically use `-short-paths` when
  calling `ocamlc -i` (ocaml/dune#1743, fix ocaml/dune#1504, @diml)
rgrinberg added a commit to rgrinberg/opam-repository that referenced this issue Feb 12, 2019
CHANGES:

- Second step of the deprecation of jbuilder: the `jbuilder` binary
  now emits a warning on every startup and both `jbuilder` and `dune`
  emit warnings when encountering `jbuild` files (ocaml/dune#1752, @diml)

- Change the layout of build artifacts inside _build. The new layout enables
  optimizations that depend on the presence of `.cmx` files of private modules
  (ocaml/dune#1676, @bobot)

- Fix merlin handling of private module visibility (ocaml/dune#1653 @bobot)

- unstable-fmt: use boxes to wrap some lists (ocaml/dune#1608, fix ocaml/dune#1153, @emillon,
  thanks to @rgrinberg)

- skip directories when looking up programs in the PATH (ocaml/dune#1628, fixes
  ocaml/dune#1616, @diml)

- Use `lsof` on macOS to implement `--stats` (ocaml/dune#1636, fixes ocaml/dune#1634, @xclerc)

- Generate `dune-package` files for every package. These files are installed and
  read instead of `META` files whenever they are available (ocaml/dune#1329, @rgrinberg)

- Fix preprocessing for libraries with `(include_subdirs ..)` (ocaml/dune#1624, fix ocaml/dune#1626,
  @nojb, @rgrinberg)

- Do not generate targets for archive that don't match the `modes` field.
  (ocaml/dune#1632, fix ocaml/dune#1617, @rgrinberg)

- When executing actions, open files lazily and close them as soon as
  possible in order to reduce the maximum number of file descriptors
  opened by Dune (ocaml/dune#1635, ocaml/dune#1643, fixes ocaml/dune#1633, @jonludlam, @rgrinberg,
  @diml)

- Reimplement the core of Dune using a new generic memoization system
  (ocaml/dune#1489, @rudihorn, @diml)

- Replace the broken cycle detection algorithm by a state of the art
  one from [this paper](https://doi.org/10.1145/2756553) (ocaml/dune#1489,
  @rudihorn)

- Get the correct environment node for multi project workspaces (ocaml/dune#1648,
  @rgrinberg)

- Add `dune compute` to call internal memoized functions (ocaml/dune#1528,
  @rudihorn, @diml)

- Add `--trace-file` option to trace dune internals (ocaml/dune#1639, fix ocaml/dune#1180, @emillon)

- Add `--no-print-directory` (borrowed from GNU make) to suppress
  `Entering directory` messages. (ocaml/dune#1668, @dra27)

- Remove `--stats` and track fd usage in `--trace-file` (ocaml/dune#1667, @emillon)

- Add virtual libraries feature and enable it by default (ocaml/dune#1430 fixes ocaml/dune#921,
  @rgrinberg)

- Fix handling of Control+C in watch mode (ocaml/dune#1678, fixes ocaml/dune#1671, @diml)

- Look for jsoo runtime in the same dir as the `js_of_ocaml` binary
  when the ocamlfind package is not available (ocaml/dune#1467, @nojb)

- Make the `seq` package available for OCaml >= 4.07 (ocaml/dune#1714, @rgrinberg)

- Add locations to error messages where a rule fails to generate targets and
  rules that require files outside the build/source directory. (ocaml/dune#1708, fixes
  ocaml/dune#848, @rgrinberg)

- Let `Configurator` handle `sizeof` (in addition to negative numbers).
  (ocaml/dune#1726, fixes ocaml/dune#1723, @Chris00)

- Fix an issue causing menhir generated parsers to fail to build in
  some cases. The fix is to systematically use `-short-paths` when
  calling `ocamlc -i` (ocaml/dune#1743, fix ocaml/dune#1504, @diml)

- Never raise when printing located errors. The code that would print the
  location excerpts was prone to raising. (ocaml/dune#1744, fix ocaml/dune#1736, @rgrinberg)

- Add a `dune upgrade` command for upgrading jbuilder projects to Dune
  (ocaml/dune#1749, @diml)

- When automatically creating a `dune-project` file, insert the
  detected name in it (ocaml/dune#1749, @diml)

- Add `(implicit_transitive_deps <bool>)` mode to dune projects. When this mode
  is turned off, transitive dependencies are not accessible. Only listed
  dependencies are directly accessible. (ocaml/dune#1734, ocaml/dune#430, @rgrinberg, @hnrgrgr)

- Add `toplevel` stanza. This stanza is used to define toplevels with libraries
  already preloaded. (ocaml/dune#1713, @rgrinberg)

- Generate `.merlin` files that account for normal preprocessors defined using a
  subset of the `action` language. (ocaml/dune#1768, @rgrinberg)

- Emit `(orig_src_dir <path>)` metadata in `dune-package` for dune packages
  built with `--store-orig-source-dir` command line flag (also controlled by
  `DUNE_STORE_ORIG_SOURCE_DIR` env variable). This is later used to generate
  `.merlin` with `S`-directives pointed to original source locations and thus
  allowing merlin to see those. (ocaml/dune#1750, @andreypopp)

- Improve the behavior of `dune promote` when the files to be promoted have been
  deleted. (ocaml/dune#1775, fixes ocaml/dune#1772, @diml)

- unstable-fmt: preserve comments (ocaml/dune#1766, @emillon)

- Pass flags correctly when using `staged_pps` (ocaml/dune#1779, fixes ocaml/dune#1774, @diml)

- Fix an issue with the use of `(mode promote)` in the menhir
  stanza. It was previously causing intermediate *mock* files to be
  promoted (ocaml/dune#1783, fixes ocaml/dune#1781, @diml)

- unstable-fmt: ignore files using OCaml syntax (ocaml/dune#1784, @emillon)

- Configurator: Add `which` function to replace the `which` command line utility
  in a cross platform way. (ocaml/dune#1773, fixes ocaml/dune#1705, @Chris00)

- Make configurator append paths to `$PKG_CONFIG_PATH` on macOS. Previously it
  was prepending paths and thus `$PKG_CONFIG_PATH` set by users could have been
  overridden by homebrew installed libraries (ocaml/dune#1785, @andreypopp)

- Disallow c/cxx sources that share an object file in the same stubs archive.
  This means that `foo.c` and `foo.cpp` can no longer exist in the same library.
  (ocaml/dune#1788, @rgrinberg)

- Forbid use of `%{targets}` (or `${@}` in jbuild files) inside
  preprocessing actions
  (ocaml/dune#1812, fixes ocaml/dune#1811, @diml)

- Add `DUNE_PROFILE` environment variable to easily set the profile. (ocaml/dune#1806,
  @rgrinberg)

- Deprecate the undocumented `(no_keep_locs)` field. It was only
  necessary until virtual libraries were supported (ocaml/dune#1822, fix ocaml/dune#1816,
  @diml)

- Rename `unstable-fmt` to `format-dune-file` and remove its `--inplace` option.
  (ocaml/dune#1821, @emillon).

- Autoformatting: `(using fmt 1.1)` will also format dune files (ocaml/dune#1821, @emillon).

- Autoformatting: record dependencies on `.ocamlformat-ignore` files (ocaml/dune#1824,
  fixes ocaml/dune#1793, @emillon)
This issue was closed.
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 a pull request may close this issue.

3 participants