Dune - full path in libraries and modules

I am building an executable which depends on 3rd party somefile.ml. I want to do something like this:

(executable
  (name test)
  (modules test ../../lib/somefile))

Unfortunately, this does not work. The error is:

Error: Module …/…/lib/somefile doesn’t exist. I also tried to make it into a library with (wrapped fasle):

(executable
  (name test)
  (libraries extracted core .../../lib/)
  (modes byte))

Which also does not work. Any workarounds?

1 Like

Note that the libraries field only accepts library names. You will not be able to use module names or file paths in that field.

The best workaround for your problem is to use the copy_file# stanza. For example:

(copy_file# ../../lib/somefile)

Thanks. It will work for a single file.

I do not see why libraries stanza enforces local path. If I have a folder foo with the following dune file:

(library
(name foo)
(wrapped false))

I can use it as (libraries foo) when it is local, but not as (libraries ../../foo) if it happens to reside elsewhere.
It is a limitation.

Is copy_file# part of dune-1.2.1? I could not fund it in documentation and trying to use it does not work.

libraries does not enforce any local paths. It does not work with paths at all. Briefly, libraries accepts names that were set either in the name or public_name field of libraries. However, the name field will only be available in the scope of the library (the .opam file defines that).

If you would like to include libraries defined in another project on your file system, you can simply symlink the directory where that library is defined into your project by the way. It does not make so much to copy modules from external libraries.

I made it a mistake, it is actually called (copy_files# ..) and it also accepts globs if you would like to copy multiple files.

(executable
  (name test)
  (copy_files#  ../lib/file.ml)

Gives me:

Error: Unknown field copy_files#

Note that I stated that copy_files# is a stanza. That’s like a top-level command in a dune file. So it should be:

(copy_files# ../lib/file.ml)

(executable (name test))
1 Like

Thanks! We are making some progress here :slight_smile: Now I am hitting this error:

Error: path outside the workspace: ../lib/file.ml from .

Could you describe your problem a bit more by the way? Are you trying to import a source from the same project? Or is it a different project? By project, I mean a dune-project here.

If you’re importing a library from a different project, I recommend that you either:

  1. Create a workspace that would include both projects. This would mean having a dir structure like:
ls workspace/
 proj1/
 proj2/
  1. Simply symlink proj2 into you proj1.

There is a project called Vellvm, which generates some OCaml code from Coq. It’s OCaml source includes:

  1. Auto-generated code (during build)
  2. Library code llvm_printer.ml
  3. Sample main/testing code

I switched it from ocamlbuld to dune. The pull request is pending and they are about to merge it. https://github.com/vzaliva/vellvm/tree/dune

Now, there is another project, HELIX, which wants to use Vellvm as a library. https://github.com/vzaliva/helix/tree/LLVM It also generates some OCaml code from Coq and using dune.
Right now it assumes that vellvm will be a git submodule (or symlink) under lib.

HELIX Coq code depends on Vellvm Coq code. This works pretty well. When generating ML code, it creates files ml/extracted. Vellvm Coq code is re-used and re-extracted as ML here. So far so good.

Now I am trying to find a way to have some additional OCaml code from Vellvm re-usable in projects like HELIX. Currently, it is just llvm_printer.ml but there might be more in the future. The directory structure is:

HELIX/
     + lib/
          + vellvm/
             + src/
                 +ml/
                    dune-project
                    dune
                    llvm_printer.ml
                    extracted/
                      dune
                      *.ml
                    main.ml
  + ml/
      dune-project
      dune
      extracted/
          dune
          *.ml
      test.ml

One of the problems is that llvm_printer.ml depends on some modules from extracted. Luckily they are the same in both Vellvm and HELIX as they generated from the same Vellvm Coq code.

One reason I’ve chosen to use dune here is the promise of composable builds. But I may have misunderstood the limitations…

In dune, the unit of composition of rules is the directory. So dune will discover all rules in starting from a root (workspace or project) and will have a unified view of the build in terms of libraries, executables, etc. However, the unit of sharing code is the library. So if you want your llvm_printer.ml source to be re-usable it must be in some library. Once you define this library (using the library stanza), it will be usable in HELIX it will be usable under the public_name you give this library. This is provided that you’re in a workspace that includes both projects of course. That is usually easy enough to arrange using symlinks or just putting related projects in root directory.