-
Notifications
You must be signed in to change notification settings - Fork 409
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
Multi directory libraries and executables #1034
Conversation
Shouldn't this be the default? IMO we shouldn't encourage people to create arbitrary grouping of the modules that isn't reflected in the module structure. Btw, I cherry picked the refactoring commit and rebased the rest so that it applies cleanly on master. It should make things easier to review. |
src/dir_contents.ml
Outdated
| Standalone of File_tree.Dir.t | ||
* Super_context.Dir_with_jbuild.t | ||
| Group_root of File_tree.Dir.t | ||
* Super_context.Dir_with_jbuild.t |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding a brief doc for every constructor here would be hlpeful
Option.bind (Path.drop_build_context dir) | ||
~f:(File_tree.find_dir (Super_context.file_tree sctx)) | ||
with | ||
| None -> Empty_standalone None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it intentional that this case doesn't populate the cache?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does, line 520
|
||
let cache = Hashtbl.create 32 | ||
|
||
let rec get sctx ~dir = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use Hashtbl.find_or_add
for this function (and others like it)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess we could use it here. It's just unfortunate that we end up systematically creating a closure while it's only useful in the not found case.
For other functions, we modify the cache in the not found case through a recursive call. It's not clear what the behavior of Hashtbl.find_or_add
is in this case should be, so it seems better to avoid it.
True, although allowing unqualified subdirs is not much work and I believe will help porting older projects to dune. What about:
? |
Thanks |
What would |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm approving because the implementation looks good. @diml I'll let you pick what you think the default on qualified vs. unqualified should be.
Changing the default to BTW, we still need to sort out the situation regarding .c/.h files before merging this. In the past there was a least one request to put .c files in a sub-directory. In the current state of this PR, .c/.h files in sub-directories are ignored, so we couldn't consider them in the future without introducing a breaking change. We can either make sure they are considered or simply forbid .c/.h files in sub-directories for now. I might do the latter for now since it's easier, in particular it's easier to setup the |
Oh, I simply suggested that |
That's a good point. I'll change the syntax to the following then: (include_subdirs <qualified|unqualified>) |
And maybe we can leave out the short |
I changed the syntax and also implemented the support for C files in sub-directories, since it wasn't that hard. @rgrinberg I let you review the latest changes. |
doc/dune-files.rst
Outdated
@@ -57,6 +57,11 @@ allowed to write an explicit ``Foo`` module, in which case this will | |||
be the interface of the library and you are free to expose only the | |||
modules you want. | |||
|
|||
Note that by default libraries and other things that consume | |||
OCaml/Reason modules only consume modules from the directory where the | |||
stanza appear. In order to delcare a multi-directory library, you need |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: declare
doc/dune-files.rst
Outdated
stop when encountering a sub-directory that: | ||
|
||
- is part of a different project (for instance when vendoring projects) | ||
- contains ``(include_subdirs true)`` or ``(include_subdirs)`` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That should be (include_subdirs unqualified)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
& the short syntax has been removed if I understand correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep. Given that it's a new thing, it seems better to make things explicit
src/dir_contents.ml
Outdated
| Standalone -> [t] | ||
| Group_root (lazy l) -> t :: l | ||
| Group_part t -> | ||
match t.kind with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The compiler seems to be doing fine, but I think adding begin
/end
around the nested match
will make this easier to read. An alternative is to use deep pattern matching instead of the nested match
, and move the assert false
to the outer match
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used a deep pattern matching
src/jbuild.ml
Outdated
|
||
let t = | ||
enum | ||
[ "unqualified", Unqualified |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thing that seems a bit weird is that there is no syntax for the default case. Would it be useful to have (include_subdirs no)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose. It especially makes sense if we plan to one day change the default to (include_subdirs qualified)
. I added no
and reworked the documentation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Just some comments that need to be updated first.
src/dir_contents.ml
Outdated
|
||
| Is_component_of_a_group_but_not_the_root of | ||
Super_context.Dir_with_jbuild.t option | ||
(* Sub-directory of a directory with [(include_subdirs true)] *) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This commend needs to be updated as you've changed the argument for this stanza.
src/dir_contents.ml
Outdated
|
||
| Group_root of File_tree.Dir.t | ||
* Super_context.Dir_with_jbuild.t | ||
(* Directory with [(include_subdirs true)] *) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment as well
src/gen_rules.ml
Outdated
Path.relative (Dir_contents.dir dc) fn :: acc | ||
else | ||
acc)) | ||
|> List.rev |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need this reverse? I just see that we provide these as command line args, does the order matter there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, it doesn't matter. Note that it's not even command line flags, it's just to specify dependencies
src/gen_rules.ml
Outdated
| Some _ -> | ||
match Dir_contents.kind (Dir_contents.get sctx ~dir) with | ||
| Group_part root -> | ||
SC.load_dir sctx ~dir:(Dir_contents.dir root) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How come we only do this in the case when there are no stanzas in dir
? Seems like we should let the paren that is part of multi dir lib regardless
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was done in the other gen_rules
function. However, it's true that this code wasn't very clear and was starting to become spaghetti code, so I refactored it
Signed-off-by: Jeremie Dimino <[email protected]>
Signed-off-by: Jeremie Dimino <[email protected]>
Signed-off-by: Jeremie Dimino <[email protected]>
Signed-off-by: Jeremie Dimino <[email protected]>
Signed-off-by: Jeremie Dimino <[email protected]>
Signed-off-by: Jeremie Dimino <[email protected]>
Signed-off-by: Rudi Grinberg <[email protected]>
Signed-off-by: Jeremie Dimino <[email protected]>
Signed-off-by: Jeremie Dimino <[email protected]>
Signed-off-by: Jeremie Dimino <[email protected]>
Signed-off-by: Jeremie Dimino <[email protected]>
Signed-off-by: Jeremie Dimino <[email protected]>
Signed-off-by: Jeremie Dimino <[email protected]>
Signed-off-by: Jeremie Dimino <[email protected]>
Signed-off-by: Jeremie Dimino <[email protected]>
Signed-off-by: Jeremie Dimino <[email protected]>
Signed-off-by: Jeremie Dimino <[email protected]>
Signed-off-by: Jeremie Dimino <[email protected]>
Signed-off-by: Jeremie Dimino <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Just need a CHANGES update
Signed-off-by: Jeremie Dimino <[email protected]>
@bobot in the end we did add first class support for multi directory libraries |
Looks good, thanks! |
CHANGES: - Fix lookup of command line specified files when `--root` is given. Previously, passing in `--root` in conjunction with `--workspace` or `--config` would not work correctly (ocaml/dune#997, @rgrinberg) - Add support for customizing env nodes in workspace files. The `env` stanza is now allowed in toplevel position in the workspace file, or for individual contexts. This feature requires `(dune lang 1.1)` (ocaml/dune#1038, @rgrinberg) - Add `enabled_if` field for aliases and tests. This field controls whether the test will be ran using a boolean expression language. (ocaml/dune#819, @rgrinberg) - Make `name`, `names` fields optional when a `public_name`, `public_names` field is provided. (ocaml/dune#1041, fix ocaml/dune#1000, @rgrinberg) - Interpret `X` in `--libdir X` as relative to `PREFIX` when `X` is relative (ocaml/dune#1072, fix ocaml/dune#1070, @diml) - Add support for multi directory libraries by writing `(include_subdirs unqualified)` (ocaml/dune#1034, @diml) - Add `(staged_pps ...)` to support staged ppx rewriters such as ones using the OCaml typer like `ppx_import` (ocaml/dune#1080, fix ocaml/dune#193, @diml) - Use `-opaque` in the `dev` profile. This option trades off binary quality for compilation speed when compiling .cmx files. (ocaml/dune#1079, fix ocaml/dune#1058, @rgrinberg) - Fix placeholders in `dune subst` documentation (ocaml/dune#1090, @emillon, thanks @trefis for the bug report) - Add locations to errors when a missing binary in PATH comes from a dune file (ocaml/dune#1096, fixes ocaml/dune#1095, @rgrinberg)
This PR adds the necessary support for multi-directory libraries and executables.
Description
When writing
(include_subdirs true)
or simple(include_subdirs)
in adune
file, dune will recurse in sub-directories to look for modules.The recursion stops when encountering a sub-directory that:
(include_subdirs true)
or(include_subdirs)
library
,executable(s)
,test(s)
Implementation
Dir_contents
was adapted to recognize directories that are part of a group of directories. WhenDir_contents.get
is called on a directory that is part of a group, the whole group is scanned at once.The rule producer in
gen_rules.ml
does exactly the same thing.TODO (before this can be merged)
Future work
Add a mode
(include_subdirs qualified)``so that sub-directories are qualifed. i.e. file
a/b/x.mlwill be seen as
A.B.xat the root, and as
B.xin
a/`