Skip to content

Commit

Permalink
Merge pull request #48 from erikmd/packaging-coq-native
Browse files Browse the repository at this point in the history
CEP for packaging coq-native
  • Loading branch information
Zimmi48 authored Nov 27, 2020
2 parents 5c5f898 + bd40b83 commit f2e5103
Showing 1 changed file with 180 additions and 0 deletions.
180 changes: 180 additions & 0 deletions text/048-packaging-coq-native.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
- Title: Packaging coq with native_compute

- Drivers: Erik Martin-Dorel (**@erikmd**), Pierre Roux (**@proux01**)

- URL: <https://github.com/coq/ceps/pull/48>

----

# Motivation

Currently, the use of `native_compute` in libraries involving many dependencies is [inconvenient](https://github.com/coq/coq/issues/12564#issuecomment-647546401) (so that nobody actually uses this feature). Indeed, all their dependencies need to be recompiled with the `-native-compiler yes` option passed to `coqc`. And this needs to be done in a specific way for each dependency, depending on the build system it uses (see e.g., [the doc of `coq_makefile`](https://coq.inria.fr/refman/practical-tools/utilities.html#precompiling-for-native-compute)), if possible at all.

The overall aim of this proposal is to provide an `opam` virtual package (named e.g. `coq-native`) that users can install to automatically (re)compile everything with `native_compute` (no need for any manual `opam pin edit`).

# Summary

This CEP offers a new strategy for setting the default value for the `-native-compiler` option (in `coqc` and in the `opam` packaging).

The proposed design tackles the following two use cases:

1. Most users' (who don't even want to hear about `native_compute`) preferred behavior would be compiling the stdlib **and** subsequent Coq libraries with `-native-compiler no` by default.
2. `native_compute` users' preferred behavior would be to easily recompile all their libraries with `coqc -native-compiler yes` (while doing this currently with `opam` requires passing custom environment variables (if possible) which aren't the same across the build systems used by libraries, thus making the setup for efficiently using `native_compute` terribly unpractical).

Also, this proposal makes the configuration uniform across the platforms (while `native_compute` [was permanently disabled for macOS](https://github.com/ocaml/opam-repository/pull/16908) to workaround performance issues, cf. [coq/coq#11178](https://github.com/coq/coq/issues/11178)).

# Detailed design

The proposal is three-fold:

* **item 1.** Update the `coq` packaging in [ocaml/opam-repository](https://github.com/ocaml/opam-repository) so that Coq's standard library is compiled with `-native-compiler yes` only if an additional virtual package `coq-native` has been installed by the user.
* **item 2.** Extend the `./configure -native-compiler` options:
* option `./configure -native-compiler yes` now impacts the default value of option `coqc -native-compiler` (in order to precompile both stdlib and third-party libraries with `-native-compiler yes`);
* option `-native-compiler ondemand` (which becomes the default when compiling coq manually) preserves the previous default behavior (modulo the stdlib that is not precompiled anymore).
* **item 3.** Optionally: to enhance `native_compute` support with old versions of Coq (the releases of Coq before 8.13, where **item 2** was not implemented), update the `opam` packaging of the considered libraries.


## Regarding item 1:

* Add an opam metapackage `coq-native.1`:

```
opam-version: "2.0"
maintainer: "Erik Martin-Dorel"
authors: "Coq"
homepage: "https://coq.inria.fr/"
bug-reports: "https://github.com/coq/coq/issues"
conflicts: [
"coq" {< "8.5"}
]
synopsis: "Package flag enabling coq's native-compiler flag"
description: """
This package acts as a package flag for the ambient switch, taken into
account by coq (and possibly any coq library) to enable native_compute
at configure time, triggering the installation of .coq-native/* files
for the coq standard library and subsequent coq libraries.
This implements item 1 of CEP #48 <https://github.com/coq/ceps/pull/48>.
Remarks:
1. you might face with issues installing this package flag under macOS,
see <https://github.com/coq/coq/issues/11178>.
2. this package is not intended to be used as a dependency of other
packages (notably as installing or uninstalling this package may
trigger a rebuild of all coq packages in the ambient switch).
3. the option set by this package will be automatically propagated to
coqc for coq >= 8.13 (but the packaging of coq libraries for
earlier versions of coq may need an update: for details, see item 3
of CEP #48 <https://github.com/coq/ceps/pull/48>).
"""
```

* Add the following lines in the opam packages of `coq`:

```diff
diff --git a/packages/coq/coq.8.11.2/opam b/packages/coq/coq.8.11.2/opam
index fdb19e9da7..3d3dee7570 100644
--- a/packages/coq/coq.8.11.2/opam
+++ b/packages/coq/coq.8.11.2/opam
@@ -23,6 +23,9 @@ depends: [
"num"
"conf-findutils" {build}
]
+depopts: [
+ "coq-native"
+]
build: [
[
"./configure"
@@ -33,7 +36,9 @@ build: [
"-libdir" "%{lib}%/coq"
"-datadir" "%{share}%/coq"
"-coqide" "no"
- "-native-compiler" {os = "macos"} "no" {os = "macos"}
+ "-native-compiler" "yes" {coq-native:installed} "no" {!coq-native:installed}
]
[make "-j%{jobs}%"]
[make "-j%{jobs}%" "byte"]
```

## Regarding item 2:

The `coqc` option `-native-compiler ondemand` corresponds to the default behavior since [4ad6855](https://github.com/coq/coq/commit/4ad6855504db2ce15a474bd646e19151aa8142e2) (8.5beta3).

The following array, adapted from [this coq/coq#12564 comment](https://github.com/coq/coq/issues/12564#issuecomment-647464937) (and [that other one](https://github.com/coq/coq/issues/12564#issuecomment-647485222)), summarizes all behaviors (the changes are highlighted in bold):

| `configure (<8.13)` | `configure (>=8.13)` | `coqc` | outcome | requirements |
| --- | --- | --- | --- | --- |
| *N/A* | **yes** | yes (default if omitted) | `.coq-native/*` + temporary (when calling `native_compute`) | dependencies should be compiled with the same native flags |
| *N/A* | **yes** | ondemand | temporary | none |
| *N/A* | **yes** | no | none | none |
| yes | **ondemand** | yes | `.coq-native/*` + temporary (when calling `native_compute`) | dependencies should be compiled with the same native flags |
| yes | **ondemand** | ondemand (default if omitted) | temporary | none |
| yes | **ondemand** | no | none | none |
| no | no | yes | none | none |
| no | no | ondemand | none | none |
| no | no | no | none | none |

Note also that (for each version of coq), **the stdlib is only precompiled with `./configure -native-compiler yes`**. It is not precompiled with `./configure -native-compiler ondemand` for `coq >= 8.13`.

[PR coq/coq#13352](https://github.com/coq/coq/pull/13352) implements this item.

## Regarding item 3:

Assuming we want to use `native_compute` on Coq < 8.13 with `coq-mathcomp-ssreflect` (or any library built with `coq_makefile`), the `opam` file has to be extended like this (see e.g. [Coq's refman](https://coq.github.io/doc/master/refman/practical-tools/utilities.html?highlight=coq_makefile#precompiling-for-native-compute)):

```diff
diff --git a/packages/coq-mathcomp-ssreflect/coq-mathcomp-ssreflect.1.10.0/opam b/packages/coq-mathcomp-ssreflect/coq-mathcomp-ssreflect.1.10.0/opam
--- a/packages/coq-mathcomp-ssreflect/coq-mathcomp-ssreflect.1.10.0/opam
+++ b/packages/coq-mathcomp-ssreflect/coq-mathcomp-ssreflect.1.10.0/opam
@@ -6,7 +6,8 @@
dev-repo: "git+https://github.com/math-comp/math-comp.git"
license: "CeCILL-B"

-build: [ make "-C" "mathcomp/ssreflect" "-j" "%{jobs}%" ]
+build: [ make "-C" "mathcomp/ssreflect" "-j" "%{jobs}%" "COQEXTRAFLAGS+=-native-compiler yes" {coq-native:installed}]
install: [ make "-C" "mathcomp/ssreflect" "install" ]
depends: [ "coq" { (>= "8.7" & < "8.12~") } ]
```

Doing this, one can notice that the appropriate `.coq-native` directory has successfully been installed along the `.vo` of the library:

```bash
find "$(opam config var lib)" -name ".coq-native" | grep ssreflect
```

# Note to library developers and package maintainers

To fully benefit from `native_compute` with a library using Coq 8.5+, some (`opam`) packaging update may be required for this library's dependencies:

- for `coq_makefile`: no change required for Coq 8.13+; otherwise follow **item 3** above (related to Section [Precompiling for `native_compute`](https://coq.github.io/doc/master/refman/practical-tools/utilities.html?highlight=coq_makefile#precompiling-for-native-compute) in Coq refman);
- for `dune / coq.theory`: this will require Coq 8.12.1+ and a version of `dune` implementing [PR ocaml/dune#3210](https://github.com/ocaml/dune/pull/3210) (cf. [this comment](https://github.com/coq/ceps/pull/48#issuecomment-727020253) by **@ejgallego**); otherwise (without native support), Dune will just ignore the native parts and no `./coq-native/*.cmxs` file will be installed.

Note that these changes could be performed directly in the existing packages gathered in the [coq/opam-coq-archive](https://github.com/coq/opam-coq-archive) repository.

# Alternatives

* A different but related idea was mentioned in [Zulip](https://coq.zulipchat.com/#narrow/stream/237656-Coq-devs.20.26.20plugin.20devs/topic/Coq-as-compiler/near/216196895): "OPAM: try out coq as a compiler" ([PR coq/opam-coq-archive#595](https://github.com/coq/opam-coq-archive/issues/595)).
* This would require opam 2.0 (which is not a drawback).
* This could be viewed as an alternative of this CEP's package flag.
* Unfortunately, this alternative would be even coarser than this CEP (as all opam packages, not only those of coq libraries, would be recompiled).

* A new strategy, called `split-native`, has been discussed in the [CEP PR](https://github.com/coq/ceps/pull/48):
* Assume a coq package `foo2` depends on `foo1`; there would be two extra packages `foo2-native` and `foo1-native`, with at least the following dependencies:
* `foo2` → `foo1`
* `foo2-native` → `foo1-native`
* `foo2-native` → `foo2`
* `foo1-native` → `foo1`
* This idea relies on the ability to generate `./coq-native/*.cmxs` directly from the `.vo` files.
* A PoC of this idea has been implemented in [PR coq/coq#13287](https://github.com/coq/coq/pull/13287).
* Yet this PR won't be ready for Coq 8.13, and it will also require some extra tooling, to automatically generate the `*-native` packages, and more generally keep `coq/opam-coq-archive` maintenance tractable.
* And there might be some corner cases where, e.g., package `foo` contains both `A.v` and `B.v`, `B` requires `A` and relies on `native_compute`.
* Finally, the implementation of the `coqc -native-compiler ondemand` setting could be optimized.

# Conclusion and perspectives

* This CEP was discussed at the 2020-11-13 weekly Coq call, in order to provide full-blown `native_compute` support for the Coq 8.13 release (cf. [PR coq/coq#13352](https://github.com/coq/coq/pull/13352)).
* The Coq team agreed on considering this CEP for Coq 8.13, while the `split-native` strategy could be further developed for a later Coq release.

*Note:* at the time this CEP is written, the Coq refman still lacks some documentation of the `-native-compiler` option; but progress on this is tracked in issue [coq/coq#12564](https://github.com/coq/coq/issues/12564); and that doc might incorporate [the array above](#regarding-item-2).

0 comments on commit f2e5103

Please sign in to comment.