-
Notifications
You must be signed in to change notification settings - Fork 81
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
Track object and interface files explicitly in Starlark #1281
Conversation
An alternative strategy that came up during discussion is to not pass I've experimented with this idea. It works in principle, however, I discovered the following issues with this approach that make it seem less favorable:
|
What’s the status of this PR, can it be reviewed? I’ve had it stagnate in my browser tabs, hoping somebody else would review it first :) |
Yes, it can be reviewed and discussed on. This has been incorporated in This is a breaking change and a restriction on what kinds of Haskell rule invocations are valid. That's why I added a discussion section. There haven't been any replies regarding that discussion, yet. |
Regarding the restriction on file names, this is already the case when using ghcide (and possibly other tools), so it might actually be a good thing to enforce it at compile time to notice errors quickly |
151f9a3
to
a002648
Compare
I need to avoid I'll move forward with the original approach of this PR, unless someone objects. The shortcomings of the alternative to copy the source files are ugly enough that I don't think it is worth continuing the debate. |
@facundominguez Thanks for picking this up! No objection. |
c9435f3
to
44d1ebf
Compare
src = "TestBin.hs", | ||
# TODO: Test naming the Main module as something different | ||
# after adding some attribute to make the module name explicit | ||
src = "Main.hs", |
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 taking this as a signal that we might want to abandon src_strip_prefix
in haskell_module
too, and use instead a new optional attribute module_name
, to be specified whenever the module name doesn't match what the heuristics in this PR would infer.
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.
Yes, I'm happy to go that way.
One thing to keep in mind: For haskell_repl
to work we'll still need to be able to generate -i
flags that point to the Haskell source files of a given haskell_module
(REPL support for haskell_module
is not implemented, yet). The src_strip_prefix
attribute is a simple way to achieve this, assuming that the remaining file path matches the module name (Main
modules are not imported by other modules, so a mismatch is not an issue in that case). However, if you can construct a -i
search path based on a module_name
attribute, then that's good as well.
Please, could someone help me diagnose what the problem with the readthedocs job is? |
The docutils python package was updated to a version not compatible with sphinx, which broke a lot of readthedocs builds. It was fixed on master by #1620. |
Instead of inferring the module names based on `src_strip_prefix`.
02cd5f2
to
cee1846
Compare
Thanks @ylecornec! |
All green! |
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.
@facundominguez Thank you for picking this up. This looks great!
I cannot approve, since I originally opened that PR. But, feel free to approve yourself and then add to merge-queue.
Infer module names from source file paths and explicitly track object and interface files in Starlark.
Motivation
Closes #1260
Since #383
rules_haskell
usesctx.actions.declare_directory
for object and interface files generated by GHC instead of tracking these explicitly. The reason for this is that GHC produces these files under paths that depend on the module name rather than the source file name, which we cannot determine in Starlark in general.However, as #1260 describes, we have found that outputs declared by
ctx.actions.declare_directory
cause issues on Windows with distributed caching. Occasionally we end up with empty intermediate outputs (interface dir/manifest files) in the remote cache. These cause build failures when later builds read these intermediate outputs from the remote cache, e.g. after arules_haskell
update. They also tend to put the contents of Bazel output path on affected CI nodes into an invalid state. All this makes these issues very disruptive as they cause unrelated builds to fail, i.e. they often put all of CI on hold, and requirebazel clean --expunge
on the nodes and overwriting the remote cache to fix. Tracking the object and interface files explicitly and declaring them usingctx.actions.declare_file
resolves this issue.Also, the implementation of coverage support in
rules_haskell
already assumes that module names can be inferred from source files and themodules
attribute tohaskell_doctest
also requires file names to match module names.Changes
This PR implements explicit mapping from source file names to module names and the corresponding object and interface files in Starlark. A source file's module name is assumed to be the longest suffix that forms a valid module name. E.g.
This is very similar to the strategy described in #1232 (comment).
The main module is determined using the following heuristics:
Main.hs
exe.hs
.Users can override this using the
main_file
attribute.Further Information
I tested this strategy on the
rules_haskell
repository and thedaml
repository. With the strategy described above nearly all Haskell targets worked without changes. Inrules_haskell
there was one case of a file name not matching its module name and one target that required amain_file
attribute. Indaml
there were two targets where modules had been renamed but the file paths had not been updated to the new module hierarchy. So, hopefully this change would have minimal impact on users.This change does not affect the Cabal rules (
haskell_cabal_library|binary
). These do not require tracking object files as the full compilation happens in a single build action. Their interface files are still tracked viadeclare_directory
. We don't even know which source files to ahaskell_cabal_*
rule will be compiled, so we cannot predict the interface files. However, as everything happens in a single build action there are no intermediate build results, and we have never observed issues like #1260 with the Cabal rules.Discussion
This is a breaking change and effectively rolls back #383, though this implementation is more flexible than the prior
src_strip_prefix
approach. As #375 points out GHC is very lenient about source file names and this PR introduces an additional restriction on top of what GHC would require. However, many Haskell developers assume that source file names and module names should match, and some tools, e.g. GHCi's:load
command ordoctest
, make that assumption as well. I.e. it is unclear that being that lenient is actually a wanted features.One component that did require more leniency, at least than
src_strip_prefix
, was Hazel. However, since we have the Cabal rules Hazel is no longer required to build external dependencies, and even if, the strategy implemented in this PR is more lenient thansrc_strip_prefix
and may well work for most Hackage packages.This change introduces additional complexity to infer module names from source file names. However, arguably, it is a simplification, as the
declare_directory
approach requires pushing logic into build actions that could otherwise be written in Starlark, e.g. generating the object manifest files or the list of exposed modules.Also, this change makes the implementation of coverage support consistent with the rest of
rules_haskell
.Possible Extensions
-i
flags e.g. fordoctest
) could be made more precise. I.e. instead of usingsrc_strip_prefix
we could use the prefix until the longest valid module name of each source file.src_strip_prefix
could be repurposed to strip prefixes that would otherwise be considered part of the longest valid module name suffix. E.g. to stripFoo
insrc/Foo/Bar/Baz.hs
.src_prefix
similar toinclude_prefix
incc_library
to allow users to prepend a module prefix. E.g. turnpackage/Foo/Bar.hs
intoPackage.Foo.Bar
.