-
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
Allow use of ppx in dune #9223
base: main
Are you sure you want to change the base?
Allow use of ppx in dune #9223
Conversation
373c949
to
6b4a9e0
Compare
TODO
This is still a draft at the moment so I'm adding this todo list. Restrict feature to dune's codebase onlyThe first part is to restrict this feature so it can only be used by dune itself as we agreed we did not want to make it public or at least not just yet. I'm not sure how to proceed with this so I'll gladly take any pointer. I wrote this feature as an extension because that was the simplest way to prototype it for me but this can be changed as well, especially if we don't want to make it public it probably doesn't make much sense to keep it that way. Ignore
|
b03914e
to
36f7b5f
Compare
Some comments addressing the version bumping which can be resolved later:
|
Simplest way is just to only allow it if the project name is equal to "dune". This is what we do for our bootstrapping extension.
You can add an appropriate field in the env stanza. That seems like the simplest thing. |
Is there any particular reason to add something to the env stanza rather than using a field of |
With the env stanza, you can set it for entire directories. Either one works fine though |
I modified the stanza to scan the whole project except for the given dirs to exclude. I added |
let syntax = | ||
let name = "include_preprocessed_sources" in | ||
let desc = "dummy" in | ||
Dune_lang.Syntax.create ~name ~desc [ (0, 1), `Since (3, 10) ] |
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 now have 3.13 in main if you want to use that.
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.
Awesome, I'll switch to it! I rolled it back to 3.10 while trying to fix an issue I had with merlin locally.
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 did bump it to 3.13 but since the PR also enables the extension it makes the whole repo depend on dune >= 3.13
and I therefore get CI builds failure with:
Switch invariant: ["ocaml" {>= "4.05.0"}]
[ERROR] Could not determine which packages to install for this switch:
* Missing dependency:
Switch initialisation failed: clean up? ('n' will leave the switch partially installed) [Y/n] y
- dune >= 3.13
no matching version
This is expected I guess. Is there any way I can tell the CI builds to pin dune.3.13.0
instead of 3.11.1
?
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.
Maybe its best to keep it 3.10 then. I don't think its worth spending time resolving these CI issues. It's not a user facing feature anyway yet.
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.
To be clear, the issue is not because we are adding a field to a new dune lang version, but because the CI works by coincidence. The actual dune-project version Dune itself uses, always lags behind the latest dune language version and our CI setup uses an older Dune to do some unrelated checks. If a newer version is required then these checks fail. (Ideally we shouldn't be doing them, but that isn't for this PR).
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 could also not enable it in this PR, simply adding the feature and enabling it later if that helps.
I'm also happy to use an older version of the language as lower bound for the feature since, as you said, it's not user facing.
I think everything in otherlibs should be excluded. |
@rgrinberg Don't we want to use this for stdune? |
No, we don't want to vendor anything for libraries that we publish. |
I added I also restricted the feature to dune only. While doing it I looked at |
e4e95b9
to
b6161c9
Compare
I completed all the items from my todo but there's a couple things I'd like to do before undrafting the PR:
I can easily take care of |
Is there a target/alias that is built to check this? We could setup something similar to our format jobs? Or even just include said target in that job. |
You can make it part of the |
At the moment we generate auto promote rules so for the CI we'd need an extra |
We could also just add a mode to dune that would fail on promotions. For now your workaround is enough though. |
9d98bd6
to
4f6ab52
Compare
I opened a draft PR here to show how it would look like to use the new I initially wanted to do it all before showing it to you but there's a significant amount of function to replace and each of them needs a bit of attention to determine whether a derived My first impression is that it adds a lot of files to the repo and some of them could probably be spared as it currently preprocesses the whole library no matter what. This could probably be improved by using a per-module pp spec or by detecting whether a preprocessed file actually differs from the original. The latter is of course harder to implement but requires less configuration if we can manage it. Let me know what you think. |
5171364
to
6c5612d
Compare
I would very much prefer this option. EDIT: it should also be fairly simple to implement if we use the |
I'll look into this. We'll need two things for this to work:
|
I'm quite surprised but after formatting it seems to work out of the box. I was sure the driver added some attributes by default but it appears it doesn't, or at least doesn't always add them. I'll try to change the rules so it doesn't promote a preprocessed file if it's identical to the source! |
I just added the formatting of promoted files, now I need to implement the conditional promotion mechanism. What we would like to have here would be:
This is quite different from Does this sound like a good behaviour to you and if so, do you have any pointer or tips on how to best implement this? |
d190764
to
a8d322f
Compare
@NathanReb is this ready for a round of review? |
No sorry, I still have to change the rules to make use of the new driver mode I added in ppxlib. I'll work on it next week! |
This adds an `(include_preprocessed_sources)` stanza which generates rules to promote preprocessed version of sources. It's used in a `ppx/` folder at the project root. For any library or executable stanza with a `(preprocess (pps ...))` field in <path>, it will generate promotion rules for preprocessed versions in `ppx/<path>`. It also modifies `duneboot.ml` to use `ppx/<path>.ml(i)` instead of `<path>.ml(i)` if it exists, allowing us to use ppx in development without making it a build dependency. Signed-off-by: Nathan Rebours <[email protected]>
It was naively reusing the Source_tree_map_reduce from the utop rules generation. It now uses its own version that collects modules to preprocess for libraries and executables. Signed-off-by: Nathan Rebours <[email protected]>
The stanza will now generate rules by scanning the whole project except for the listed exlude dirs. This allow us to exclude the places that uses ppx but aren't necessary for bootstrapping such as the `bench/` directory. Signed-off-by: Nathan Rebours <[email protected]>
Signed-off-by: Nathan Rebours <[email protected]>
Signed-off-by: Nathan Rebours <[email protected]>
Signed-off-by: Nathan Rebours <[email protected]>
Signed-off-by: Nathan Rebours <[email protected]>
Signed-off-by: Nathan Rebours <[email protected]>
Signed-off-by: Nathan Rebours <[email protected]>
Signed-off-by: Nathan Rebours <[email protected]>
Signed-off-by: Nathan Rebours <[email protected]>
Signed-off-by: Nathan Rebours <[email protected]>
4dc52a1
to
2f34aa4
Compare
I'm looking into how to rewrite the rules with the new driver mode. For context, the idea was to make the ppx driver not write to the target file if there is no ppx transformation to apply so we can use it with a I'm struggling with how to write such a rule and think I could use some guidance here. It seems that it should be used in a I'm probably missing something very simple but if anyone can point me in the right direction that would probably ease things a lot! |
Signed-off-by: Rudi Grinberg <[email protected]>
Signed-off-by: Rudi Grinberg <[email protected]>
Signed-off-by: Rudi Grinberg <[email protected]>
I pushed a quick sketch of how I imagined it to work. You were indeed pretty close. The key here is that we don't need any intermediate targets for our rule. We need two ingredients:
The only missing piece is that to correctly create the action in 1., we need a way to run the formatter only if the file produced by the ppx exists. So we need an action like: val run_if_exists : Path.t -> Action.t -> Action.t I inlined a comment on how you would go about implementing such an action. Let me know if this isn't clear. |
Thanks @rgrinberg! I just got back from vacation and will start working on this! |
Signed-off-by: Nathan Rebours <[email protected]>
Signed-off-by: Nathan Rebours <[email protected]>
Signed-off-by: Nathan Rebours <[email protected]>
I have a draft version of this that builds but when I try to use it I get the following errors:
and so on, for each file in the library that uses a ppx. I'm guessing this is an error somewhat similar to what I encountered originally with rules being defined in a different folder than their targets. That required that the addition this function, used here. I expect this is a slightly different flavor of the same issue. |
Nevermind, it seems to be something much simpler: the formatting action I'm using must be declaring a dependency on the preprocessed file which is the optional output of the driver invocation and is never declared as a target of any rule. I think I got it wrong when building the combined action. I'll look into it! |
Fixes #8586
This adds an
(include_preprocessed_sources)
extension which generates rules to promote preprocessed version of source files. It's used in appx/
folder at the project root.For any library or executable stanza with a
(preprocess (pps ...))
field in , it will generate promotion rules for preprocessed versions inppx/<path>
.It also modifies
duneboot.ml
to useppx/<path>.ml(i)
instead of<path>.ml(i)
if it exists, allowing us to use ppx in development without making it a build dependency.