-
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
[RFC] Allow dune to treat targets opaquely. #1547
Conversation
The idea is essentially to add support for directory targets. This seems fine, especially as we currently do it for odoc but in a not very clean way. When considering the digest of a directory, we should probably consider the digest of the contents of the directory as well. Otherwise, dune will not re-generate it if it is modified. Regarding the current problem you are seeing, have you tried printing the stats to see if something is changing? |
Yes, and something is changing the
My understanding was that Dune will regenerate it if its dependencies are modified, right? I think that factoring the contents of the directories would be useful if those directories are inputs to other targets, right? I was even content with only supporting directories at root of dependency trees, because the common case is external systems that generate docs etc. They aren't typically used as inputs to other rules. Thoughts? |
Not that I can think of. It feels like Dune should really care about whether a target is a directory or a file, though I can't think of a place where this matters at the moment.
Since #1343, it will also regenerate it if the target is modified.
Yes.
That's fine as long as we get a proper error message if we try to use such a directory as dependency. |
For example, even if I change the |
Ah indeed, that's the function |
This function should be adapted to support directory targets |
I made the change you suggested. It seems to work. |
src/utils.ml
Outdated
let path = Path.to_string fn in | ||
let stat = Unix.stat path in | ||
let digest = | ||
if stat.st_kind == Unix.S_DIR then |
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.
We can use normal equality here instead of physical one:
if stat.st_kind == Unix.S_DIR then | |
if stat.st_kind = Unix.S_DIR then |
src/utils.ml
Outdated
if stat.st_kind == Unix.S_DIR then | ||
dir_digest stat | ||
else | ||
Digest.file (Path.to_string fn) |
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 looks like we could factorise this bit of code between here and refresh
Thanks, could you sign your commits as per the CONTRIBUTING.md file and add a changelog entry? We'll need to update |
Summary: Some targets will be generated by external build commands (such as static resource managers, documentation generators, etc). Often, those resources must be generated into a directory and the external tool will manage the contents of that directory. Dune can properly determine when to invoke the external build tool to regenerate that directory content, and the external build tool will be responsible for doing so. In this sense, Dune can treat directories generated by build commands as "opaque" resources, almost as if the directory was the tar equivalent of the directory. This diff attempts to implement this, but I'd like some feedback. There is one issue with this implementation which I could use some help resolving. Even if the mtime does not change for the file, Dune decides to regenerate the target - merely because it is a directory, and I cannot find the place in Dune where it decides to do that. Signed-off-by: Jordan Walke <jordojw@gmail.com>
Suggestions applied, signed off. |
Thanks. js_of_ocaml doesn't seem to build in travis, we need to double check if it builds with master or if the build of jsoo is broken by this PR. |
I had a quick look and couldn't reproduce the error locally. I restarted the build. |
@ejgallego do you have a full backtrace? It is truncated in the CI logs |
Let me try to reproduce. |
For some reason I am not able to reproduce reliably but it looks like this:
|
Thanks, I think I see the issue |
Anyway, we can merge this PR since the build failure is due to something else. |
@jordwalke, thanks for your contribution! |
Shouldn't this PR have also updated |
Before advertising this feature more, we need to:
|
Cool, thanks @diml, should something be done about |
Yh, we should be able to install a directory. Also that's quite a bit more work. |
How do we handle |
Having
That said, we should probably add a check somewhere to make sure we don't declare an existing directory as target. |
let ints = stat.Unix.st_size + stat.st_perm in | ||
(string_of_int ints ^ | ||
string_of_float stat.st_mtime ^ | ||
string_of_float stat.st_ctime) |
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's a relatively minor thing, but (a ^ b ^ c) will allocate an intermediate string (a^b) that creates unnecessary garbage. It might be better to do a sprintf here to do it in one allocation if the digest function is called a lot
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.
Now that you point that out, I just realise that we are missing separators in this string. i.e. two different stats records might produce the same string... That's very unlikely, but just to avoid readers wondering about it, we should add separators
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.
Fix here #1592
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.
thank you all!
CHANGES: - Expand variables in `install` stanzas (ocaml/dune#1354, @mseri) - Add predicate language support for specifying sub directories. This allows the use globs, set operations, and special values in specifying the sub directories used for the build. For example: `(dirs :standard \ lib*)` will use all directories except those that start with `lib`. (ocaml/dune#1517, ocaml/dune#1568, @rgrinberg) - Add `binaries` field to the `(env ..)` stanza. This field sets and overrides binaries for rules defined in a directory. (ocaml/dune#1521, @rgrinberg) - Fix a crash caused by using an extension in a project without dune-project file (ocaml/dune#1535, fix ocaml/dune#1529, @diml) - Allow `%{bin:..}`, `%{exe:..}`, and other static expansions in the `deps` field. (ocaml/dune#1155, fix ocaml/dune#1531, @rgrinberg) - Fix bad interaction between on-demand ppx rewriters and using multiple build contexts (ocaml/dune#1545, @diml) - Fix handling of installed .dune files when the backend is declared via a `dune` file (ocaml/dune#1551, fixes ocaml/dune#1549, @diml) - Add a `--stats` command line option to record resource usage (ocaml/dune#1543, @diml) - Fix `dune build @doc` deleting `highlight.pack.js` on rebuilds, after the first build (ocaml/dune#1557, @aantron). - Allow targets to be directories, which Dune will treat opaquely (ocaml/dune#1547, @jordwalke) - Support for OCaml 4.08: `List.t` is now provided by OCaml (ocaml/dune#1561, @ejgallego) - Exclude the local esy directory (`_esy`) from the list of watched directories (ocaml/dune#1578, @andreypopp) - Fix the output of `dune external-lib-deps` (ocaml/dune#1594, @diml) - Introduce `data_only_dirs` to replace `ignored_subdirs`. `ignored_subdirs` is deprecated since 1.6. (ocaml/dune#1590, @rgrinberg)
But what about a promoted directory? Wouldn't that end up in the source tree and as a target? |
FTR, we have been working on proper support for directory targets, including promoted directory targets. The support is almost complete in the main branch. It is still guarded by |
Summary: Some targets will be generated by external build commands (such
as static resource managers, documentation generators, etc). Often,
those resources must be generated into a directory and the external tool
will manage the contents of that directory.
Dune can properly determine when to invoke the external build tool to
regenerate that directory content, and the external build tool will be
responsible for doing so.
In this sense, Dune can treat directories generated by build commands as
"opaque" resources, almost as if the directory was the tar equivalent of
the directory.
This diff attempts to implement this, but I'd like some feedback.
There is one issue with this implementation which I could use some help
resolving. Even if the mtime does not change for the file, Dune decides
to regenerate the target - merely because it is a directory, and I
cannot find the place in Dune where it decides to do that.