This commit is contained in:
swrup 2025-11-11 02:07:51 +01:00
parent aa2ff7b2f0
commit 2f3113f55d
11742 changed files with 1223940 additions and 0 deletions

View file

@ -0,0 +1,3 @@
(rule
(alias default)
(action (run ./exe/test.exe)))

View file

@ -0,0 +1,3 @@
(executable
(name test)
(libraries foolib))

View file

@ -0,0 +1,3 @@
let () =
Foolib.Foo.Bar.run ();
Foolib.Foo.A.B.run ()

View file

@ -0,0 +1,3 @@
(include_subdirs qualified)
(library (name foolib))

View file

@ -0,0 +1 @@
let run () = print_endline "hello from nested module B"

View file

@ -0,0 +1 @@
let run () = print_endline "hello from nested module bar"

View file

@ -0,0 +1,27 @@
Basic test showcasing the feature. Every directory creates a new level of aliasing.
$ dune build
hello from nested module bar
hello from nested module B
$ find _build -iname "*.ml-gen" | sort | while read file; do echo "contents of $file"; cat $file; echo "--------"; done;
contents of _build/default/lib/foolib.ml-gen
(* generated by dune *)
(** @canonical Foolib.Foo *)
module Foo = Foolib__Foo
--------
contents of _build/default/lib/foolib__Foo.ml-gen
(* generated by dune *)
(** @canonical Foolib.Foo.A *)
module A = Foolib__Foo__A
(** @canonical Foolib.Foo.Bar *)
module Bar = Foolib__Foo__Bar
--------
contents of _build/default/lib/foolib__Foo__A.ml-gen
(* generated by dune *)
(** @canonical Foolib.Foo.A.B *)
module B = Foolib__Foo__A__B
--------

View file

@ -0,0 +1,19 @@
$ cat >dune-project <<EOF
> (lang dune 3.7)
> EOF
$ cat >dune <<EOF
> (include_subdirs qualified)
> (executable
> (name foo))
> EOF
$ mkdir -p bar/baz/ baz/
$ touch bar/baz/baz.ml baz/bar.ml
$ cat >foo.ml <<EOF
> module X = Baz.Bar
> module Y = Bar.Baz
> EOF
$ dune exec ./foo.exe

View file

@ -0,0 +1,39 @@
When (include_subdirs qualified) is enabled, we should forbid the same module
to be defined by both a normal compilation unit and a directory of modules
$ cat >dune-project <<EOF
> (lang dune 3.7)
> EOF
$ cat >dune <<EOF
> (include_subdirs qualified)
> (executable
> (name foo))
> EOF
$ cat >foo.ml <<EOF
> module X = Mod
> EOF
$ touch mod.ml
$ mkdir mod
$ touch mod/baz.ml
$ dune build foo.exe
File "dune", line 1, characters 0-0:
Error: The following module and module group cannot co-exist in the same
executable or library because they correspond to the same module path
- module mod.ml
- module group mod/
[1]
Another type of overlap:
$ rm mod/baz.ml
$ touch mod/mod.ml
$ dune build foo.exe
File "dune", line 1, characters 0-0:
Error: The following module and module group cannot co-exist in the same
executable or library because they correspond to the same module path
- module mod.ml
- module group mod/
[1]

View file

@ -0,0 +1,39 @@
It should be possible to install sources with the same file name when
(include_subirs qualified) is used
$ cat >dune-project <<EOF
> (lang dune 3.7)
> (package
> (name foo))
> EOF
$ cat >dune <<EOF
> (include_subdirs qualified)
> (library
> (public_name foo))
> EOF
First we test the case without any sources. To make sure we can at least
install empty libraries.
$ dune build foo.install
Now we add some source with duplicate base names and test again:
$ mkdir bar
$ touch baz.ml bar/baz.ml
$ dune build foo.install
$ cat _build/default/foo.install | grep .ml
"_build/install/default/lib/foo/bar/bar.ml" {"bar/bar.ml"}
"_build/install/default/lib/foo/bar/baz.ml" {"bar/baz.ml"}
"_build/install/default/lib/foo/baz.ml"
"_build/install/default/lib/foo/foo.ml"
$ cat _build/install/default/lib/foo/dune-package | grep ".ml"
bar/bar.ml
bar/baz.ml
baz.ml
foo.ml
(source (path Foo) (impl (path foo.ml-gen))))
(source (path Bar Bar) (impl (path foo__Bar.ml-gen))))
(source (path Bar Baz) (impl (path bar/baz.ml))))))
(source (path Baz) (impl (path baz.ml))))))

View file

@ -0,0 +1,31 @@
We shouldn't allow foo/y/$x.ml to depend on foo/foo.ml
$ cat > dune-project << EOF
> (lang dune 3.7)
> EOF
$ cat > dune << EOF
> (include_subdirs qualified)
> (library
> (name foo))
> EOF
$ mkdir -p x/y
$ touch x/x.ml
$ cat >x/y/z.ml <<EOF
> let () = X.f
> EOF
$ dune build
Error: Module Z in directory _build/default depends on X.
This doesn't make sense to me.
X 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.
-> required by _build/default/.foo.objs/foo__X__Y__Z.impl.all-deps
-> required by _build/default/.foo.objs/byte/foo__X__Y__Z.cmo
-> required by _build/default/foo.cma
-> required by alias all
-> required by alias default
[1]

View file

@ -0,0 +1,31 @@
We shouldn't allow foo/$x.ml to depend on foo/foo.ml
$ cat > dune-project << EOF
> (lang dune 3.7)
> EOF
$ cat > dune << EOF
> (include_subdirs qualified)
> (library
> (name foo))
> EOF
$ mkdir baz
$ touch baz/baz.ml
$ cat >baz/bar.ml <<EOF
> let () = Baz.f
> EOF
$ dune build
Error: Module Bar in directory _build/default depends on Baz.
This doesn't make sense to me.
Baz 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.
-> required by _build/default/.foo.objs/foo__Baz__Bar.impl.all-deps
-> required by _build/default/.foo.objs/byte/foo__Baz__Bar.cmo
-> required by _build/default/foo.cma
-> required by alias all
-> required by alias default
[1]

View file

@ -0,0 +1,24 @@
We should forbid lib interfaces modules from depending on themselves:
$ cat > dune-project << EOF
> (lang dune 3.7)
> EOF
$ cat > dune << EOF
> (include_subdirs qualified)
> (library
> (name foo))
> EOF
$ cat > foo.ml <<EOF
> let () = Foo.f ()
> EOF
$ touch bar.ml
$ dune build @check
File "foo.ml", line 1, characters 9-14:
1 | let () = Foo.f ()
^^^^^
Error: Unbound module Foo
[1]

View file

@ -0,0 +1,3 @@
(rule
(alias default)
(action (run ./exe/test.exe)))

View file

@ -0,0 +1,3 @@
(executable
(name test)
(libraries foolib))

View file

@ -0,0 +1,3 @@
let () =
Foolib.Foo.Bar.run ();
Foolib.Foo.A.B.run ()

View file

@ -0,0 +1,5 @@
(include_subdirs qualified)
(library
(name foolib)
(modules :standard \ excluded))

View file

@ -0,0 +1 @@
let run () = print_endline "hello from nested module B"

View file

@ -0,0 +1 @@
let run () = print_endline "hello from nested module bar"

View file

@ -0,0 +1,29 @@
Demonstrate building a `include_subdirs qualified` project with `(modules
:standard \ exclusion)`
$ dune build
hello from nested module bar
hello from nested module B
$ find _build -iname "*.ml-gen" | sort | while read file; do echo "contents of $file"; cat $file; echo "--------"; done;
contents of _build/default/lib/foolib.ml-gen
(* generated by dune *)
(** @canonical Foolib.Foo *)
module Foo = Foolib__Foo
--------
contents of _build/default/lib/foolib__Foo.ml-gen
(* generated by dune *)
(** @canonical Foolib.Foo.A *)
module A = Foolib__Foo__A
(** @canonical Foolib.Foo.Bar *)
module Bar = Foolib__Foo__Bar
--------
contents of _build/default/lib/foolib__Foo__A.ml-gen
(* generated by dune *)
(** @canonical Foolib.Foo.A.B *)
module B = Foolib__Foo__A__B
--------

View file

@ -0,0 +1,3 @@
(rule
(alias default)
(action (run ./exe/test.exe)))

View file

@ -0,0 +1,3 @@
(executable
(libraries foolib)
(name test))

View file

@ -0,0 +1,3 @@
let () =
Foolib.Bar.Fake.run ();
Foolib.Bar.Baz.run ()

View file

@ -0,0 +1,5 @@
module Fake = struct
let run () =
print_endline "defined in lib interface file"
end
module Baz = Baz

View file

@ -0,0 +1 @@
let run () = print_endline "hello from baz"

View file

@ -0,0 +1,4 @@
(include_subdirs qualified)
(library
(name foolib))

View file

@ -0,0 +1,36 @@
We are also allowed to write lib interface files at each level.
$ dune build
defined in lib interface file
hello from baz
$ find _build -iname "*.cmi" | sort
_build/default/exe/.test.eobjs/byte/dune__exe__Test.cmi
_build/default/lib/.foolib.objs/byte/foolib.cmi
_build/default/lib/.foolib.objs/byte/foolib__.cmi
_build/default/lib/.foolib.objs/byte/foolib__Bar.cmi
_build/default/lib/.foolib.objs/byte/foolib__Bar__.cmi
_build/default/lib/.foolib.objs/byte/foolib__Bar__Baz.cmi
_build/default/lib/.foolib.objs/byte/foolib__Private.cmi
$ find _build -iname "*.ml-gen" | sort | while read file; do echo "contents of $file"; cat $file; echo "--------"; done;
contents of _build/default/lib/foolib__.ml-gen
(* generated by dune *)
(** @canonical Foolib.Bar *)
module Bar = Foolib__Bar
(** @canonical Foolib.Private *)
module Private = Foolib__Private
module Foolib__ = struct end
[@@deprecated "this module is shadowed"]
--------
contents of _build/default/lib/foolib__Bar__.ml-gen
(* generated by dune *)
(** @canonical Foolib.Bar.Baz *)
module Baz = Foolib__Bar__Baz
module Foolib__Bar__ = struct end
[@@deprecated "this module is shadowed"]
--------

View file

@ -0,0 +1,5 @@
(include_subdirs qualified)
(library
(name impl)
(implements vlib))

View file

@ -0,0 +1,7 @@
We can nested modules virtual
$ dune build @all
File "vlib/dune", line 5, characters 18-26:
5 | (virtual_modules bar/virt))
^^^^^^^^
Error: Module Bar/virt doesn't exist.
[1]

View file

@ -0,0 +1,5 @@
(include_subdirs qualified)
(library
(name vlib)
(virtual_modules bar/virt))

View file

@ -0,0 +1,68 @@
We should forbid lib interfaces modules from depending on themselves:
$ cat > dune-project << EOF
> (lang dune 3.7)
> EOF
$ cat > dune << EOF
> (include_subdirs qualified)
> (library
> (name foo))
> EOF
$ cat > foo.ml <<EOF
> let () = Foo.f ()
> EOF
$ touch bar.ml
$ dune build @check
File "foo.ml", line 1, characters 9-14:
1 | let () = Foo.f ()
^^^^^
Error: Unbound module Foo
[1]
We also forbid submodules from depending on their interface modules:
$ rm foo.ml bar.ml
$ mkdir baz
$ touch baz/baz.ml
$ cat >baz/bar.ml <<EOF
> let () = Baz.f
> EOF
$ dune build
Error: Module Bar in directory _build/default depends on Baz.
This doesn't make sense to me.
Baz 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.
-> required by _build/default/.foo.objs/foo__Baz__Bar.impl.all-deps
-> required by _build/default/.foo.objs/byte/foo__Baz__Bar.cmo
-> required by _build/default/foo.cma
-> required by alias all
-> required by alias default
[1]
Or their parent interface modules:
$ rm -rf baz
$ mkdir -p baz/foo/
$ cat >baz/foo/z.ml <<EOF
> let () = Baz.f
> EOF
$ dune build
Error: Module Z in directory _build/default depends on Baz.
This doesn't make sense to me.
Baz 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.
-> required by _build/default/.foo.objs/foo__Baz__Foo__Z.impl.all-deps
-> required by _build/default/.foo.objs/byte/foo__Baz__Foo__Z.cmo
-> required by _build/default/foo.cma
-> required by alias all
-> required by alias default
[1]

View file

@ -0,0 +1,17 @@
Preprocessing should work when there's modules with the same name
$ cat >dune-project <<EOF
> (lang dune 3.7)
> EOF
$ cat >dune <<EOF
> (include_subdirs qualified)
> (library
> (name foo)
> (preprocess (action (system "cat %{input-file}"))))
> EOF
$ mkdir bar/
$ touch baz.ml bar/baz.ml
$ dune build @check

View file

@ -0,0 +1,8 @@
(include_subdirs qualified)
(library
(name foolib)
(preprocess
(per_module
((action
(run cat %{input-file})) bar/ppme))))

View file

@ -0,0 +1 @@
module Bar = Bar.Ppme

View file

@ -0,0 +1,10 @@
We can set preprocessing options for nested modules
$ dune build @all
File "dune", line 8, characters 30-38:
8 | (run cat %{input-file})) bar/ppme))))
^^^^^^^^
Error: "bar/ppme" is an invalid module name.
Module names must be non-empty, start with a letter, and composed only of the
following characters: 'A'..'Z', 'a'..'z', '_', ''' or '0'..'9'.
Hint: barppme would be a correct module name
[1]

View file

@ -0,0 +1,22 @@
Marking modules as private
$ cat >dune-project <<EOF
> (lang dune 3.7)
> EOF
$ cat >dune <<EOF
> (include_subdirs qualified)
> (library
> (name foolib)
> (private_modules baz/foo))
> EOF
$ mkdir baz
$ touch baz/foo.ml
$ dune build
File "dune", line 4, characters 18-25:
4 | (private_modules baz/foo))
^^^^^^^
Error: Module Baz/foo doesn't exist.
[1]

View file

@ -0,0 +1,23 @@
Libraries designed as the "stdlib" may not use (include_subdirs qualified)
Although it's just an artificial limitation and when we can lift it if the need
arises to.
$ cat >dune-project <<EOF
> (lang dune 3.7)
> (using experimental_building_ocaml_compiler_with_dune 0.1)
> EOF
$ cat >dune <<EOF
> (include_subdirs qualified)
> (library
> (name foo)
> (stdlib))
> EOF
$ dune build @check
File "dune", line 1, characters 0-27:
1 | (include_subdirs qualified)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: a library with (stdlib ...) may not use (include_subdirs qualified)
[1]

View file

@ -0,0 +1,43 @@
Unwrapped libraries and (include_subdirs unqualified)
$ cat >dune-project <<EOF
> (lang dune 3.7)
> EOF
$ mkdir lib/ && cd lib
$ cat >dune <<EOF
> (include_subdirs qualified)
> (library
> (wrapped false)
> (name foo))
> EOF
$ mkdir x
$ cat >x/x.ml <<EOF
> let run () = Foo.run ()
> EOF
$ cat >x/foo.ml <<EOF
> let run () = print_endline "Foo"
> EOF
$ mkdir y
$ cat >y/z.ml <<EOF
> let run () = print_endline "Z"
> EOF
$ cd ..
$ cat >dune <<EOF
> (executable
> (libraries foo)
> (name main))
> EOF
$ cat >main.ml <<EOF
> let () = X.run (); Y.Z.run ()
> EOF
$ dune exec ./main.exe
Foo
Z