Skip to content

Dune Package#1329

Merged
rgrinberg merged 8 commits intoocaml:masterfrom
rgrinberg:dune-package
Dec 9, 2018
Merged

Dune Package#1329
rgrinberg merged 8 commits intoocaml:masterfrom
rgrinberg:dune-package

Conversation

@rgrinberg
Copy link
Copy Markdown
Member

@rgrinberg rgrinberg commented Sep 25, 2018

This PR is required for non lossy installation of dune packages. It will include all information that is lost by installing things via findlib. In particular, this will allow virtual libraries and implementations to be available as external libraries. But also, this would allow for adding robust checks such as not using preprocessors (kind = ppx_rewriter) in the dependency field.

TODO

  • Add version information to the dune package
  • Read META + dune installed files or the dune-package files
  • Use correct dune version to generate file (it should be the latest version)
  • Fix tests for generating the old .dune files.
  • Stop printing empty lists in the dune-package file
  • Fix parsing subsystem files
  • Add tests for parsing old dune subsystem files.

What I will delay for subsequent PR's:

Installing virtual library/implementation specific information in these dune-package files.

There's some current parsing failures:

#=== ERROR while compiling ppxlib.0.3.1 =======================================#
# context     2.0.0 | linux/x86_64 | ocaml-system.4.06.0 | https://opam.ocaml.org/#892303df
# path        ~/.opam/default/.opam-switch/build/ppxlib.0.3.1
# command     ~/.opam/default/bin/jbuilder build -p ppxlib -j 47
# exit-code   1
# env-file    ~/.opam/log/ppxlib-8134-242f40.env
# output-file ~/.opam/log/ppxlib-8134-242f40.out
### output ###
# File "/home/travis/.opam/default/lib/ocaml-migrate-parsetree/dune-package", line 18, characters 5-122:
# 18 |      ((flags (--dump-ast))
# 19 |       (lint_flags (--null))
# 20 |       (main Migrate_parsetree.Driver.run_main)
# 21 |       (replaces ())))))))
# Error: Atom expected
# Hint: dune files require less parentheses than jbuild files.
# If you just converted this file from a jbuild file, try removing these parentheses.

@rgrinberg rgrinberg requested review from a user and emillon September 25, 2018 21:20
@rgrinberg rgrinberg force-pushed the dune-package branch 2 times, most recently from a41acea to 2b2a580 Compare September 25, 2018 23:14
@rgrinberg
Copy link
Copy Markdown
Member Author

@diml have a look at how I've implemented versioning. I'm not entirely confident by how things are done right now on the encoding side as there's quite a bit of boilerplate. I suppose it's because we don't have any combinators to output a list of sexp, rather than just 1 big record.

@rgrinberg
Copy link
Copy Markdown
Member Author

@diml Hilariously, not having #966 is blocking our plans for the META -> Dune_package.t conversion that we planned. Our Dune_package.Lib.dir function assumes that every sub library has its own sub directory, but this isn't true for the stdlib (unfortunately). We can either:

  • bring back the old legacy Findlib.Package.t -> Lib_info.t which already takes care of this special case.

  • Add a dir field to Dune_pacakge.Lib.t and then special case the stdlib conversion.

@ghost
Copy link
Copy Markdown

ghost commented Oct 2, 2018

Let's do the second option, it seems more flexible.

@rgrinberg
Copy link
Copy Markdown
Member Author

@diml I chose the 2nd option. As a consequence, the dir field must now be Path.t as opposed to Path.Local.t. The paths that we get from reading the META files aren't necessarily local, so we must treat them more generally.

@ghost
Copy link
Copy Markdown

ghost commented Oct 4, 2018

Ok, makes sense

@rgrinberg rgrinberg force-pushed the dune-package branch 2 times, most recently from 4a16ca6 to f2f062d Compare October 4, 2018 22:34
@rgrinberg
Copy link
Copy Markdown
Member Author

Hm, this path is a bit more complicated than I thought. All of the various artifacts fields:

    ; archives         : Path.t list Mode.Dict.t
    ; plugins          : Path.t list Mode.Dict.t
    ; foreign_objects  : Path.t list
    ; foreign_archives : Path.t list Mode.Dict.t
    ; jsoo_runtime     : Path.t list

Seems like they should be Path.Local.t rather than Path.t when encoding the paths. As we only want to encode the bit that is relative to the dir field. But it's quite a bit more inconvenient to deal with Path.Local.t for artifacts, plugins, etc. I'm wondering if we should one of the following:

  • Change the Path.t for all of these library relative paths and make this record abstract. We'll add accessors functions such var archives : t -> Path.t list Mode.Dict.t that will concatenate the paths appropriately.

  • Add a path parameter for this Path.t type. When encoding, this should be Path.Local.t. While when decoding, it should be Path.t

@rgrinberg
Copy link
Copy Markdown
Member Author

@diml when printing the (lang dune x.y) line for the dune-package file, which version do we use? Do we use the latest version? Or the version in the dune-project of the package. The latter is harder, as we'd need to support serialization to different versions. But at least this way, users would have a controlled way of upgrading the package format.

@ghost
Copy link
Copy Markdown

ghost commented Oct 5, 2018

Let's use the latest version. Using the one specified in the dune-project is much more work, and the only advantage I can think of doing so would be that the user could downgrade dune without reinstalling existing packages. This is not likely to happen very often so it doesn't seem worth the effort. Can you think of any other advantage?

@rgrinberg
Copy link
Copy Markdown
Member Author

I don't see any advantages, but I still think that it will cause some surprises to users. Let's prepare the team for this decision as well btw. I'll mention this to everyone on slack.

@emillon
Copy link
Copy Markdown
Collaborator

emillon commented Oct 6, 2018

That seems OK to me, but I'm fine with waiting for #966 as well. And in the meantime, we could use some heuristics to detect ppx used as libraries.

@ghost
Copy link
Copy Markdown

ghost commented Oct 8, 2018

Unfortunately, it's not clear whether the OCaml PR #966 is waiting on will go in or not. So for now we should assume it won't go in. Additionally, the new layout would only apply to the latest version of the compiler. We still need to support existing versions of compiler, as well as OCaml packages that don't use dune.

@rgrinberg
Copy link
Copy Markdown
Member Author

Let's use the latest version. Using the one specified in the dune-project is much more work, and the only advantage I can think of doing so would be that the user could downgrade dune without reinstalling existing packages. This is not likely to happen very often so it doesn't seem worth the effort. Can you think of any other advantage?

Can't think of anything. Let's just use the latest version. The other devs don't seem to mind either.

@rgrinberg
Copy link
Copy Markdown
Member Author

rgrinberg commented Oct 30, 2018

I've rebased this PR on top of master. There's still some hiccups with the paths unfortunately. A naive conversion like:

val to_dune_lib : lib -> Dune_package.Lib.t

Will not work. This is because we'd like the paths in the Dune_package.Lib.t to reflect the path structure in _build/install. The solution I'm working on is to change the signature to:

val to_dune_lib : lib -> map_paths:(Path.t -> Path.t) -> Dune_package.Lib.t

map_paths can be easily generated after running the copy rules from the object dirs to the install dirs. Another approach would be to have an explicit function that would simply change the root dir for a Dune_pacakge.Lib.t. But this doesn't work as well because some paths have a completely different structure when stored as installed paths. For example, the cma's live in the obj sub dir of a library in _build/default, but there's no obj sub dir in the corresponding _build/install.

@ghost
Copy link
Copy Markdown

ghost commented Oct 30, 2018

What about using the following for a library with public name "a.b.c":

Path.relative (Config.local_install_lib_dir ~context ~package:"a") "b/c"

?

@rgrinberg
Copy link
Copy Markdown
Member Author

So take all the paths in Dune_package.Lib.t, take their basenames and prepend them with the prefix you've proposed?

I think that will work currently but unfortunately, it will flatten all the objects into 1 dir for installation. That should work well now, but it might be break if we'll need a subdirectory for some files in an installed library (This could happen if we'll have some cmi's that we only share between libraries for example).

I'll give that a try, but it might still be used as the argument passed to map_paths:(fun p -> Path.relative lib_install_root (Path.basename p)).

@ghost
Copy link
Copy Markdown

ghost commented Oct 30, 2018

Note that this corresponds exactly to the directory structure we use in install/..., so it should be enough.

@rgrinberg
Copy link
Copy Markdown
Member Author

In the last commit things are starting to work. I think that we'll need to update the subsystems API if we'll want subsystems to install their own artifacts.

@rgrinberg rgrinberg changed the title Dune package [WIP] Dune Package Nov 27, 2018
@rgrinberg
Copy link
Copy Markdown
Member Author

Okay, this PR is now ready for review. There's still a little more work to do to make these files work for virtual libraries but that can be done in subsequent PR's.

@ghost
Copy link
Copy Markdown

ghost commented Dec 4, 2018

Sorry for the delay, I feel like this PR needs careful review but I'm a bit busy at the moment. If I don't get a chance to review it by Thursday, we can look at it together then.

@rgrinberg
Copy link
Copy Markdown
Member Author

Agreed. This is why I didn't want to push this into 1.6 either. It would suck to have to many versions of this format.

@rgrinberg rgrinberg force-pushed the dune-package branch 4 times, most recently from 14f03f8 to 707d9bf Compare December 6, 2018 14:29
@rgrinberg rgrinberg force-pushed the dune-package branch 2 times, most recently from b011866 to b3a5461 Compare December 7, 2018 16:26
@rgrinberg
Copy link
Copy Markdown
Member Author

Here's a summary of the discussion with diml about this feature:

In anticipation of dune 2.0, we will eventually want to have a form of forward compatibility for dune-package files. We'd still expect dune 2.0 to be able to generate valid dune-package 1.x files. @diml can explain the reasoning for this, as I've forgotten why can't we have dune 2.0 just generate dune-package files valid for 2.0.

We'd like the file paths in the dune-package file to be relative to the dune-package itself. The alternative was to infer the full file paths from the library names.

Subsystem (plugin) handling requires that dune knows which fields and stanzas to ignore when it doesn't recognize a plugin/subsystem. We've decided handle this as follows:

Every declared plugin will have an appropriate (using foo x.x) in the dune-package file. Such a plugin will only be able to define foo or foo.* stanzas and fields. If dune doesn't recognize a declared plugin, it will ignore the appropriate stanzas/fields. cc @ejgallego regarding coq.

For variants support, we need to add some extra module information. There's a couple of possibilities on how to handle this:

  • Just include the module information in the dune-package file (might as well do it for every library in this case). However, including information in the dune-package file should be done with care. As it means that we'll have to support this format forever.

  • Try to infer it by scanning the file system. While we won't have to change the dune-package file with this approach, we'll have to add rules based on the results of evaluating some globs (to infer modules). This isn't very desirable either.

Personally, I'm leaning towards the former.

@rgrinberg rgrinberg force-pushed the dune-package branch 2 times, most recently from cfb49e5 to 42152c8 Compare December 8, 2018 12:56
rgrinberg and others added 7 commits December 9, 2018 09:05
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
dune package replace META + subsystems files as the main format for dune to read
binary packages.

Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Jeremie Dimino <jeremie@dimino.org>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Jeremie Dimino <jeremie@dimino.org>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
@rgrinberg
Copy link
Copy Markdown
Member Author

The last commit makes subsystems in the dune-package file only generate using the dune syntax.

@rgrinberg rgrinberg merged commit 28947e7 into ocaml:master Dec 9, 2018
@rgrinberg rgrinberg deleted the dune-package branch December 9, 2018 11:22
rgrinberg added a commit to rgrinberg/opam-repository that referenced this pull request Feb 12, 2019
CHANGES:

- Second step of the deprecation of jbuilder: the `jbuilder` binary
  now emits a warning on every startup and both `jbuilder` and `dune`
  emit warnings when encountering `jbuild` files (ocaml/dune#1752, @diml)

- Change the layout of build artifacts inside _build. The new layout enables
  optimizations that depend on the presence of `.cmx` files of private modules
  (ocaml/dune#1676, @bobot)

- Fix merlin handling of private module visibility (ocaml/dune#1653 @bobot)

- unstable-fmt: use boxes to wrap some lists (ocaml/dune#1608, fix ocaml/dune#1153, @emillon,
  thanks to @rgrinberg)

- skip directories when looking up programs in the PATH (ocaml/dune#1628, fixes
  ocaml/dune#1616, @diml)

- Use `lsof` on macOS to implement `--stats` (ocaml/dune#1636, fixes ocaml/dune#1634, @xclerc)

- Generate `dune-package` files for every package. These files are installed and
  read instead of `META` files whenever they are available (ocaml/dune#1329, @rgrinberg)

- Fix preprocessing for libraries with `(include_subdirs ..)` (ocaml/dune#1624, fix ocaml/dune#1626,
  @nojb, @rgrinberg)

- Do not generate targets for archive that don't match the `modes` field.
  (ocaml/dune#1632, fix ocaml/dune#1617, @rgrinberg)

- When executing actions, open files lazily and close them as soon as
  possible in order to reduce the maximum number of file descriptors
  opened by Dune (ocaml/dune#1635, ocaml/dune#1643, fixes ocaml/dune#1633, @jonludlam, @rgrinberg,
  @diml)

- Reimplement the core of Dune using a new generic memoization system
  (ocaml/dune#1489, @rudihorn, @diml)

- Replace the broken cycle detection algorithm by a state of the art
  one from [this paper](https://doi.org/10.1145/2756553) (ocaml/dune#1489,
  @rudihorn)

- Get the correct environment node for multi project workspaces (ocaml/dune#1648,
  @rgrinberg)

- Add `dune compute` to call internal memoized functions (ocaml/dune#1528,
  @rudihorn, @diml)

- Add `--trace-file` option to trace dune internals (ocaml/dune#1639, fix ocaml/dune#1180, @emillon)

- Add `--no-print-directory` (borrowed from GNU make) to suppress
  `Entering directory` messages. (ocaml/dune#1668, @dra27)

- Remove `--stats` and track fd usage in `--trace-file` (ocaml/dune#1667, @emillon)

- Add virtual libraries feature and enable it by default (ocaml/dune#1430 fixes ocaml/dune#921,
  @rgrinberg)

- Fix handling of Control+C in watch mode (ocaml/dune#1678, fixes ocaml/dune#1671, @diml)

- Look for jsoo runtime in the same dir as the `js_of_ocaml` binary
  when the ocamlfind package is not available (ocaml/dune#1467, @nojb)

- Make the `seq` package available for OCaml >= 4.07 (ocaml/dune#1714, @rgrinberg)

- Add locations to error messages where a rule fails to generate targets and
  rules that require files outside the build/source directory. (ocaml/dune#1708, fixes
  ocaml/dune#848, @rgrinberg)

- Let `Configurator` handle `sizeof` (in addition to negative numbers).
  (ocaml/dune#1726, fixes ocaml/dune#1723, @Chris00)

- Fix an issue causing menhir generated parsers to fail to build in
  some cases. The fix is to systematically use `-short-paths` when
  calling `ocamlc -i` (ocaml/dune#1743, fix ocaml/dune#1504, @diml)

- Never raise when printing located errors. The code that would print the
  location excerpts was prone to raising. (ocaml/dune#1744, fix ocaml/dune#1736, @rgrinberg)

- Add a `dune upgrade` command for upgrading jbuilder projects to Dune
  (ocaml/dune#1749, @diml)

- When automatically creating a `dune-project` file, insert the
  detected name in it (ocaml/dune#1749, @diml)

- Add `(implicit_transitive_deps <bool>)` mode to dune projects. When this mode
  is turned off, transitive dependencies are not accessible. Only listed
  dependencies are directly accessible. (ocaml/dune#1734, ocaml/dune#430, @rgrinberg, @hnrgrgr)

- Add `toplevel` stanza. This stanza is used to define toplevels with libraries
  already preloaded. (ocaml/dune#1713, @rgrinberg)

- Generate `.merlin` files that account for normal preprocessors defined using a
  subset of the `action` language. (ocaml/dune#1768, @rgrinberg)

- Emit `(orig_src_dir <path>)` metadata in `dune-package` for dune packages
  built with `--store-orig-source-dir` command line flag (also controlled by
  `DUNE_STORE_ORIG_SOURCE_DIR` env variable). This is later used to generate
  `.merlin` with `S`-directives pointed to original source locations and thus
  allowing merlin to see those. (ocaml/dune#1750, @andreypopp)

- Improve the behavior of `dune promote` when the files to be promoted have been
  deleted. (ocaml/dune#1775, fixes ocaml/dune#1772, @diml)

- unstable-fmt: preserve comments (ocaml/dune#1766, @emillon)

- Pass flags correctly when using `staged_pps` (ocaml/dune#1779, fixes ocaml/dune#1774, @diml)

- Fix an issue with the use of `(mode promote)` in the menhir
  stanza. It was previously causing intermediate *mock* files to be
  promoted (ocaml/dune#1783, fixes ocaml/dune#1781, @diml)

- unstable-fmt: ignore files using OCaml syntax (ocaml/dune#1784, @emillon)

- Configurator: Add `which` function to replace the `which` command line utility
  in a cross platform way. (ocaml/dune#1773, fixes ocaml/dune#1705, @Chris00)

- Make configurator append paths to `$PKG_CONFIG_PATH` on macOS. Previously it
  was prepending paths and thus `$PKG_CONFIG_PATH` set by users could have been
  overridden by homebrew installed libraries (ocaml/dune#1785, @andreypopp)

- Disallow c/cxx sources that share an object file in the same stubs archive.
  This means that `foo.c` and `foo.cpp` can no longer exist in the same library.
  (ocaml/dune#1788, @rgrinberg)

- Forbid use of `%{targets}` (or `${@}` in jbuild files) inside
  preprocessing actions
  (ocaml/dune#1812, fixes ocaml/dune#1811, @diml)

- Add `DUNE_PROFILE` environment variable to easily set the profile. (ocaml/dune#1806,
  @rgrinberg)

- Deprecate the undocumented `(no_keep_locs)` field. It was only
  necessary until virtual libraries were supported (ocaml/dune#1822, fix ocaml/dune#1816,
  @diml)

- Rename `unstable-fmt` to `format-dune-file` and remove its `--inplace` option.
  (ocaml/dune#1821, @emillon).

- Autoformatting: `(using fmt 1.1)` will also format dune files (ocaml/dune#1821, @emillon).

- Autoformatting: record dependencies on `.ocamlformat-ignore` files (ocaml/dune#1824,
  fixes ocaml/dune#1793, @emillon)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants