Skip to content
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

pkg: build and make ocamlformat dev-tool available #10647

Merged
merged 1 commit into from
Sep 12, 2024

Conversation

moyodiallo
Copy link
Collaborator

@moyodiallo moyodiallo commented Jun 13, 2024

Attempts to implement #10688.

Reopen the PR #10613 to target main branch instead of toolchain one.

To avoid dune capturing a dev-tool like ocamlformat when using dune build @fmt. This PR is about to build this tool independently from dune-project dependencies, to avoid conflict. After a successful build it will be directly available whenever dune build @fmt or dune fmt is invoked.

  • ocamlformat: build and make it available
  • prioritize dev tools to PATH when dune.lock dir is present in the project.
  • Solve ocamlformat when dune fmt invoke it. (you're right here @Leonidas-from-XIV, it is needed to keep the pkg tests using dune pkg lock intact or facilitate adding new test for this PR)
  • Fix the fetch of ocamlformat dev tool dependencies ( It turns out that the fetch rules are missing those packages)
  • add a cram test

The next works that would be done:

  • The ocamlformat stanza (ocamlformat <version>) could be added in another PR in order to make this one simple.
  • A PR for odoc tool will the same as this PR.

@moyodiallo
Copy link
Collaborator Author

moyodiallo commented Jun 18, 2024

This PR is not supposed to be merged before #10639, in order to test it properly. Or if we managed to add a cram test which validate it, we could go for that.

@moyodiallo
Copy link
Collaborator Author

I'm hitting a new issue, it about fetching the dev-tools dependencies, the solution I found is to fetch them in a different directory _fecth/.dev-tools/<dep>, because a regular pkg and dev-tool dep doesn't share the same pkg database so the fetch_rules need to differentiate.

@moyodiallo moyodiallo force-pushed the dev-tool-ocamlformat branch 4 times, most recently from b22f0ee to e71cb15 Compare July 2, 2024 17:34
@moyodiallo moyodiallo marked this pull request as ready for review July 2, 2024 17:35
@moyodiallo
Copy link
Collaborator Author

I'm hitting a new issue, it about fetching the dev-tools dependencies, the solution I found is to fetch them in a different directory _fecth/.dev-tools/<dep>, because a regular pkg and dev-tool dep doesn't share the same pkg database so the fetch_rules need to differentiate.

Another solution is used and is short than this one.

@rgrinberg
Copy link
Member

Is there an issue I could read that describes the solution being implemented here in high level terms?

match components with
| [ ".ocamlformat"; pkg_name ] ->
setup_package_rules ctx ~component:(Dev_tool Ocamlformat) ~dir ~pkg_name
| [ ".ocamlformat" ] ->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need to introduce a special directory just for ocamlformat?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid conflict with dune.lock packages. Like the ocamlformat could have the same dependency with different version, so it is built separately.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you indeed have two versions of ocamlformat, which one are you going to let the user see then?

Copy link
Collaborator Author

@moyodiallo moyodiallo Jul 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The priority is the one described in dune-project.

@moyodiallo
Copy link
Collaborator Author

Is there an issue I could read that describes the solution being implemented here in high level terms?

There's no opened issue. This is new feature about ocamlformat. When ocamlformat is not a dependency of a project, dune fmt will capture ocamlformat command from the PATH. So in the case of pkg management we could build ocamlformat and make it available to dune fmt.

@rgrinberg
Copy link
Member

Okay, please write such an issue. In particular, it should describe how it resolves the conflict situation we discussed above.

@moyodiallo
Copy link
Collaborator Author

Okay, please write such an issue. In particular, it should describe how it resolves the conflict situation we discussed above.

Added here #10688.

Copy link
Collaborator

@Leonidas-from-XIV Leonidas-from-XIV left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that there is a test now that shows that the feature works! Functionality-wise I have one concern: the lockdir for the tools shouldn't be in the users source directory. Code-wise see my comments in the review.

}

let to_local (t : t) : Local_package.t =
let open Local_package in
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in Dune we usually try to avoid local opens (except for operators) and instead use Local_package.name = t.name.

src/dune_pkg/dev_tool.ml Outdated Show resolved Hide resolved
Make a package for the library:
$ mkpkg ocamlformat 0.26.2 <<EOF
> build: [
> ["dune" "subst"] {dev}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be removed.

> jobs
> "@install"
> "@runtest" {with-test}
> "@doc" {with-doc}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-j jobs @runtest @doc can all be removed as they are not relevant for the test.

test/blackbox-tests/test-cases/pkg/ocamlformat-dev-tool.t Outdated Show resolved Hide resolved
@@ -1688,10 +1722,184 @@ let gen_rules context_name (pkg : Pkg.t) =

module Gen_rules = Build_config.Gen_rules

let setup_package_rules context ~dir ~pkg_name : Gen_rules.result Memo.t =
module Solver = struct
let repositories_of_workspace (workspace : Workspace.t) =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be duplicated from pkg_common

Copy link
Collaborator Author

@moyodiallo moyodiallo Jul 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At some point I added a comment that indicate it is duplicated but I erased it because of a revert.

(* All the file IO side effects happen here: *)
Dune_pkg.Lock_dir.Write_disk.commit write_disk
;;
end
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be deduplicated with the code from pkg_common.

Copy link
Collaborator Author

@moyodiallo moyodiallo Jul 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code from pkg_common is for more than one lockdir.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No solving should occur in pkg_rules

@@ -1726,26 +1934,38 @@ let setup_package_rules context ~dir ~pkg_name : Gen_rules.result Memo.t =
;;

let setup_rules ~components ~dir ctx =
let open Rule_root in
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to deduplicate the paths. The issue is that .ocamlformat/.pkg are defined once in Rule_root and once here. e.g. to change it, one needs to change both Rule_root and this function, if only one changes things break.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right here.

let ocamlformat_artifact_and_deps =
Memo.lazy_ (fun () ->
let* () =
if not (Stdune.Path.exists (Path.source Dev_tool.Ocamlformat.lock_dir))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to reference Stdune here.

> ]
> ]
> url {
> src: "http://0.0.0.0:$PORT"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that needs to be 127.0.0.1 or maybe better localhost.

@moyodiallo
Copy link
Collaborator Author

I like that there is a test now that shows that the feature works! Functionality-wise I have one concern: the lockdir for the tools shouldn't be in the users source directory. Code-wise see my comments in the review.

I tried to hide the lockdir, but it needs more work to be done for this PR. At the moment dune load only lockdir inside source directory that need to be changed to allow loading from build directory.

@rgrinberg
Copy link
Member

Some initial comments about the implementation:

  1. There's an intentional layer of abstraction between solving for build plans and executing them. We should maintain it. In particular, solving is not a valid build rule because we do not correctly track its dependencies.

  2. We should avoid hard coding things related to ocamlformat as much as possible. For us there's no difference between any of the dev tools apart from the stage where we generate the lock directories and we need to find the constraints. So you should pretend you have a "dev tools" lock directory and a few packages from where we pull binaries. No additional mentions of ocamlformat should be needed.

Other than that, things are looking good 👍

A few test cases we need to cover:

  1. The conflicting dependencies case that we talked about.
  2. Make sure that a dev tool's dependencies do not leak into the user's build environment.
  3. Errors when solving for the dev tools
  4. Errors when build dev tools

| Dev_tool Ocamlformat -> ".ocamlformat"
;;

let equal t1 t2 = t1 = t2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should avoid structural equality and instead explicitly compare variants by matching.

@@ -140,6 +140,8 @@ let get (ctx : Context_name.t) : t Memo.t =
lock_dir
;;

let get_ocamlformat : t Memo.t = Load.load @@ Dev_tool.Ocamlformat.lock_dir
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The @@ is unnecessary here.

Console.Status_line.add_overlay (Constant (Pp.text "Solving for Build Plan"))
in
let local_packages =
Package_name.Map.add Package_name.Map.empty local_package.name local_package
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use Package_name.Map.singleton instead

@moyodiallo
Copy link
Collaborator Author

Some initial comments about the implementation:

  1. There's an intentional layer of abstraction between solving for build plans and executing them. We should maintain it. In particular, solving is not a valid build rule because we do not correctly track its dependencies.

I get it, what do you think about having dune pkg lock --with-dev-tool=ocamlformat or something similar ?
cc: @Leonidas-from-XIV

  1. We should avoid hard coding things related to ocamlformat as much as possible. For us there's no difference between any of the dev tools apart from the stage where we generate the lock directories and we need to find the constraints. So you should pretend you have a "dev tools" lock directory and a few packages from where we pull binaries. No additional mentions of ocamlformat should be needed.

Super, the idea could be having _build/private/.dev_tools/<name>/<package_deps> instead of _build/private/.ocamlformat/<package_deps>, that will avoid hard-coding ocamlformat. I could try to do this.

Other than that, things are looking good 👍

A few test cases we need to cover:

  1. The conflicting dependencies case that we talked about.

  2. Make sure that a dev tool's dependencies do not leak into the user's build environment.

  3. Errors when solving for the dev tools

  4. Errors when build dev tools

Thanks, those are good test cases.

@rgrinberg
Copy link
Member

I get it, what do you think about having dune pkg lock --with-dev-tool=ocamlformat or something similar

Before you extend the command line, I suggest you try to accomplish what you'd like using workspace file configuration. Usually, command line options are better suited for things that need to be executed often and don't need to be shared. That does not seem to fit the use case here. Workspace files are a little more verbose, but offer more flexibility and most importantly, do not require to remembering long commands. If we ever need to add a shortcut, we can think of extending the command line later.

@moyodiallo
Copy link
Collaborator Author

I get it, what do you think about having dune pkg lock --with-dev-tool=ocamlformat or something similar

Before you extend the command line, I suggest you try to accomplish what you'd like using workspace file configuration. Usually, command line options are better suited for things that need to be executed often and don't need to be shared. That does not seem to fit the use case here. Workspace files are a little more verbose, but offer more flexibility and most importantly, do not require to remembering long commands. If we ever need to add a shortcut, we can think of extending the command line later.

Good point, we could skip this since we can take what we need from .ocamlformat and make the solve at the start of dune fmt command.


Format foo.ml, 'dune fmt' uses printer.1.0 instead. There is no conflict with different
versions of the same dependency.
$ DUNE_CONFIG__LOCK_DEV_TOOL=enabled dune fmt
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dune fmt --preview so you don't need to revert foo.ml below.

Solution for dune.lock:
(no dependencies to lock)

The OCamlFormat binary from the dev-tool.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this section intended to communicate to readers?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To show that ocamlformat dev-tool is available.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you update the comment to make this clear.

> (public_name foo))
> EOF

The OCamlFormat binary from the dev-tool.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's necessary to test that the ocamlformat binary works correctly after each step.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Always the same, the intention behind is to be sure ocamlformat dev-tool is not cleaned at some point.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you update the comment to explain this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed it and preparing to merge some other concern with this.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file needs a description.

> version = 0.26.9
> EOF

An important cleaning here
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A more meaningful comment would explain why it's important to clean here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normally this clean is not necessary.

We need to fix this in the PR, because when the dev-tool is disabled, even if dev-tools.locks/ocamlformat exists dune fmt is not supposed wokrs as if dev-tool is enabled.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. Can you update the comment to explain this.

Copy link
Collaborator Author

@moyodiallo moyodiallo Sep 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could just extends the check for dev-tool and remove this cleaning. I could do that.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now let's just prioritize getting this PR merged, so I'd say just update the comment to clarify and make additional changes in a later PR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right.

Copy link
Collaborator

@gridbugs gridbugs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've left a bunch of suggestions throughout the tests.

I think the files beginning with "binary-" should be renamed to remove that prefix as it doesn't seem relevant to what the tests are doing.

All the tests need to be renamed to start with "ocamlformat-" or similar. This is because when you run a single test from the command line, you run dune build @test/<filename-without-the-extension>. If there are multiple tests in different directories with the same filename, all those tests will run. For example there is already a test named e2e.t, so now running dune build @test/e2e will run the existing test and the one introduced here. Adding an explicit prefix ocamlformat- to each of these test files will reduce the risk of accidental name collisions in the future.

$ cd ..
$ tar -czf ocamlformat-0.26.2.tar.gz ocamlformat

Make a fake ocamlformat.0.26.3:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see these written both like OCamlFormat 0.26.3 and ocamlformat.0.26.3. If the latter is correct, it will need to be in monospace ocamlformat.0.26.3.

Let me know which format is correct, and I'll go through and make them all consistent.

Copy link
Collaborator Author

@moyodiallo moyodiallo Sep 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is "ocamlformat.0.26.3". we are also trying to avoid quoting with ``.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the response! To clarify, you want it written in monospace or without? I believe the correct way would be in monospace since it appears in the code, no? Let me know and I'll make all of them consistent.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Christine, The backquotes syntax for code is only for files that are in the markdown format. Our tests are not written in markdown, so the backticks aren't needed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah! Thank you for that explanation. Some of them are in .ml, .mli. and .t, all which have their own way to put things in code block. Shall I do that?

If you don't want the things normally in monospace formatted that way in these (code, libraries, specific files, etc.), how do you want them formatted to indicate what they are? I saw a lot of them were in " " -- but not all of them. Whichever you'd like, please let me know so I can make all of them consistent.

@moyodiallo moyodiallo force-pushed the dev-tool-ocamlformat branch 2 times, most recently from 6b54507 to ede02e2 Compare September 11, 2024 11:06
@moyodiallo
Copy link
Collaborator Author

@christinerose your last changes was added. I took what is needed.

@moyodiallo
Copy link
Collaborator Author

@gridbugs I applied lot of your concerns, maybe all of them.

@christinerose
Copy link
Collaborator

@christinerose your last changes was added. I took what is needed.

Great! I went through the new changes and made the formatting consistent.

Part of my job is to make formatting consistent across all documentation. The changes I make are based on previously-decided formatting from the maintainers. If the maintainers have changed in the way these are formatted, please let me know so I can update my style guide.

Copy link
Collaborator

@gridbugs gridbugs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. @rgrinberg is there anything more that this PR needs from your end?

Signed-off-by: Alpha DIALLO <moyodiallo@gmail.com>
@rgrinberg rgrinberg enabled auto-merge (squash) September 12, 2024 22:59
@rgrinberg rgrinberg merged commit ded1f5e into ocaml:main Sep 12, 2024
27 checks passed
anmonteiro pushed a commit to anmonteiro/dune that referenced this pull request Nov 17, 2024
Signed-off-by: Alpha DIALLO <moyodiallo@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants