diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 20a0ef5d6e6..ecac9d804b2 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -270,6 +270,36 @@ jobs: # We disable the Dune cache when running the tests DUNE_CACHE: disabled + rocq: + name: Rocq Language (Rocq 9.1.0) + runs-on: ubuntu-latest + strategy: + matrix: + include: + # Keep packages and OCaml version in sync with the version + # in the makefile; rocq-stdlib should be easy to remove + - ocaml-compiler: 5.3 + opam-packages: rocq-core.9.1.0 rocq-stdlib.9.0.0 csexp re spawn pp uutf + test-target: test-rocq + - ocaml-compiler: 4.14 + opam-packages: rocq-core.9.1.0 rocq-stdlib.9.0.0 csexp re spawn pp uutf rocq-native + test-target: test-rocq-native + steps: + - name: Checkout Code + uses: actions/checkout@v5 + - name: Setup OCaml + uses: ocaml/setup-ocaml@v3 + with: + ocaml-compiler: ${{ matrix.ocaml-compiler }} + dune-cache: true + - name: install Rocq Prover + run: opam install -y ${{ matrix.opam-packages }} + - name: test Rocq Prover Build Language + run: opam exec -- make ${{ matrix.test-target }} + env: + # We disable the Dune cache when running the tests + DUNE_CACHE: disabled + wasm: name: Wasm_of_ocaml needs: nix-build diff --git a/Makefile b/Makefile index e7254ed0c49..9ce30a9ec85 100644 --- a/Makefile +++ b/Makefile @@ -100,17 +100,26 @@ test-js: $(BIN) test-wasm: $(BIN) DUNE_WASM_TEST=enable $(BIN) build @runtest-wasm +.PHONY: test-coq test-coq: $(BIN) DUNE_COQ_TEST=enable $(BIN) build @runtest-coq +.PHONY: test-rocq +test-rocq: $(BIN) + DUNE_ROCQ_TEST=enable $(BIN) build @runtest-rocq + +.PHONY: test-rocq-native +test-rocq-native: $(BIN) + DUNE_ROCQ_NATIVE_TEST=enable $(BIN) build @runtest-rocq-native + test-melange: $(BIN) $(BIN) build @runtest-melange test-all: $(BIN) - $(BIN) build @runtest @runtest-js @runtest-coq @runtest-melange + $(BIN) build @runtest @runtest-js @runtest-coq @runtest-rocq @runtest-melange test-all-sans-melange: $(BIN) - $(BIN) build @runtest @runtest-js @runtest-coq + $(BIN) build @runtest @runtest-js @runtest-coq @runtest-rocq test-ox: $(BIN) $(BIN) runtest test/blackbox-tests/test-cases/oxcaml diff --git a/bin/main.ml b/bin/main.ml index b52b5681e33..93d5536c15c 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -30,6 +30,7 @@ let all : _ Cmdliner.Cmd.t list = let groups = [ Ocaml.Ocaml_cmd.group ; Coq.Group.group + ; Rocq.group ; Describe.group ; Describe.Show.group ; Rpc.Group.group diff --git a/bin/printenv.ml b/bin/printenv.ml index fce6b79d6b6..2315b5067ee 100644 --- a/bin/printenv.ml +++ b/bin/printenv.ml @@ -29,6 +29,9 @@ let dump sctx ~dir = and+ coq_dump = Dune_rules.Coq.Coq_rules.coq_env ~dir >>| Dune_rules.Coq.Coq_flags.dump ~dir:(Path.build dir) + and+ rocq_dump = + Dune_rules.Rocq.Rocq_rules.rocq_env ~dir + >>| Dune_rules.Rocq.Rocq_flags.dump ~dir:(Path.build dir) and+ jsoo_js_dump = let module Js_of_ocaml = Dune_lang.Js_of_ocaml in let* jsoo = Action_builder.of_memo (Dune_rules.Jsoo_rules.jsoo_env ~dir ~mode:JS) in @@ -45,6 +48,7 @@ let dump sctx ~dir = ; link_flags_dump ; menhir_dump ; coq_dump + ; rocq_dump ; jsoo_js_dump ; jsoo_wasm_dump ] diff --git a/bin/rocq/rocq.ml b/bin/rocq/rocq.ml new file mode 100644 index 00000000000..b88f38a70df --- /dev/null +++ b/bin/rocq/rocq.ml @@ -0,0 +1,20 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import + +let doc = "Command group related to Rocq." +let sub_commands_synopsis = Common.command_synopsis [ "rocq top FILE -- ARGS" ] +let man = [ `Blocks sub_commands_synopsis ] +let info = Cmd.info ~doc ~man "rocq" +let group = Cmd.group info [ Rocqtop.command ] diff --git a/bin/rocq/rocq.mli b/bin/rocq/rocq.mli new file mode 100644 index 00000000000..984d98dc11e --- /dev/null +++ b/bin/rocq/rocq.mli @@ -0,0 +1,16 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import + +val group : unit Cmd.t diff --git a/bin/rocq/rocqtop.ml b/bin/rocq/rocqtop.ml new file mode 100644 index 00000000000..4262a10b6ac --- /dev/null +++ b/bin/rocq/rocqtop.ml @@ -0,0 +1,174 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import + +let doc = "Execute a Rocq toplevel with the local configuration." + +let man = + [ `S "DESCRIPTION" + ; `P + {|$(b,dune rocq top FILE -- ARGS) runs the Rocq toplevel to process the + given $(b,FILE). The given arguments are completed according to the + local configuration. This is equivalent to running $(b,rocq top ARGS) + with a $(b,_RocqProject) file containing the local configurations + from the $(b,dune) files, but does not require maintaining a + $(b,_RocqProject) file.|} + ; `Blocks Common.help_secs + ] +;; + +let info = Cmd.info "top" ~doc ~man + +let term = + let+ default_builder = Common.Builder.term + and+ context = + let doc = Some "Run the Rocq toplevel in this build context." in + Common.context_arg ~doc + and+ rocqtop = + let doc = Some "Run the given toplevel command instead of the default." in + Arg.(value & opt string "rocq" & info [ "toplevel" ] ~docv:"CMD" ~doc) + and+ rocq_file_arg = + Arg.(required & pos 0 (some string) None (Arg.info [] ~doc:None ~docv:"ROCQFILE")) + and+ extra_args = + Arg.(value & pos_right 0 string [] (Arg.info [] ~doc:None ~docv:"ARGS")) + and+ no_rebuild = + Arg.( + value + & flag + & info [ "no-build" ] ~doc:(Some "Don't rebuild dependencies before executing.")) + in + let common, config = + let builder = + if no_rebuild then Common.Builder.forbid_builds default_builder else default_builder + in + Common.init builder + in + let rocq_file_arg = Common.prefix_target common rocq_file_arg |> Path.Local.of_string in + let rocqtop, args, env = + Scheduler.go_with_rpc_server ~common ~config + @@ fun () -> + let open Fiber.O in + let* setup = Import.Main.setup () in + let* setup = Memo.run setup in + let sctx = Import.Main.find_scontext_exn setup ~name:context in + let context = Dune_rules.Super_context.context sctx in + let rocq_file_build = + Path.Build.append_local (Context.build_dir context) rocq_file_arg + in + let dir = + (match Path.Local.parent rocq_file_arg with + | None -> Path.Local.root + | Some dir -> dir) + |> Path.Build.append_local (Context.build_dir context) + in + let* rocqtop, rocq_arg, args, env = + build_exn + @@ fun () -> + let open Memo.O in + let* (tr : Dune_rules.Dir_contents.triage) = + Dune_rules.Dir_contents.triage sctx ~dir + in + let dir = + match tr with + | Group_part dir -> dir + | Standalone_or_root _ -> dir + in + let* dc = Dune_rules.Dir_contents.get sctx ~dir in + let* rocq_src = Dune_rules.Dir_contents.rocq dc in + let rocq_module = + let source = rocq_file_build in + match Dune_rules.Rocq.Rocq_sources.find_module ~source rocq_src with + | Some m -> snd m + | None -> + let hints = + [ Pp.textf "Is the file part of a stanza?" + ; Pp.textf "Has the file been written to disk?" + ] + in + User_error.raise + ~hints + [ Pp.textf "Cannot find file: %s" (rocq_file_arg |> Path.Local.to_string) ] + in + let stanza = Dune_rules.Rocq.Rocq_sources.lookup_module rocq_src rocq_module in + let args, use_stdlib, wrapper_name, mode = + match stanza with + | None -> + User_error.raise + [ Pp.textf + "File not part of any stanza: %s" + (rocq_file_arg |> Path.Local.to_string) + ] + | Some (`Theory theory) -> + ( Dune_rules.Rocq.Rocq_rules.rocqtop_args_theory + ~sctx + ~dir + ~dir_contents:dc + theory + rocq_module + , theory.buildable.use_stdlib + , Dune_rules.Rocq.Rocq_lib_name.wrapper (snd theory.name) + , theory.buildable.mode ) + | Some (`Extraction extr) -> + ( Dune_rules.Rocq.Rocq_rules.rocqtop_args_extraction ~sctx ~dir extr rocq_module + , extr.buildable.use_stdlib + , "DuneExtraction" + , extr.buildable.mode ) + in + (* Run rocqdep *) + let* (_ : unit * Dep.Fact.t Dep.Map.t) = + let deps_of = + if no_rebuild + then Action_builder.return () + else ( + let mode = + match mode with + | None -> Dune_rules.Rocq.Rocq_mode.VoOnly + | Some mode -> mode + in + Dune_rules.Rocq.Rocq_rules.deps_of + ~dir + ~use_stdlib + ~wrapper_name + ~mode + rocq_module) + in + Action_builder.evaluate_and_collect_facts deps_of + in + let real_binary, rocq_arg = + if String.equal "rocq" rocqtop then "rocq", [ "top" ] else rocqtop, [] + in + let* prog = Super_context.resolve_program_memo sctx ~dir ~loc:None real_binary in + let prog = Action.Prog.ok_exn prog in + let* () = Build_system.build_file prog in + (* Get args *) + let* (args, _) : string list * Dep.Fact.t Dep.Map.t = + let* args = args in + let dir = Path.external_ Path.External.initial_cwd in + let args = Dune_rules.Command.expand ~dir (S args) in + Action_builder.evaluate_and_collect_facts args.build + in + let+ env = Super_context.context_env sctx in + Path.to_string prog, rocq_arg, args, env + in + (* Careful about the first argument to "rocq" *) + let args = + let topfile = Path.to_absolute_filename (Path.build rocq_file_build) in + rocq_arg @ ("-topfile" :: topfile :: args) @ extra_args + in + Fiber.return (rocqtop, args, env) + in + restore_cwd_and_execve (Common.root common) rocqtop args env +;; + +let command = Cmd.v info term diff --git a/bin/rocq/rocqtop.mli b/bin/rocq/rocqtop.mli new file mode 100644 index 00000000000..8d039c75e5e --- /dev/null +++ b/bin/rocq/rocqtop.mli @@ -0,0 +1,16 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import + +val command : unit Cmd.t diff --git a/doc/changes/added/12035.md b/doc/changes/added/12035.md new file mode 100644 index 00000000000..72a4e56ac01 --- /dev/null +++ b/doc/changes/added/12035.md @@ -0,0 +1,7 @@ +- New `(lang rocq)` build mode for Rocq 9.0 and later. This new mode + is very similar to the existing `(lang coq)`, except that it doesn't + need the `coq*` compatibility wrappers. As of today `(lang rocq)` + doesn't support yet composed builds with Rocq itself, this will be + added later. `(lang coq)` is deprecated, development is frozen, and + will be removed at some point in the future. (#12035, @ejgallego, + @lysxia, fixes #11572) diff --git a/doc/concepts/variables.rst b/doc/concepts/variables.rst index 19f82c88c37..878abc2d44c 100644 --- a/doc/concepts/variables.rst +++ b/doc/concepts/variables.rst @@ -75,7 +75,8 @@ Dune supports the following variables: variable ````, or ```` if it does not exist. For example, ``%{env:BIN=/usr/bin}``. Available since Dune 1.4.0. -- There are some Coq-specific variables detailed in :ref:`coq-variables`. +- There are some Rocq-specific and Coq-specific variables detailed in + :ref:`rocq-variables` and :ref:`coq-variables`. In addition, ``(action ...)`` fields support the following special variables: diff --git a/doc/coq.rst b/doc/coq.rst index 01cca1a3754..a4a5e2f2f92 100644 --- a/doc/coq.rst +++ b/doc/coq.rst @@ -14,6 +14,10 @@ Coq Introduction ------------ +**Note**: the Dune Coq mode has been replaced by Dune's :ref:`Rocq +mode`, following the renaming of Coq into Rocq. We strongly +recommend all users to migrate to this mode. + Dune can build Coq theories and plugins with additional support for extraction and ``.mlg`` file preprocessing. @@ -93,11 +97,12 @@ The semantics of the fields are: same theory don't see the ``foo.Bar`` prefix in the same way that OCaml ``wrapped`` libraries do. - For compatibility, :ref:`Coq lang 1.0` installs a theory named - ``foo.Bar`` under ``foo/Bar``. Also note that Coq supports composing a module - path from different theories, thus you can name a theory ``foo.Bar`` and a - second one ``foo.Baz``, and Dune composes these properly. See an example of - :ref:`a multi-theory` Coq project for this. + For compatibility, we install a theory named ``foo.Bar`` under + ``foo/Bar``. Also note that Coq supports composing a module path + from different theories, thus you can name a theory ``foo.Bar`` and + a second one ``foo.Baz``, and Dune composes these properly. See an + example of :ref:`a multi-theory` Coq project + for this. - The ``modules`` field allows one to constrain the set of modules included in the theory, similar to its OCaml counterpart. Modules are specified in Coq @@ -106,10 +111,10 @@ The semantics of the fields are: - If the ``package`` field is present, Dune generates install rules for the ``.vo`` files of the theory. ``pkg_name`` must be a valid package name. - Note that :ref:`Coq lang 1.0` will use the Coq legacy install - setup, where all packages share a common root namespace and install directory, - ``lib/coq/user-contrib/``, as is customary in the Make-based - Coq package ecosystem. + Note that we use the Coq install setup, where all packages share a + common root namespace and install directory, + ``lib/coq/user-contrib/``, as is customary in the + Make-based Coq package ecosystem. For compatibility, Dune also installs, under the ``user-contrib`` prefix, the ``.cmxs`` files that appear in ````. This will be dropped in @@ -377,9 +382,10 @@ The Coq lang can be modified by adding the following to a The supported Coq language versions (not the version of Coq) are: -- ``0.11``: Support for the ``(coqdoc_header ...)`` and ``(coqdoc_footer ...)`` - fields, for ``_CoqProject`` file generation, and multiple modules in - ``(modules_flags ...)``. +- ``0.11``: Rocq mode. Support for the ``(coqdoc_header ...)`` and + ``(coqdoc_footer ...)`` fields, for ``_CoqProject`` file generation, + and multiple modules in ``(modules_flags ...)``. + See Rocq mode manual for more details - ``0.10``: Support for the ``(coqdep_flags ...)`` field. - ``0.9``: Support for per-module flags with the ``(modules_flags ...)`` field, limited to a single module due to a bug. @@ -401,17 +407,6 @@ Deprecated experimental Coq language versions are: and ``(mode native)`` is deprecated. The ``dev`` profile also no longer disables native compilation. -.. _coq-lang-1.0: - -Coq Language Version 1.0 -~~~~~~~~~~~~~~~~~~~~~~~~ - -Guarantees with respect to stability are not yet provided, but we -intend that the ``(0.8)`` version of the language becomes ``1.0``. -The ``1.0`` version of Coq lang will commit to a stable set of -functionality. All the features below are expected to reach ``1.0`` -unchanged or minimally modified. - .. _coq-extraction: coq.extraction diff --git a/doc/dune.inc b/doc/dune.inc index 2a6608db1ab..ec405cc6fc3 100644 --- a/doc/dune.inc +++ b/doc/dune.inc @@ -215,6 +215,15 @@ (package dune) (files dune-promotion.1)) +(rule + (with-stdout-to dune-rocq.1 + (run dune rocq --help=groff))) + +(install + (section man) + (package dune) + (files dune-rocq.1)) + (rule (with-stdout-to dune-rpc.1 (run dune rpc --help=groff))) diff --git a/doc/hacking.rst b/doc/hacking.rst index 732d1bf3305..bb89c83d9ad 100644 --- a/doc/hacking.rst +++ b/doc/hacking.rst @@ -194,6 +194,10 @@ We have the following shells for specific tasks: - For running the Coq tests, you can use ``nix develop .#coq``. NB: Coq native is not currently installed; this will cause some of the tests to fail. It's currently better to fallback to opam in this case. +- We don't have yet a Nix setup for running the Rocq tests, as of + today, there are two classes of tests: + + ``make test-rocq``: these work well on a regular Dune opam dev switch + + ``make test-rocq-native``: these require the Rocq native compiler to run, and thus need OCaml 4.x Releasing Dune ============== diff --git a/doc/reference/cli.rst b/doc/reference/cli.rst index 4831085e528..9b52e1a0489 100644 --- a/doc/reference/cli.rst +++ b/doc/reference/cli.rst @@ -24,6 +24,14 @@ documentation for each command is available through ``dune COMMAND --help``. Clean the project. +.. describe:: dune rocq + + Command group related to Rocq. + + .. describe:: dune rocq top + + Execute a Rocq toplevel with the local configuration. + .. describe:: dune coq Command group related to Coq. diff --git a/doc/reference/dune-project/using.rst b/doc/reference/dune-project/using.rst index a32241f1795..3d14abde320 100644 --- a/doc/reference/dune-project/using.rst +++ b/doc/reference/dune-project/using.rst @@ -6,7 +6,7 @@ using Enable a dune language extension. The language of configuration files read by Dune can be extended to support - additional stanzas (e.g., ``menhir``, ``coq.theory``, ``mdx``). + additional stanzas (e.g., ``menhir``, ``rocq.theory``, ``mdx``). `` is the name of the plugin that defines this stanza and `` describes the configuration language's version. Note that this diff --git a/doc/reference/dune/dynamic_include.rst b/doc/reference/dune/dynamic_include.rst index 2ff42daf062..fd342c1f65c 100644 --- a/doc/reference/dune/dynamic_include.rst +++ b/doc/reference/dune/dynamic_include.rst @@ -26,6 +26,6 @@ directory. The following stanzas cannot be dynamically generated: -* Libraries, coq theories, library redirects +* Libraries, Rocq and Coq theories, library redirects * Public executables or install section with the ``bin`` section * Plugin stanzas diff --git a/doc/reference/dune/env.rst b/doc/reference/dune/env.rst index a0474c5bd19..16ded42703b 100644 --- a/doc/reference/dune/env.rst +++ b/doc/reference/dune/env.rst @@ -86,6 +86,9 @@ Fields supported in ```` are: - ``(odoc )`` allows passing options to ``odoc``. See :ref:`odoc-options` for more details. +- ``(rocq )`` allow passing options to Coq. See :ref:`rocq-env` + for more details. + - ``(coq )`` allow passing options to Coq. See :ref:`coq-env` for more details. diff --git a/doc/reference/dune/index.rst b/doc/reference/dune/index.rst index 71ead589c57..351e7c68b5e 100644 --- a/doc/reference/dune/index.rst +++ b/doc/reference/dune/index.rst @@ -69,6 +69,7 @@ The following pages describe the available stanzas and their meanings. :maxdepth: 1 cinaps + rocq_theory coq_theory mdx menhir diff --git a/doc/reference/dune/rocq_theory.rst b/doc/reference/dune/rocq_theory.rst new file mode 100644 index 00000000000..fb72ac21957 --- /dev/null +++ b/doc/reference/dune/rocq_theory.rst @@ -0,0 +1,5 @@ +rocq.theory +----------- + +See the documentation on the :ref:`rocq-theory`, :ref:`rocq-extraction`, +:ref:`rocq-pp`, and related stanzas. diff --git a/doc/reference/index.rst b/doc/reference/index.rst index a374c4363bd..2d0db3a5bd8 100644 --- a/doc/reference/index.rst +++ b/doc/reference/index.rst @@ -74,6 +74,7 @@ These documents specify the various features and languages present in Dune. :maxdepth: 1 :caption: Integrations + ../rocq ../coq ../rpc packages diff --git a/doc/rocq.rst b/doc/rocq.rst new file mode 100644 index 00000000000..bf41710cd39 --- /dev/null +++ b/doc/rocq.rst @@ -0,0 +1,843 @@ +.. _rocq: + +****************************** +The Rocq Prover Build Language +****************************** + +.. TODO(diataxis) + + This looks like there are several components in there: + + - reference info for stanzas and variables + - tutorials (the examples part) + +Introduction +------------ + +Dune can build Rocq theories and plugins with additional support for extraction +and ``.mlg`` file preprocessing. + +A *Rocq theory* is a collection of ``.v`` files that define Rocq modules whose +names share a common prefix. The module names reflect the directory hierarchy. + +Rocq theories may be defined using :ref:`rocq.theory` stanzas, or be +auto-detected by Dune by inspecting Rocq's install directories. + +A *Rocq plugin* is an OCaml :doc:`/reference/dune/library` that Rocq can +load dynamically at runtime. Plugins are typically linked with the Rocq OCaml +API. + +Rocq plugins need to be "public" libraries in Dune's terminology, that +is to say, they must declare a ``public_name`` field; this is +necessary as they are located using ``ocamlfind``. + +A *Rocq project* is an informal term for a +:doc:`/reference/dune-project/index` containing a collection of Rocq +theories and plugins. + +The ``.v`` files of a theory need not be present as source files. They may also +be Dune targets of other rules. + +To enable Rocq support in a Dune project, specify the :ref:`Rocq language +version` in the :doc:`/reference/dune-project/index` file. For +example, adding + +.. code:: dune + + (using rocq 0.11) + +to a :doc:`/reference/dune-project/index` file enables using the +``rocq.theory`` stanza and other ``rocq.*`` stanzas. See the :ref:`Dune Rocq +language` section for more details. + +.. _rocq-theory: + +rocq.theory +----------- + +The Rocq theory stanza is very similar in form to the OCaml +:doc:`/reference/dune/library` stanza: + +.. code:: dune + + (rocq.theory + (name ) + (package ) + (synopsis ) + (modules ) + (plugins ) + (flags ) + (modules_flags ) + (generate_project_file) + (rocqdep_flags ) + (rocqdoc_flags ) + (rocqdoc_header ) + (rocqdoc_footer ) + (stdlib ) + (mode ) + (theories )) + +The stanza builds all the ``.v`` files in the given directory and its +subdirectories if the :ref:`include-subdirs ` stanza is +present. + +For usage of this stanza, see the :ref:`rocq-examples`. + +The semantics of the fields are: + +- ```` is a dot-separated list of valid Rocq module names and + determines the module scope under which the theory is compiled (this + corresponds to Rocq's ``-R`` option). + + For example, if ```` is ``foo.Bar``, the theory modules are + named ``foo.Bar.module1``, ``foo.Bar.module2``, etc. Note that modules in the + same theory don't see the ``foo.Bar`` prefix in the same way that OCaml + ``wrapped`` libraries do. + + For compatibility, :ref:`Rocq lang 1.0` installs a theory named + ``foo.Bar`` under ``foo/Bar``. Also note that Rocq supports composing a module + path from different theories, thus you can name a theory ``foo.Bar`` and a + second one ``foo.Baz``, and Dune composes these properly. See an example of + :ref:`a multi-theory` Rocq project for this. + +- The ``modules`` field allows one to constrain the set of modules included in + the theory, similar to its OCaml counterpart. Modules are specified in Rocq + notation. That is to say, ``A/b.v`` is written ``A.b`` in this field. + +- If the ``package`` field is present, Dune generates install rules for the + ``.vo`` files of the theory. ``pkg_name`` must be a valid package name. + + Note that :ref:`Rocq lang 1.0` uses the Rocq install + setup, where all packages share a common root namespace and install + directory, ``lib/rocq/user-contrib/``, as is + customary in the Make-based Rocq package ecosystem. + + For compatibility, Dune also installs, under the ``user-contrib`` prefix, the + ``.cmxs`` files that appear in ````. This will be dropped in + future versions. + +- ```` are passed to ``rocqc`` as command-line options. ``:standard`` + is taken from the value set in the ``(rocq (flags ))`` field in ``env`` + profile. See :doc:`/reference/dune/env` for more information. + +- ```` is a list of pairs of valid Rocq module names and a + list of ````. Note that if a module is present here, the + ``:standard`` variable will be bound to the value of ```` + effective for the theory. This way it is possible to override the + default flags for particular files of the theory, for example: + + .. code:: dune + + (rocq.theory + (name Foo) + (modules_flags + (bar (:standard \ -quiet)))) + + + It is more common to just use this field to *add* some particular + flags, but that should be done using ``(:standard + ...)`` as to propagate the default flags. + +- ```` are extra user-configurable flags passed to ``rocqdep``. The + default value for ``:standard`` is empty. This field exists for transient + use-cases, in particular disabling ``rocqdep`` warnings, but it should not be + used in normal operations. + +- ```` are extra user-configurable flags passed to ``rocqdoc``. The + default value for ``:standard`` is ``--toc``. The ``--html`` or ``--latex`` + flags are passed separately depending on which mode is target. See the section + on :ref:`documentation using rocqdoc` for more information. + +- ```` is a file passed to ``rocqdoc`` using the ``--with-header`` + option, to configure a custom HTML header for the generated HTML pages. + +- ```` is a file passed to ``rocqdoc`` using the ``--with-footer`` + option, to configure a custom HTML footer for the generated HTML pages. + +- ```` can either be ``yes`` or ``no``, currently defaulting to + ``yes``. When set to ``no``, Rocq's standard library won't be visible from this + theory, which means the ``Rocq`` prefix won't be bound, and + ``Rocq.Init.Prelude`` won't be imported by default. + +- If the ``plugins`` field is present, Dune will pass the corresponding flags to + Rocq so that ``rocqdep`` and ``rocqc`` can find the corresponding OCaml libraries + declared in ````. This allows a Rocq theory to depend on OCaml + plugins. The field must contain a public library name. + +- Your Rocq theory can depend on other theories --- globally installed or defined + in the current workspace --- by adding the theories names to the + ```` field. Then, Dune will ensure that the depended theories + are present and correctly registered with Rocq. + + See :ref:`Locating Theories` for more information on how + Rocq theories are located by Dune. + +- The ```` field does control what Rocq objects are + built. Allowed values are ``vo`` or ``vos``. + + By default, Dune will build Rocq's ``.vo`` and ``.glob`` files. + + If Rocq was configured with ``-native-compiler yes``, Dune will + also build the corresponding ``cmxs`` native files. + + You may disable the compilation of native objects in this case by + specifying ``(mode vo)``, which can bring an important speedup in some cases. + + If ``(mode vos)`` is set, Dune will instead output ``.vos`` + interface files, which skip proof checking. + +- If the ``(generate_project_file)`` is present, a ``_RocqProject`` file is + generated in the Rocq theory's directory (it is promoted to the source tree). + This file should be suitable for editor compatibility, and it provides an + alternative to using ``dune rocq top``. It is however limited in two ways: it + is incompatible with the ``(modules_flags ...)`` field, and it cannot be + used for two Rocq theories declared in the same directory. + +Rocq Dependencies +~~~~~~~~~~~~~~~~~ + +When a Rocq file ``a.v`` depends on another file ``b.v``, Dune is able to build +them in the correct order, even if they are in separate theories. Under the +hood, Dune asks rocqdep how to resolve these dependencies, which is why it is +called once per theory. + +.. _rocqdoc: + +Rocq Documentation +~~~~~~~~~~~~~~~~~~ + +Given a :ref:`rocq-theory` stanza with ``name A``, Dune will produce two +*directory targets*, ``A.html/`` and ``A.tex/``. HTML or LaTeX documentation for +a Rocq theory may then be built by running ``dune build A.html`` or ``dune build +A.tex``, respectively (if the :doc:`dune file ` for the +theory is the current directory). + +There are also two aliases :doc:`/reference/aliases/doc` and ``@doc-latex`` +that will respectively build the HTML or LaTeX documentation when called. These +will determine whether or not Dune passes a ``--html`` or ``--latex`` flag to +``rocqdoc``. + +Further flags can also be configured using the ``(rocqdoc_flags)`` field in the +``rocq.theory`` stanza. These will be passed to ``rocqdoc`` and the default value +is ``:standard`` which is ``--toc``. Extra flags can therefore be passed by +writing ``(rocqdoc_flags :standard --body-only)`` for example. + +When building the HTML documentation, flags ``(rocqdoc_header)`` and +``(rocqdoc_footer)`` can also be used to configure a custom HTML header or +footer respectively. + +.. _include-subdirs-rocq: + +Recursive Qualification of Modules +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you add: + +.. code:: dune + + (include_subdirs qualified) + +to a :doc:`/reference/dune/index` file, Dune considers all the modules in +the directory and its subdirectories, adding a prefix to the module name in the +usual Rocq style for subdirectories. For example, file ``A/b/C.v`` becomes the +module ``A.b.C``. + +.. _rocq-locating-theories: + +How Dune Locates and Builds theories +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Dune organises it's knowledge about Rocq theories in 3 databases: + +- Scope database: A Dune *scope* is a part of the project sharing a single + common ``dune-project`` file. In a single scope, any theory in the database + can depend on any other theory in that database as long as their visibilities + are compatible. A public theory for example cannot depend on a private + theory. + +- Public theory database: The set of all scopes that Dune knows about is termed + a *workspace*. Only public theories coming from scopes are added to the + database of all public theories in the current workspace. + + The public theory database allows theories to depend on theories that are in + a different scope. Thus, you can depend on theories belonging to another + :doc:`/reference/dune-project/index` as long as they share a common + scope under another :doc:`/reference/dune-project/index` file or a + :doc:`/reference/dune-workspace/index` file. + + Doing so is usually as simple as placing a Rocq project within the scope of + another. This process is termed *composition*. See the :ref:`interproject + composition` example. + + Inter-project composition allows Dune to compute module dependencies using a + fine granularity. In practice, this means that Dune will only build the parts + of a depended theory that are needed by your project. + +- Installed theory database: If a theory cannot be found in the list of + workspace-public theories, Dune will try to locate the theory in the list of + installed locations Rocq knows about. + + This list is built using the output of ``rocqc --config`` in order to infer + the ``ROCQLIB`` and ``ROCQPATH`` environment variables. Each path in ``ROCQPATH`` + and ``ROCQLIB/user-contrib`` is used to build the database of installed + theories. + + Note that, for backwards compatibility purposes, installed theories do not + have to be installed or built using Dune. Dune tries to infer the name of the + theory from the installed layout. This is ambiguous in the sense that a + file-system layout of `a/b` will provide theory names ``a`` and ``a.b``. + + Resolving this ambiguity in a backwards-compatible way is not possible, but + future versions of Dune Rocq support will provide a way to improve this. + + Rocq's standard library gets a special status in Dune. The location at + ``ROCQLIB/theories`` will be assigned a entry with the theory name ``Rocq``, and + added to the dependency list implicitly. This can be disabled with the + ``(stdlib no)`` field in the ``rocq.theory`` stanza. + + The ``Rocq`` prefix can then be used to depend on Rocq's stdlib in a regular, + qualified way. We recommend setting ``(stdlib no)`` and adding ``(theories + Rocq)`` explicitly. + +The databases above are used to locate a theory dependencies. Note that Dune has +a complete global view of every file involved in the compilation of your theory +and will therefore rebuild if any changes are detected. + +.. _rocq-public-private-theory: + +Public and Private Theories +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A *public theory* is a :ref:`rocq-theory` stanza that is visible outside the +scope of a :doc:`/reference/dune-project/index` file. + +A *private theory* is a :ref:`rocq-theory` stanza that is limited to the scope +of the :doc:`/reference/dune-project/index` file it is in. + +A private theory may depend on both private and public theories; however, a +public theory may only depend on other public theories. + +By default, all :ref:`rocq-theory` stanzas are considered private by Dune. In +order to make a private theory into a public theory, the ``(package )`` field +must be specified. + +.. code:: dune + + (rocq.theory + (name private_theory)) + + (rocq.theory + (name private_theory) + (package rocq-public-theory)) + +Limitations +~~~~~~~~~~~ + +- ``.v`` files always depend on the native OCaml version of the Rocq binary and + its plugins, unless the natively compiled versions are missing. + +.. _limitation-mlpack: + +- A ``foo.mlpack`` file must the present in directories of locally defined + plugins for things to work. ``rocqdep``, which is used internally by Dune, will + recognize a plugin by looking at the existence of an ``.mlpack`` file, as it + cannot access (for now) Dune's library database. This is a limitation of + ``rocqdep``. See the :ref:`example plugin` or the `this + template `_. + + This limitation will be lifted soon, as newer versions of ``rocqdep`` can use + findlib's database to check the existence of OCaml libraries. + +.. _rocq-lang: + +Rocq Language Version +~~~~~~~~~~~~~~~~~~~~~ + +The Rocq lang can be modified by adding the following to a +:doc:`/reference/dune-project/index` file: + +.. code:: dune + + (using rocq 0.11) + +The supported Rocq language versions (not the version of Rocq) are: + +- ``0.11``: Support for the Rocq Prover; most important changes are: + + all deprecated features in ``(lang coq 0.10)`` have been removed. + + Dune won't install .cmxs files in user-contrib (along .vo files) anymore. + + ``(mode native)`` is not allowed anymore. It is the default if Rocq was configured with native compute enabled. + + ``COQPATH`` is not recognized anymore, use ``ROCQPATH``. + +.. _rocq-lang-1.0: + +Rocq Language Version 1.0 +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Guarantees with respect to stability are not yet provided, but we +intend that the ``(0.11)`` version of the language becomes ``1.0``. +The ``1.0`` version of Rocq lang will commit to a stable set of +functionality. All the features below are expected to reach ``1.0`` +unchanged or minimally modified. + +.. _rocq-extraction: + +rocq.extraction +--------------- + +Rocq may be instructed to *extract* OCaml sources as part of the compilation +process by using the ``rocq.extraction`` stanza: + +.. code:: dune + + (rocq.extraction + (prelude ) + (extracted_modules ) + ) + +- ``(prelude )`` refers to the Rocq source that contains the extraction + commands. + +- ``(extracted_modules )`` is an exhaustive list of OCaml modules + extracted. + +- ```` are ``flags``, ``stdlib``, ``theories``, and + ``plugins``. All of these fields have the same meaning as in the + ``rocq.theory`` stanza. + +The extracted sources can then be used in ``executable`` or ``library`` stanzas +as any other sources. + +Note that the sources are extracted to the directory where the ``prelude`` file +lives. Thus the common placement for the ``OCaml`` stanzas is in the same +:doc:`/reference/dune/index` file. + +**Warning**: using Rocq's ``Cd`` command to work around problems with the output +directory is not allowed when using extraction from Dune. Moreover the ``Cd`` +command has been deprecated in Coq 8.12. + +.. _rocq-pp: + +rocq.pp +------- + +Authors of Rocq plugins often need to write ``.mlg`` files to extend the Rocq +grammar. Such files are preprocessed with the ``rocqpp`` binary. To help plugin +authors avoid writing boilerplate, we provide a ``(rocq.pp ...)`` stanza: + +.. code:: dune + + (rocq.pp + (modules )) + +This will run the ``rocqpp`` binary on all the ``.mlg`` files in +````. + +.. _rocq-examples: + +Examples of Rocq Projects +------------------------- + +Here we list some examples of some basic Rocq project setups in order. + +.. _rocq-example-simple: + +Simple Project +~~~~~~~~~~~~~~ + +Let us start with a simple project. First, make sure we have a +:doc:`/reference/dune-project/index` file with a :ref:`Rocq +lang` stanza present: + +.. code:: dune + + (lang dune 3.21) + (using rocq 0.11) + +Next we need a :doc:`/reference/dune/index` file with a :ref:`rocq-theory` +stanza: + +.. code:: dune + + (rocq.theory + (name myTheory)) + + +Finally, we need a Rocq ``.v`` file which we name ``A.v``: + + +.. code:: coq + + (** This is my def *) + Definition mydef := nat. + +Now we run ``dune build``. After this is complete, we get the following files: + +.. code:: + + . + ├── A.v + ├── _build + │ ├── default + │ │ ├── A.glob + │ │ ├── A.v + │ │ └── A.vo + │ └── log + ├── dune + └── dune-project + +.. _rocq-example-multi-theory: + +Multi-Theory Project +~~~~~~~~~~~~~~~~~~~~ + +Here is an example of a more complicated setup: + +.. code:: + + . + ├── A + │ ├── AA + │ │ └── aa.v + │ ├── AB + │ │ └── ab.v + │ └── dune + ├── B + │ ├── b.v + │ └── dune + └── dune-project + +Here are the :doc:`/reference/dune/index` files: + +.. code:: dune + + ; A/dune + (include_subdirs qualified) + (rocq.theory + (name A)) + + ; B/dune + (rocq.theory + (name B) + (theories A)) + +Notice the ``theories`` field in ``B`` allows one :ref:`rocq-theory` to depend on +another. Another thing to note is the inclusion of the +:doc:`/reference/dune/include_subdirs` stanza. This allows our theory to +have :ref:`multiple subdirectories`. + +Here are the contents of the ``.v`` files: + +.. code:: coq + + (* A/AA/aa.v is empty *) + + (* A/AB/ab.v *) + Require Import AA.aa. + + (* B/b.v *) + From A Require Import AB.ab. + +This causes a dependency chain ``b.v -> ab.v -> aa.v``. Now we might be +interested in building theory ``B``, so all we have to do is run ``dune build +B``. Dune will automatically build the theory ``A`` since it is a dependency. + +.. _rocq-example-interproject-theory: + +Composing Projects +~~~~~~~~~~~~~~~~~~ + +To demonstrate the composition of Rocq projects, we can take our previous two +examples and put them in project which has a theory that depends on theories in +both projects. + +.. code:: + + . + ├── CombinedWork + │ ├── comb.v + │ └── dune + ├── DeeperTheory + │ ├── A + │ │ ├── AA + │ │ │ └── aa.v + │ │ ├── AB + │ │ │ └── ab.v + │ │ └── dune + │ ├── B + │ │ ├── b.v + │ │ └── dune + │ ├── Deep.opam + │ └── dune-project + ├── dune-project + └── SimpleTheory + ├── A.v + ├── dune + ├── dune-project + └── Simple.opam + +The file ``comb.v`` looks like: + +.. code:: coq + + (* Files from DeeperTheory *) + From A.AA Require Import aa. + (* In Rocq, partial prefixes for theory names are enough *) + From A Require Import ab. + From B Require Import b. + + (* Files from SimpleTheory *) + From myTheory Require Import A. + +We are referencing Rocq modules from all three of our previously defined +theories. + +Our :doc:`/reference/dune/index` file in ``CombinedWork`` looks like: + +.. code:: dune + + (rocq.theory + (name Combined) + (theories myTheory A B)) + +As you can see, there are dependencies on all the theories we mentioned. + +All three of the theories we defined before were *private theories*. In order to +depend on them, we needed to make them *public theories*. See the section on +:ref:`rocq-public-private-theory`. + +Composing With Installed Theories +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We can also compose with theories that are installed. If we wanted to have a +theory that depends on the Rocq theory ``mathcomp.ssreflect`` we can add the +following to our stanza: + +.. code:: dune + + (rocq.theory + (name my_mathcomp_theory) + (theories mathcomp.ssreflect)) + +Note that ``mathcomp`` on its own would also work, since there would be a +``matchcomp`` directory in ``user-contrib``, however it would not compose +locally with a ``rocq.theory`` stanza with the ``mathcomp.ssreflect`` name (in +case one exists). So it is advisable to use the actual theory name. Dune is not +able to validate theory names that have been installed since they do not include +their Dune metadata. + +Building Documentation +~~~~~~~~~~~~~~~~~~~~~~ + +Following from our last example, we might wish to build the HTML documentation +for ``A``. We simply do ``dune build A/A.html/``. This will produce the +following files: + +.. code:: + + A + ├── AA + │ ├── aa.glob + │ ├── aa.v + │ └── aa.vo + ├── AB + │ ├── ab.glob + │ ├── ab.v + │ └── ab.vo + └── A.html + ├── A.AA.aa.html + ├── A.AB.ab.html + ├── rocqdoc.css + ├── index.html + └── toc.html + +We may also want to build the LaTeX documentation of the theory ``B``. For this +we can call ``dune build B/B.tex/``. If we want to build all the HTML +documentation targets, we can use the :doc:`/reference/aliases/doc` alias as in +``dune build @doc``. If we want to build all the LaTeX documentation then we +use the ``@doc-latex`` alias instead. + +.. _rocq example plugin: + +Rocq Plugin Project +~~~~~~~~~~~~~~~~~~~ + +Let us build a simple Rocq plugin to demonstrate how Dune can handle this setup. + +.. code:: + + . + ├── dune-project + ├── src + │ ├── dune + │ ├── hello_world.ml + │ ├── my_plugin.mlpack + │ └── syntax.mlg + └── theories + ├── dune + └── UsingMyPlugin.v + +Our :doc:`/reference/dune-project/index` will need to have a package for +the plugin to sit in, otherwise Rocq will not be able to find it. + +.. code:: dune + + (lang dune 3.21) + (using rocq 0.11) + + (package + (name my-rocq-plugin) + (synopsis "My Rocq Plugin") + (depends rocq-core)) + +Now we have two directories, ``src/`` and ``theories/`` each with their own +:doc:`/reference/dune/index` file. Let us begin with the plugin +:doc:`/reference/dune/index` file: + +.. code:: dune + + (library + (name my_plugin) + (public_name my-rocq-plugin.plugin) + (synopsis "My Rocq Plugin") + (flags :standard -rectypes -w -27) + (libraries rocq-core.vernac)) + + (rocq.pp + (modules syntax)) + +Here we define a library using the :doc:`/reference/dune/library` stanza. +Importantly, we declared which external libraries we rely on and gave the +library a ``public_name``, which Rocq will use to identify the plugin. + +The :ref:`rocq-pp` stanza allows ``src/syntax.mlg`` to be preprocessed, which for +reference looks like: + +.. code:: ocaml + + DECLARE PLUGIN "my-rocq-plugin.plugin" + + VERNAC COMMAND EXTEND Hello CLASSIFIED AS QUERY + | [ "Hello" ] -> { Feedback.msg_notice Pp.(str Hello_world.hello_world) } + END + +Together with ``hello_world.ml``: + +.. code:: ocaml + + let hello_world = "hello world!" + +They make up the plugin. There is one more important ingredient here and that is +the ``my_plugin.mlpack`` file, needed to signal ``rocqdep`` the existence of +``my_plugin`` in this directory. An empty file suffices. See :ref:`this note on +.mlpack files`. + +The file for ``theories/`` is a standard :ref:`rocq-theory` stanza with an +included ``libraries`` field allowing Dune to see ``my-rocq-plugin.plugin`` as a +dependency. + +.. code:: dune + + (rocq.theory + (name MyPlugin) + (package my-rocq-plugin) + (plugins my-rocq-plugin.plugin)) + +Finally, our .v file will look something like this: + +.. code:: coq + + Declare ML Module "my-rocq-plugin.plugin". + + Hello. + +Running ``dune build`` will build everything correctly. + +.. _running-rocq-top: + +Running a Rocq Toplevel +----------------------- + +Dune supports running a Rocq toplevel binary such as ``rocqtop``, which is +typically used by editors such as RocqIDE or Proof General to interact with Rocq. + +The following command: + +.. code:: console + + $ dune rocq top -- + +runs a Rocq toplevel (``rocqtop`` by default) on the given Rocq file ````, +after having recompiled its dependencies as necessary. The given arguments +```` are forwarded to the invoked command. For example, this can be used +to pass a ``-emacs`` flag to ``rocqtop``. + +A different toplevel can be chosen with ``dune rocq top --toplevel CMD ``. +Note that using ``--toplevel echo`` is one way to observe what options are +actually passed to the toplevel. These options are computed based on the options +that would be passed to the Rocq compiler if it was invoked on the Rocq file +````. + +In certain situations, it is desirable to not rebuild dependencies for a ``.v`` +files but still pass the correct flags to the toplevel. For this reason, a +``--no-build`` flag can be passed to ``dune rocq top`` which will skip any +building of dependencies. + +Limitations +~~~~~~~~~~~ + +* Only files that are part of a stanza can be loaded in a Rocq toplevel. +* When a file is created, it must be written to the file system before the Rocq + toplevel is started. +* When new dependencies are added to a file (via a Rocq ``Require`` vernacular + command), it is in principle required to save the file and restart to Rocq + toplevel process. + +.. _rocq-variables: + +Rocq-Specific Variables +----------------------- + +There are some special variables that can be used to access data about the Rocq +configuration. These are: + +- ``%{rocq:version}`` the version of Rocq. +- ``%{rocq:version.major}`` the major version of Rocq (e.g., ``9.1.2`` gives + ``9``). +- ``%{rocq:version.minor}`` the minor version of Rocq (e.g., ``9.1.2`` gives + ``1``). +- ``%{rocq:version.suffix}`` the suffix version of Rocq (e.g., ``9.1.2`` gives + ``.2`` and ``9.2+rc1`` gives ``+rc1``). +- ``%{rocq:ocaml-version}`` the version of OCaml used to compile Rocq. +- ``%{rocq:rocqlib}`` the output of ``ROCQLIB`` from ``rocqc -config``. +- ``%{rocq:rocq_native_compiler_default}`` the output of + ``ROCQ_NATIVE_COMPILER_DEFAULT`` from ``rocqc -config``. + +See :doc:`concepts/variables` for more information on variables supported by +Dune. + + +.. _rocq-env: + +Rocq Environment Fields +----------------------- + +The :doc:`/reference/dune/env` stanza has a ``(rocq )`` field +with the following values for ````: + +- ``(flags )``: The default flags passed to ``rocqc``. The default value + is ``-q``. Values set here become the ``:standard`` value in the + ``(rocq.theory (flags ))`` field. +- ``(rocqdep_flags )``: The default flags passed to ``rocqdep``. The default + value is empty. Values set here become the ``:standard`` value in the + ``(rocq.theory (rocqdep_flags ))`` field. As noted in the documentation + of the ``(rocq.theory (rocqdep_flags ))`` field, changing the ``rocqdep`` + flags is discouraged. +- ``(rocqdoc_flags )``: The default flags passed to ``rocqdoc``. The default + value is ``--toc``. Values set here become the ``:standard`` value in the + ``(rocq.theory (rocqdoc_flags ))`` field. +- ``(rocqdoc_header )``: The default HTML header passed to ``rocqdoc`` via + the ``--with-header`` flag. Values set here become the ``:standard`` value in the + ``(rocq.theory (rocqdoc_header ))`` field. +- ``(rocqdoc_footer )``: The default HTML footer passed to ``rocqdoc`` via + the ``--with-footer`` flag. Values set here become the ``:standard`` value in the + ``(rocq.theory (rocqdoc_footer ))`` field. diff --git a/src/dune_lang/dune_env.ml b/src/dune_lang/dune_env.ml index 2063d4df863..aa8ab94aa76 100644 --- a/src/dune_lang/dune_env.ml +++ b/src/dune_lang/dune_env.ml @@ -80,6 +80,7 @@ type config = ; js_of_ocaml : Ordered_set_lang.Unexpanded.t Js_of_ocaml.Env.t ; wasm_of_ocaml : Ordered_set_lang.Unexpanded.t Js_of_ocaml.Env.t ; coq : Coq_env.t + ; rocq : Rocq_env.t ; format_config : Format_config.t option ; error_on_use : User_message.t option ; warn_on_load : User_message.t option @@ -103,6 +104,7 @@ let equal_config ; js_of_ocaml ; wasm_of_ocaml ; coq + ; rocq ; format_config ; error_on_use ; warn_on_load @@ -122,6 +124,7 @@ let equal_config && Menhir_env.equal menhir t.menhir && Odoc.equal odoc t.odoc && Coq_env.equal coq t.coq + && Rocq_env.equal rocq t.rocq && Option.equal Format_config.equal format_config t.format_config && Js_of_ocaml.Env.equal js_of_ocaml t.js_of_ocaml && Js_of_ocaml.Env.equal wasm_of_ocaml t.wasm_of_ocaml @@ -144,6 +147,7 @@ let empty_config = ; js_of_ocaml = Js_of_ocaml.Env.empty ; wasm_of_ocaml = Js_of_ocaml.Env.empty ; coq = Coq_env.default + ; rocq = Rocq_env.default ; format_config = None ; error_on_use = None ; warn_on_load = None @@ -245,6 +249,7 @@ let config = and+ js_of_ocaml = js_of_ocaml_field and+ wasm_of_ocaml = wasm_of_ocaml_field and+ coq = Coq_env.decode + and+ rocq = Rocq_env.decode and+ format_config = Format_config.field ~since:(2, 8) and+ bin_annot = bin_annot in let menhir = @@ -266,6 +271,7 @@ let config = ; js_of_ocaml ; wasm_of_ocaml ; coq + ; rocq ; format_config ; error_on_use = None ; warn_on_load = None diff --git a/src/dune_lang/dune_env.mli b/src/dune_lang/dune_env.mli index 12d8a8c7c39..33568d4a50f 100644 --- a/src/dune_lang/dune_env.mli +++ b/src/dune_lang/dune_env.mli @@ -32,6 +32,7 @@ type config = ; js_of_ocaml : Ordered_set_lang.Unexpanded.t Js_of_ocaml.Env.t ; wasm_of_ocaml : Ordered_set_lang.Unexpanded.t Js_of_ocaml.Env.t ; coq : Coq_env.t + ; rocq : Rocq_env.t ; format_config : Format_config.t option ; error_on_use : User_message.t option ; warn_on_load : User_message.t option diff --git a/src/dune_lang/dune_lang.ml b/src/dune_lang/dune_lang.ml index 0cca05ef778..cc609d85842 100644 --- a/src/dune_lang/dune_lang.ml +++ b/src/dune_lang/dune_lang.ml @@ -53,6 +53,7 @@ module File_binding = File_binding module Foreign_language = Foreign_language module Ocaml_flags = Ocaml_flags module Coq_env = Coq_env +module Rocq_env = Rocq_env module Menhir_env = Menhir_env module Dune_env = Dune_env module Js_of_ocaml = Js_of_ocaml diff --git a/src/dune_lang/pform.ml b/src/dune_lang/pform.ml index 378d6ebc3ac..e836d64c8f3 100644 --- a/src/dune_lang/pform.ml +++ b/src/dune_lang/pform.ml @@ -296,6 +296,7 @@ module Macro = struct | Path_no_dep | Ocaml_config | Coq_config + | Rocq_config | Env | Artifact of Artifact.t | Pkg @@ -349,6 +350,8 @@ module Macro = struct | Coq_config, Coq_config -> Eq | Coq_config, _ -> Lt | _, Coq_config -> Gt + | Rocq_config, _ -> Lt + | _, Rocq_config -> Gt | Env, Env -> Eq | Env, _ -> Lt | _, Env -> Gt @@ -384,6 +387,7 @@ module Macro = struct | Path_no_dep -> string "Path_no_dep" | Ocaml_config -> string "Ocaml_config" | Coq_config -> string "Coq_config" + | Rocq_config -> string "Rocq_config" | Env -> string "Env" | Artifact ext -> variant "Artifact" [ Artifact.to_dyn ext ] | Pkg -> variant "Pkg" [] @@ -409,6 +413,7 @@ module Macro = struct | Path_no_dep -> Error `Pform_was_deleted | Ocaml_config -> Ok "ocaml-config" | Coq_config -> Ok "coq" + | Rocq_config -> Ok "rocq" | Env -> Ok "env" | Pkg -> Ok "pkg" | Pkg_self -> Ok "pkg-self" @@ -680,6 +685,7 @@ module Env = struct ; "env", since ~version:(1, 4) Macro.Env ; "ppx", since ~version:(3, 21) Macro.Ppx ; "coq", macro Coq_config + ; "rocq", macro Rocq_config ] @ List.map ~f:artifact Artifact.all) in diff --git a/src/dune_lang/pform.mli b/src/dune_lang/pform.mli index c73b8b64921..ae2eba7c3ce 100644 --- a/src/dune_lang/pform.mli +++ b/src/dune_lang/pform.mli @@ -137,6 +137,7 @@ module Macro : sig | Path_no_dep | Ocaml_config | Coq_config + | Rocq_config | Env | Artifact of Artifact.t | Pkg diff --git a/src/dune_lang/rocq_env.ml b/src/dune_lang/rocq_env.ml new file mode 100644 index 00000000000..4da3631968a --- /dev/null +++ b/src/dune_lang/rocq_env.ml @@ -0,0 +1,75 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import +open Decoder + +type t = + { flags : Ordered_set_lang.Unexpanded.t + ; rocqdep_flags : Ordered_set_lang.Unexpanded.t + ; rocqdoc_flags : Ordered_set_lang.Unexpanded.t + ; rocqdoc_header : String_with_vars.t option + ; rocqdoc_footer : String_with_vars.t option + } + +let default = + { flags = Ordered_set_lang.Unexpanded.standard + ; rocqdep_flags = Ordered_set_lang.Unexpanded.standard + ; rocqdoc_flags = Ordered_set_lang.Unexpanded.standard + ; rocqdoc_header = None + ; rocqdoc_footer = None + } +;; + +let flags t = t.flags +let rocqdep_flags t = t.rocqdep_flags +let rocqdoc_flags t = t.rocqdoc_flags +let rocqdoc_header t = t.rocqdoc_header +let rocqdoc_footer t = t.rocqdoc_footer + +let decode = + field + "rocq" + ~default + (fields + (let+ flags = + Ordered_set_lang.Unexpanded.field + "flags" + ~check:(Syntax.since Stanza.syntax (2, 7)) + and+ rocqdep_flags = + Ordered_set_lang.Unexpanded.field + "rocqdep_flags" + ~check:(Syntax.since Stanza.syntax (3, 17)) + and+ rocqdoc_flags = + Ordered_set_lang.Unexpanded.field + "rocqdoc_flags" + ~check:(Syntax.since Stanza.syntax (3, 13)) + and+ rocqdoc_header = + field_o + "rocqdoc_header" + (Syntax.since Stanza.syntax (3, 21) >>> String_with_vars.decode) + and+ rocqdoc_footer = + field_o + "rocqdoc_footer" + (Syntax.since Stanza.syntax (3, 21) >>> String_with_vars.decode) + in + { flags; rocqdep_flags; rocqdoc_flags; rocqdoc_header; rocqdoc_footer })) +;; + +let equal { flags; rocqdep_flags; rocqdoc_flags; rocqdoc_header; rocqdoc_footer } t = + Ordered_set_lang.Unexpanded.equal flags t.flags + && Ordered_set_lang.Unexpanded.equal rocqdep_flags t.rocqdep_flags + && Ordered_set_lang.Unexpanded.equal rocqdoc_flags t.rocqdoc_flags + && Option.equal String_with_vars.equal rocqdoc_header t.rocqdoc_header + && Option.equal String_with_vars.equal rocqdoc_footer t.rocqdoc_footer +;; diff --git a/src/dune_lang/rocq_env.mli b/src/dune_lang/rocq_env.mli new file mode 100644 index 00000000000..35a81c8e218 --- /dev/null +++ b/src/dune_lang/rocq_env.mli @@ -0,0 +1,40 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import + +(** Environment for Rocq. *) +type t + +val equal : t -> t -> bool + +(** Default environment for Rocq. *) +val default : t + +(** Flags for Rocq binaries. *) +val flags : t -> Ordered_set_lang.Unexpanded.t + +(** Flags for rocqdep *) +val rocqdep_flags : t -> Ordered_set_lang.Unexpanded.t + +(** Flags for rocqdoc *) +val rocqdoc_flags : t -> Ordered_set_lang.Unexpanded.t + +(** Rocqdoc header config. *) +val rocqdoc_header : t -> String_with_vars.t option + +(** Rocqdoc footer config. *) +val rocqdoc_footer : t -> String_with_vars.t option + +(** Parser for env stanza. *) +val decode : t Decoder.fields_parser diff --git a/src/dune_rules/dir_contents.ml b/src/dune_rules/dir_contents.ml index 0283be29589..4bc0bec4983 100644 --- a/src/dune_rules/dir_contents.ml +++ b/src/dune_rules/dir_contents.ml @@ -24,6 +24,7 @@ type t = ; foreign_sources : Foreign_sources.t Memo.Lazy.t ; mlds : (Documentation.t * Doc_sources.mld list) list Memo.Lazy.t ; coq : Coq_sources.t Memo.Lazy.t + ; rocq : Rocq_sources.t Memo.Lazy.t ; ml : Ml_sources.t Memo.Lazy.t ; source_dir : Source_tree.Dir.t option } @@ -42,6 +43,7 @@ let empty kind ~dir ~source_dir = ; mlds = Memo.Lazy.of_val [] ; foreign_sources = Memo.Lazy.of_val Foreign_sources.empty ; coq = Memo.Lazy.of_val Coq_sources.empty + ; rocq = Memo.Lazy.of_val Rocq_sources.empty } ;; @@ -88,6 +90,7 @@ type triage = let dir t = t.dir let source_dir t = t.source_dir let coq t = Memo.Lazy.force t.coq +let rocq t = Memo.Lazy.force t.rocq let ocaml t = Memo.Lazy.force t.ml let dirs t = @@ -151,6 +154,12 @@ end = struct Path.Build.set_extension mlg_file ~ext:".ml" |> Path.Build.basename) | Coq_stanza.Extraction.T s -> Memo.return (Coq_stanza.Extraction.ml_target_fnames s) + | Rocq_stanza.Rocqpp.T { modules; _ } -> + Rocq_sources.mlg_files ~sctx ~dir ~modules + >>| List.rev_map ~f:(fun mlg_file -> + Path.Build.set_extension mlg_file ~ext:".ml" |> Path.Build.basename) + | Rocq_stanza.Extraction.T s -> + Memo.return (Rocq_stanza.Extraction.ml_target_fnames s) | Menhir_stanza.T menhir -> Memo.return (Menhir_stanza.targets menhir) | Rule_conf.T rule -> Simple_rules.user_rule sctx rule ~dir ~expander @@ -275,6 +284,9 @@ end = struct ; coq = Memo.lazy_ (fun () -> stanzas >>| Coq_sources.of_dir ~dir ~include_subdirs ~dirs) + ; rocq = + Memo.lazy_ (fun () -> + stanzas >>| Rocq_sources.of_dir ~dir ~include_subdirs ~dirs) } ; rules ; subdirs = Path.Build.Map.empty @@ -366,6 +378,10 @@ end = struct Memo.lazy_ (fun () -> stanzas >>| Coq_sources.of_dir ~dir ~dirs ~include_subdirs) in + let rocq = + Memo.lazy_ (fun () -> + stanzas >>| Rocq_sources.of_dir ~dir ~dirs ~include_subdirs) + in let mlds = mlds ~sctx ~dir ~dune_file ~files in let subdirs = List.map @@ -379,6 +395,7 @@ end = struct ; foreign_sources ; mlds ; coq + ; rocq }) in let root = @@ -390,6 +407,7 @@ end = struct ; foreign_sources ; mlds ; coq + ; rocq } in { Standalone_or_root.root diff --git a/src/dune_rules/dir_contents.mli b/src/dune_rules/dir_contents.mli index 69e8503d3b2..d6089a1b88f 100644 --- a/src/dune_rules/dir_contents.mli +++ b/src/dune_rules/dir_contents.mli @@ -28,6 +28,7 @@ val ocaml : t -> Ml_sources.t Memo.t val mlds : t -> stanza:Documentation.t -> Doc_sources.mld list Memo.t val coq : t -> Coq_sources.t Memo.t +val rocq : t -> Rocq_sources.t Memo.t (** Get the directory contents of the given directory. *) val get : Super_context.t -> dir:Path.Build.t -> t Memo.t diff --git a/src/dune_rules/dir_status.ml b/src/dune_rules/dir_status.ml index 953689f429e..a25f0771cad 100644 --- a/src/dune_rules/dir_status.ml +++ b/src/dune_rules/dir_status.ml @@ -204,6 +204,7 @@ let extract_directory_targets ~jsoo_enabled ~dir stanzas = (* It's unfortunate that we need to pull in the coq rules here. But we don't have a generic mechanism for this yet. *) Coq_doc.coqdoc_directory_targets ~dir m + | Rocq_stanza.Theory.T m -> Rocq_doc.rocqdoc_directory_targets ~dir m | _ -> Memo.return Path.Build.Map.empty) >>| Path.Build.Map.union_all ~f:(fun path loc1 loc2 -> User_error.raise diff --git a/src/dune_rules/dune_file.ml b/src/dune_rules/dune_file.ml index 8b34817be1b..d1b1afe4968 100644 --- a/src/dune_rules/dune_file.ml +++ b/src/dune_rules/dune_file.ml @@ -364,6 +364,7 @@ let check_dynamic_stanza = | Install_conf.T { section = loc, Section Bin; _ } -> User_error.raise ~loc [ Pp.text "binary section cannot be generated dynamically" ] | Coq_stanza.Theory.T { buildable = { Coq_stanza.Buildable.loc; _ }; _ } + | Rocq_stanza.Theory.T { buildable = { Rocq_stanza.Buildable.loc; _ }; _ } | Library.T { buildable = { loc; _ }; _ } | Install_conf.T { section = _, Site { loc; _ }; _ } | Executables.T diff --git a/src/dune_rules/dune_rules.ml b/src/dune_rules/dune_rules.ml index 73cf79b8d18..3beae919d9d 100644 --- a/src/dune_rules/dune_rules.ml +++ b/src/dune_rules/dune_rules.ml @@ -96,3 +96,13 @@ module Coq = struct module Coq_lib = Coq_lib module Coq_flags = Coq_flags end + +module Rocq = struct + module Rocq_mode = Rocq_mode + module Rocq_rules = Rocq_rules + module Rocq_module = Rocq_module + module Rocq_sources = Rocq_sources + module Rocq_lib_name = Rocq_lib_name + module Rocq_lib = Rocq_lib + module Rocq_flags = Rocq_flags +end diff --git a/src/dune_rules/expander.ml b/src/dune_rules/expander.ml index b0934633415..22a0b42c908 100644 --- a/src/dune_rules/expander.ml +++ b/src/dune_rules/expander.ml @@ -724,6 +724,13 @@ let expand_pform_macro |> Resolve.Memo.read in [ Value.Path (Path.build exe) ])) + | Rocq_config -> + Need_full_expander + (fun t -> + Without + (let open Memo.O in + let* artifacts_host = t.artifacts_host in + Rocq_config.expand source macro_invocation artifacts_host)) ;; let expand_pform_gen ~(context : Context.t) ~bindings ~dir ~source (pform : Pform.t) diff --git a/src/dune_rules/gen_rules.ml b/src/dune_rules/gen_rules.ml index 34db8d07528..0228a5e30eb 100644 --- a/src/dune_rules/gen_rules.ml +++ b/src/dune_rules/gen_rules.ml @@ -273,6 +273,14 @@ let gen_rules_for_stanzas sctx dir_contents cctxs expander ~dune_file ~dir:ctx_d | Coq_stanza.Extraction.T m -> Coq_rules.setup_extraction_rules ~sctx ~dir:ctx_dir ~dir_contents m | Coq_stanza.Coqpp.T m -> Coq_rules.setup_coqpp_rules ~sctx ~dir:ctx_dir m + | Rocq_stanza.Theory.T m -> + Expander.eval_blang expander m.enabled_if + >>= (function + | false -> Memo.return () + | true -> Rocq_rules.setup_theory_rules ~sctx ~dir:ctx_dir ~dir_contents m) + | Rocq_stanza.Extraction.T m -> + Rocq_rules.setup_extraction_rules ~sctx ~dir:ctx_dir ~dir_contents m + | Rocq_stanza.Rocqpp.T m -> Rocq_rules.setup_rocqpp_rules ~sctx ~dir:ctx_dir m | _ -> Memo.return ()) and+ () = let project = Dune_file.project dune_file in diff --git a/src/dune_rules/import.ml b/src/dune_rules/import.ml index 2b952f3139b..7a68b559d0d 100644 --- a/src/dune_rules/import.ml +++ b/src/dune_rules/import.ml @@ -121,6 +121,7 @@ include struct module File_binding = File_binding module Foreign_language = Foreign_language module Coq_env = Coq_env + module Rocq_env = Rocq_env module Menhir_env = Menhir_env module Dune_env = Dune_env module Js_of_ocaml = Js_of_ocaml diff --git a/src/dune_rules/install_rules.ml b/src/dune_rules/install_rules.ml index 5097e6ec50d..a781d1248fc 100644 --- a/src/dune_rules/install_rules.ml +++ b/src/dune_rules/install_rules.ml @@ -435,6 +435,7 @@ end = struct let+ requires = Lib.Compile.direct_requires compile_info in Resolve.is_ok requires) | Coq_stanza.Theory.T d -> Memo.return (Option.is_some d.package) + | Rocq_stanza.Theory.T d -> Memo.return (Option.is_some d.package) | _ -> Memo.return false in Option.some_if keep stanza @@ -519,6 +520,7 @@ end = struct let* dir_contents = Dir_contents.get sctx ~dir in lib_install_files sctx ~scope ~dir ~sub_dir lib ~dir_contents | Coq_stanza.Theory.T coqlib -> Coq_rules.install_rules ~sctx ~dir coqlib + | Rocq_stanza.Theory.T theory -> Rocq_rules.install_rules ~sctx ~dir theory | Documentation.T stanza -> let* dir_contents = Dir_contents.get sctx ~dir in let+ mld_contents = Dir_contents.mlds ~stanza dir_contents in diff --git a/src/dune_rules/rocq/rocq_config.ml b/src/dune_rules/rocq/rocq_config.ml new file mode 100644 index 00000000000..a7a209081ff --- /dev/null +++ b/src/dune_rules/rocq/rocq_config.ml @@ -0,0 +1,296 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import +open Memo.O + +module Vars : sig + type t + + val get_opt : t -> string -> string option + val get_path : t -> string -> Path.t + val of_lines : string list -> (t, User_message.Style.t Pp.t) result +end = struct + open Result.O + + type t = string String.Map.t + + let of_lines lines = + let rec loop acc = function + | [] -> Ok acc + | line :: lines -> + (match String.index line '=' with + | Some i -> + let x = String.take line i, String.drop line (i + 1) in + loop (x :: acc) lines + | None -> Error Pp.(textf "Unrecognized line: %S" line)) + in + let* vars = loop [] lines in + Result.map_error (String.Map.of_list vars) ~f:(fun (var, _, _) -> + Pp.(textf "Variable %S present twice." var)) + ;; + + let get_opt = String.Map.find + + let get t var = + match get_opt t var with + | Some s -> s + | None -> Code_error.raise "Variable not found." [ "var", Dyn.string var ] + ;; + + let get_path t var = get t var |> Path.of_string +end + +module Value : sig + type t = private + | Int of int + | Path of Path.t + | String of string + + val int : int -> t + val string : string -> t + val path : Path.t -> t + val to_dyn : t -> Dyn.t +end = struct + type t = + | Int of int + | Path of Path.t + | String of string + + let int i = Int i + let string s = String s + let path p = Path p + + let to_dyn = function + | Int i -> Dyn.Int i + | Path p -> Path.to_dyn p + | String s -> Dyn.String s + ;; +end + +let get_output_from_config_or_version ~(rocq : Action.Prog.t) ~what memo = + match rocq with + | Ok coqc_path -> + let open Memo.O in + let+ output, exit_code = Memo.exec memo coqc_path in + let sbin = Path.to_string coqc_path in + if exit_code <> 0 + then + Error + (Pp.vbox + @@ Pp.concat_map + ~sep:Pp.space + ~f:(fun x -> Pp.hbox (Pp.text x)) + (sprintf "%s %s failed with exit code %d." sbin what exit_code :: output)) + else Ok output + | Error e -> Action.Prog.Not_found.raise e +;; + +module Version = struct + module Num = struct + type t = + { major : int + ; minor : int + ; suffix : string + } + + let make version_string = + let module Group = Re.Group in + let regex = + let open Re in + seq [ rep digit |> group; char '.'; rep digit |> group; rep any |> group ] + |> compile + in + let open Result.O in + let* groups = + Re.exec_opt regex version_string + |> function + | Some groups -> Result.Ok groups + | None -> Result.Error Pp.(textf "Could not parse version string.") + in + let* major = + let major = Group.get groups 1 in + major + |> Int.of_string + |> function + | Some major -> Result.Ok major + | None -> Result.Error Pp.(textf "Could not parse int: %S." major) + in + let* minor = + let minor = Group.get groups 2 in + minor + |> Int.of_string + |> function + | Some minor -> Result.Ok minor + | None -> Result.Error Pp.(textf "Could not parse int: %S." minor) + in + let suffix = Group.get groups 3 in + Result.Ok { major; minor; suffix } + ;; + + let by_name { major; minor; suffix } name = + match name with + | "major" -> Some (Value.int major) + | "minor" -> Some (Value.int minor) + | "suffix" -> Some (Value.string suffix) + | _ -> None + ;; + end + + type t = + { version_num : Num.t + ; version_string : string + ; ocaml_version_string : string + } + + let impl_version bin = + let* _ = Build_system.build_file bin in + Memo.of_reproducible_fiber + @@ Process.run_capture_lines + ~display:Quiet + ~stderr_to: + (Process.Io.make_stderr + ~output_on_success:Swallow + ~output_limit:Execution_parameters.Action_output_limit.default) + Return + bin + (* we pass -boot since this means it will work with just coq-core *) + [ "--print-version"; "-boot"; "-noinit" ] + ;; + + let version_memo = Memo.create "coq-and-ocaml-version" ~input:(module Path) impl_version + + let make ~(rocq : Action.Prog.t) = + let open Memo.O in + let+ version_output = + get_output_from_config_or_version ~rocq ~what:"--print-version" version_memo + in + let open Result.O in + let* version_output = version_output in + let* version_string, ocaml_version_string = + (* First check that the command returned a single line *) + let* line = + match version_output with + | [ line ] -> Ok line + | _ -> Error Pp.(textf "Multiple lines in output of coqc --print-version.") + in + (* Next split into two parts, version looks like [" "] *) + match String.lsplit2 ~on:' ' line with + | Some (version_string, ocaml_version_string) -> + Ok (version_string, ocaml_version_string) + | None -> Error Pp.(textf "Unable to parse output of coqc --print-version.") + in + let+ version_num = Num.make version_string in + { version_num; version_string; ocaml_version_string } + ;; + + let by_name { version_num; version_string; ocaml_version_string } name = + match name with + | "version.major" -> Num.by_name version_num "major" + | "version.minor" -> Num.by_name version_num "minor" + | "version.revision" -> Num.by_name version_num "revision" + | "version.suffix" -> Num.by_name version_num "suffix" + | "version" -> Some (Value.string version_string) + | "ocaml-version" -> Some (Value.string ocaml_version_string) + | _ -> None + ;; +end + +type t = + { rocqlib : Path.t + ; rocq_native_compiler_default : string option + } + +let impl_config bin = + let* _ = Build_system.build_file bin in + Memo.of_reproducible_fiber + @@ Process.run_capture_lines + ~display:Quiet + ~stderr_to: + (Process.Io.make_stderr + ~output_on_success:Swallow + ~output_limit:Execution_parameters.Action_output_limit.default) + Return + bin + [ "--config" ] +;; + +let config_memo = Memo.create "rocq-config" ~input:(module Path) impl_config + +let make ~(rocq : Action.Prog.t) = + let open Memo.O in + let+ config_output = + get_output_from_config_or_version ~rocq ~what:"--config" config_memo + in + let open Result.O in + let* config_output = config_output in + match Vars.of_lines config_output with + | Ok vars -> + (* EJGA: Note, this is still COQLIB and + COQ_NATIVE_COMPILER_DEFAULT in both [rocq --config] and [rocq c + --config] ; so BEWARE ! *) + let rocqlib = Vars.get_path vars "COQLIB" in + let rocq_native_compiler_default = Vars.get_opt vars "COQ_NATIVE_COMPILER_DEFAULT" in + Ok { rocqlib; rocq_native_compiler_default } + | Error msg -> + User_error.raise Pp.[ textf "Cannot parse output of rocq --config:"; msg ] +;; + +let by_name { rocqlib; rocq_native_compiler_default } name = + match name with + | "rocqlib" -> Some (Value.path rocqlib) + | "rocq_native_compiler_default" -> + Option.map ~f:Value.string rocq_native_compiler_default + | _ -> + Code_error.raise + "Unknown name was requested from coq_config" + [ "name", Dyn.string name ] +;; + +let expand source macro artifacts_host = + let s = Pform.Macro_invocation.Args.whole macro in + let open Memo.O in + let* rocq = Artifacts.binary artifacts_host ~where:Original_path ~loc:None "rocq" in + let expand m k s = + let+ t = m ~rocq in + match t with + | Error msg -> + User_error.raise + ~loc:(Dune_lang.Template.Pform.loc source) + [ Pp.textf "Could not expand %%{rocq:%s} as running rocq failed." s; msg ] + | Ok t -> + (match k t s with + | None -> + User_error.raise + ~loc:(Dune_lang.Template.Pform.loc source) + [ Pp.textf "Unknown Rocq configuration variable %S" s ] + | Some v -> + let open Value in + (match v with + | Int x -> [ Dune_lang.Value.String (string_of_int x) ] + | String x -> [ Dune_lang.Value.String x ] + | Path x -> Dune_lang.Value.L.paths [ x ])) + in + match s with + | "version.major" + | "version.minor" + | "version.revision" + | "version.suffix" + | "version" + | "ocaml-version" -> expand Version.make Version.by_name s + | "rocqlib" | "rocq_native_compiler_default" -> expand make by_name s + | _ -> + Code_error.raise + "Unknown name was requested from rocq_config" + [ "name", Dyn.string s ] +;; diff --git a/src/dune_rules/rocq/rocq_config.mli b/src/dune_rules/rocq/rocq_config.mli new file mode 100644 index 00000000000..66e0ecdb6ab --- /dev/null +++ b/src/dune_rules/rocq/rocq_config.mli @@ -0,0 +1,81 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import + +module Value : sig + type t = private + | Int of int + | Path of Path.t + | String of string + + val int : int -> t + val string : string -> t + val path : Path.t -> t + val to_dyn : t -> Dyn.t +end + +module Version : sig + (** Data of a Rocq version. *) + type t + + (** [make ~rocq] runs rocq --print-version and returns the version of Rocq + and the version of OCaml used to build Rocq. + Exceptionally, one of the following will happen: + + - Return [Error message] if rocq --print-version exits with a non-zero code. + - Throw a user error if rocq --print-version is not parsable. + - Throw an [Action.Prog.Not_found] exception if the rocq binary is not found. *) + val make : rocq:Action.Prog.t -> (t, User_message.Style.t Pp.t) result Memo.t + + (** [by_name t name] returns the value of the field [name] in the Rocq + version [t]. If the value is not available then [None] is returned. + Throws a code error if an invalid [name] is requested. + + Currently supported names are: + + - version.major + - version.minor + - version.revision + - version.suffix + - version + - ocaml-version *) + val by_name : t -> string -> Value.t Option.t +end + +(** Data of a Rocq configuration. *) +type t + +(** [make ~rocq] runs rocq --config and returns the configuration data. Exceptionally, one + of the following will happen: + + - Return [Error message] if rocq --config exits with a non-zero code. + - Throw a user error if rocq --config is not parsable. + - Throw an [Action.Prog.Not_found] exception if the rocq binary is not found. *) +val make : rocq:Action.Prog.t -> (t, User_message.Style.t Pp.t) result Memo.t + +(** [by_name t name] returns the value of the option [name] in the Rocq + configuration [t]. If the value is not available then [None] is returned. + Throws a code error if an invalid [name] is requested. + + Currently supported names are: + + - rocqlib + - rocq_native_compiler_default *) +val by_name : t -> string -> Value.t Option.t + +val expand + : Dune_lang.Template.Pform.t + -> Pform.Macro_invocation.t + -> Artifacts.t + -> Dune_lang.Value.t list Memo.t diff --git a/src/dune_rules/rocq/rocq_doc.ml b/src/dune_rules/rocq/rocq_doc.ml new file mode 100644 index 00000000000..593434277db --- /dev/null +++ b/src/dune_rules/rocq/rocq_doc.ml @@ -0,0 +1,40 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import +open Memo.O + +let rocqdoc_directory ~mode ~obj_dir ~name = + Path.Build.relative + obj_dir + (Rocq_lib_name.to_string name + ^ + match mode with + | `Html -> ".html" + | `Latex -> ".tex") +;; + +let rocqdoc_directory_targets ~dir:obj_dir (theory : Rocq_stanza.Theory.t) = + let+ (_ : Rocq_lib.DB.t) = + (* We force the creation of the rocq_lib db here so that errors there can + appear before any errors to do with directory targets from rocqdoc. *) + let* scope = Scope.DB.find_by_dir obj_dir in + Scope.rocq_libs scope + in + let loc = theory.buildable.loc in + let name = snd theory.name in + Path.Build.Map.of_list_exn + [ rocqdoc_directory ~mode:`Html ~obj_dir ~name, loc + ; rocqdoc_directory ~mode:`Latex ~obj_dir ~name, loc + ] +;; diff --git a/src/dune_rules/rocq/rocq_doc.mli b/src/dune_rules/rocq/rocq_doc.mli new file mode 100644 index 00000000000..32f2fee469b --- /dev/null +++ b/src/dune_rules/rocq/rocq_doc.mli @@ -0,0 +1,28 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import + +(* This code lives in its own module so that it's usable in [Dir_status] + without creating dependency cycles *) + +val rocqdoc_directory + : mode:[< `Html | `Latex ] + -> obj_dir:Path.Build.t + -> name:Rocq_lib_name.t + -> Path.Build.t + +val rocqdoc_directory_targets + : dir:Path.Build.t + -> Rocq_stanza.Theory.t + -> Loc.t Path.Build.Map.t Memo.t diff --git a/src/dune_rules/rocq/rocq_flags.ml b/src/dune_rules/rocq/rocq_flags.ml new file mode 100644 index 00000000000..5f06307a19b --- /dev/null +++ b/src/dune_rules/rocq/rocq_flags.ml @@ -0,0 +1,43 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) +open Import + +type t = + { rocq_flags : string list + ; rocqdep_flags : string list + ; rocqdoc_flags : string list + ; rocqdoc_header : Path.t option + ; rocqdoc_footer : Path.t option + } + +let default = + { rocq_flags = [ "-q" ] + ; rocqdep_flags = [] + ; rocqdoc_flags = [ "--toc" ] + ; rocqdoc_header = None + ; rocqdoc_footer = None + } +;; + +let dump ~dir { rocq_flags; rocqdep_flags; rocqdoc_flags; rocqdoc_header; rocqdoc_footer } + = + List.map + ~f:Dune_lang.Encoder.(pair string (list string)) + [ "rocq_flags", rocq_flags + ; "rocqdep_flags", rocqdep_flags + ; "rocqdoc_flags", rocqdoc_flags + ] + @ List.map + ~f:Dune_lang.Encoder.(pair string (option (Dune_lang.Path.Local.encode ~dir))) + [ "rocqdoc_header", rocqdoc_header; "rocqdoc_footer", rocqdoc_footer ] +;; diff --git a/src/dune_rules/rocq/rocq_flags.mli b/src/dune_rules/rocq/rocq_flags.mli new file mode 100644 index 00000000000..7775eb65a49 --- /dev/null +++ b/src/dune_rules/rocq/rocq_flags.mli @@ -0,0 +1,24 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) +open Import + +type t = + { rocq_flags : string list + ; rocqdep_flags : string list + ; rocqdoc_flags : string list + ; rocqdoc_header : Path.t option + ; rocqdoc_footer : Path.t option + } + +val default : t +val dump : dir:Path.t -> t -> Dune_lang.t list diff --git a/src/dune_rules/rocq/rocq_lib.ml b/src/dune_rules/rocq/rocq_lib.ml new file mode 100644 index 00000000000..c019f1793a0 --- /dev/null +++ b/src/dune_rules/rocq/rocq_lib.ml @@ -0,0 +1,651 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import + +module Id = struct + module T = struct + type t = + { path : Path.t + ; loc : Loc.t + ; name : Rocq_lib_name.t + } + + let compare t { path; name; _ } = + let open Ordering.O in + let= () = Path.compare t.path path in + Rocq_lib_name.compare t.name name + ;; + + let to_dyn { path; loc; name } = + Dyn.( + record + [ "path", Path.to_dyn path + ; "loc", Loc.to_dyn loc + ; "name", Rocq_lib_name.to_dyn name + ]) + ;; + end + + include T + + let pp { path; loc; name } = + let loc_or_path = + if Loc.is_none loc then Path.pp path else Loc.pp_file_colon_line loc + in + Pp.concat + ~sep:Pp.space + [ Pp.textf "theory %s in" (Rocq_lib_name.to_string name); loc_or_path ] + ;; + + let create ~path ~name:(loc, name) = { path; name; loc } + + module C = Comparable.Make (T) + module Top_closure = Top_closure.Make (C.Set) (Resolve) + + let top_closure ~key ~deps xs = Top_closure.top_closure ~key ~deps xs +end + +module rec R : sig + type t = + | Dune of Dune.t + | Legacy of Legacy.t + + val to_dyn : t -> Dyn.t +end = struct + type t = + | Dune of Dune.t + | Legacy of Legacy.t + + let to_dyn = function + | Dune t -> Dyn.Variant ("Dune", [ Dune.to_dyn t ]) + | Legacy t -> Dyn.Variant ("Legacy", [ Legacy.to_dyn t ]) + ;; +end + +and Dune : sig + type t = + { loc : Loc.t + ; boot_id : Id.t option (** boot library that was selected to build this theory *) + ; id : Id.t + ; implicit : bool (* Only useful for the stdlib *) + ; use_stdlib : bool + (* whether this theory uses the stdlib, eventually set to false for all libs *) + ; src_root : Path.Build.t + ; obj_root : Path.Build.t + ; theories : (Loc.t * R.t) list Resolve.t + ; libraries : (Loc.t * Lib.t) list Resolve.t + ; theories_closure : R.t list Resolve.t Lazy.t + ; package : Package.t option + } + + val to_dyn : t -> Dyn.t + val src_root : t -> Path.Build.t + val obj_root : t -> Path.Build.t + val implicit : t -> bool + + (** ML libraries *) + val libraries : t -> (Loc.t * Lib.t) list Resolve.t +end = struct + type t = + { loc : Loc.t + ; boot_id : Id.t option (** boot library that was selected to build this theory *) + ; id : Id.t + ; implicit : bool (* Only useful for the stdlib *) + ; use_stdlib : bool + (* whether this theory uses the stdlib, eventually set to false for all libs *) + ; src_root : Path.Build.t + ; obj_root : Path.Build.t + ; theories : (Loc.t * R.t) list Resolve.t + ; libraries : (Loc.t * Lib.t) list Resolve.t + ; theories_closure : R.t list Resolve.t Lazy.t + ; package : Package.t option + } + + let to_dyn + { loc + ; boot_id + ; id + ; implicit + ; use_stdlib + ; src_root + ; obj_root + ; theories + ; libraries + ; theories_closure + ; package + } + = + Dyn.( + record + [ "loc", Loc.to_dyn loc + ; "boot_id", Dyn.option Id.to_dyn boot_id + ; "id", Id.to_dyn id + ; "implicit", Bool.to_dyn implicit + ; "use_stdlib", Bool.to_dyn use_stdlib + ; "src_root", Path.Build.to_dyn src_root + ; "obj_root", Path.Build.to_dyn obj_root + ; "theories", Resolve.to_dyn (Dyn.list (Dyn.pair Loc.to_dyn R.to_dyn)) theories + ; ( "libraries" + , Resolve.to_dyn (Dyn.list (Dyn.pair Loc.to_dyn Lib.to_dyn)) libraries ) + ; ( "theories_closure" + , Resolve.to_dyn (Dyn.list R.to_dyn) (Lazy.force theories_closure) ) + ; "package", Dyn.option Package.to_dyn package + ]) + ;; + + let src_root t = t.src_root + let obj_root t = t.obj_root + let implicit t = t.implicit + let libraries t = t.libraries +end + +and Legacy : sig + type t = + { boot_id : Id.t option + ; id : Id.t + ; implicit : bool (* Only useful for the stdlib *) + ; installed_root : Path.t (* ; libraries : (Loc.t * Lib.t) list Resolve.t *) + ; vo : Path.t list + } + + val to_dyn : t -> Dyn.t + val implicit : t -> bool + val installed_root : t -> Path.t + val vo : t -> Path.t list +end = struct + type t = + { boot_id : Id.t option + ; id : Id.t + ; implicit : bool (* Only useful for the stdlib *) + ; installed_root : Path.t (* ; libraries : (Loc.t * Lib.t) list Resolve.t *) + ; vo : Path.t list + } + + let to_dyn { boot_id; id; implicit; installed_root; vo } = + Dyn.record + [ "boot_id", Dyn.option Id.to_dyn boot_id + ; "id", Id.to_dyn id + ; "implicit", Dyn.bool implicit + ; "installed_root", Path.to_dyn installed_root + ; "vo", Dyn.list Path.to_dyn vo + ] + ;; + + let implicit t = t.implicit + let installed_root t = t.installed_root + let vo t = t.vo +end + +include R + +let boot_id_of_lib = function + | Dune t -> t.boot_id + | Legacy t -> t.boot_id +;; + +let id_of_lib = function + | Dune t -> t.id + | Legacy t -> t.id +;; + +let name = function + | Dune t -> t.id.name + | Legacy t -> t.id.name +;; + +let obj_root = function + | Dune t -> Dune.obj_root t |> Path.build + | Legacy t -> Legacy.installed_root t +;; + +let implicit = function + | Dune t -> Dune.implicit t + | Legacy t -> Legacy.implicit t +;; + +module Error = struct + let annots = User_message.Annots.singleton User_message.Annots.needs_stack_trace () + + let duplicate_theory_name (id1 : Id.t) (id2 : Id.t) = + let name = id1.name in + User_error.raise + [ Pp.textf "Rocq theory %s is defined twice:" (Rocq_lib_name.to_string name) + ; Pp.enumerate ~f:Id.pp [ id1; id2 ] + ] + ;; + + let incompatible_boot id1 id2 = + User_message.make + ~annots + [ Pp.textf "The following theories use incompatible boot libraries:" + ; Pp.enumerate ~f:Id.pp [ id1; id2 ] + ] + |> Resolve.fail + ;; + + let theory_not_found ~loc ?hints name = + let name = Rocq_lib_name.to_string name in + Resolve.Memo.fail + @@ User_message.make + ~annots + ~loc + ?hints + [ Pp.textf "Theory %S has not been found." name ] + ;; + + let private_deps_not_allowed ~loc name = + let name = Rocq_lib_name.to_string name in + Resolve.Memo.fail + @@ User_message.make + ~loc + [ Pp.textf + "Theory %S is private, it cannot be a dependency of a public theory. You \ + need to associate %S to a package." + name + name + ] + ;; + + let duplicate_boot_lib theories = + let open Rocq_stanza.Theory in + let name (t : Rocq_stanza.Theory.t) = + let name = Rocq_lib_name.to_string (snd t.name) in + Pp.textf "%s at %s" name (Loc.to_file_colon_line t.buildable.loc) + in + User_error.raise + [ Pp.textf "Cannot have more than one boot theory in scope:" + ; Pp.enumerate theories ~f:name + ] + ;; + + (* XXX: Not in the test suite *) + let duplicate_boot_path paths = + let describe_path cp = + let name = Rocq_path.name cp in + let path = Rocq_path.path cp in + Pp.textf "%s at %s" (Rocq_lib_name.to_string name) (Path.to_string path) + in + User_error.raise + [ Pp.textf "Found more than one installed Rocq Corelib" + ; Pp.enumerate paths ~f:describe_path + ] + ;; +end + +let top_closure = + let key t = id_of_lib t in + let deps t = + match t with + | Dune t -> t.theories |> Resolve.map ~f:(List.map ~f:snd) + | Legacy _ -> Resolve.return [] + in + fun theories -> + let open Resolve.O in + Id.top_closure theories ~key ~deps + >>= function + | Ok s -> Resolve.return s + | Error _ -> assert false +;; + +module DB = struct + type lib = t + + module Resolve_result = struct + (** This is the first result of resolving a rocq library, later one we will + refine this data. *) + type 'a t = + | Redirect of 'a + | Theory of Lib.DB.t * Path.Build.t * Rocq_stanza.Theory.t + | Legacy_theory of Rocq_path.t + | Not_found + end + + type t = + { parent : t option + ; resolve : Rocq_lib_name.t -> t Resolve_result.t + ; boot_id : Id.t option + } + + let rec to_dyn { parent; resolve = _; boot_id } = + Dyn.record + [ "parent", Dyn.option to_dyn parent; "boot_id", Dyn.option Id.to_dyn boot_id ] + ;; + + module Entry = struct + type nonrec t = + | Redirect of t + | Theory of Path.Build.t + end + + let rec boot_library_id rocq_db = + match rocq_db.boot_id with + | Some boot_id -> Some boot_id + | None -> + (match rocq_db.parent with + | None -> None + | Some parent -> boot_library_id parent) + ;; + + module rec R : sig + val resolve_boot : t -> (Loc.t * lib) option Resolve.Memo.t + val resolve : t -> Loc.t * Rocq_lib_name.t -> lib Resolve.Memo.t + end = struct + open R + + let resolve_plugin ~db ~allow_private_deps ~name (loc, lib) = + let open Resolve.Memo.O in + let* lib = Lib.DB.resolve db (loc, lib) in + let+ () = + Resolve.Memo.lift + @@ + if allow_private_deps + then Resolve.return () + else ( + match + let info = Lib.info lib in + let status = Lib_info.status info in + Lib_info.Status.is_private status + with + | false -> Resolve.return () + | true -> + Resolve.fail + @@ User_message.make + ~loc + [ Pp.textf + "private theory %s may not depend on a public library" + (Rocq_lib_name.to_string name) + ]) + in + loc, lib + ;; + + let resolve_plugins ~db ~allow_private_deps ~name plugins = + let f = resolve_plugin ~db ~allow_private_deps ~name in + Resolve.Memo.List.map plugins ~f + ;; + + let check_boot ~boot_id (lib : lib) = + match boot_id, boot_id_of_lib lib with + | Some id, Some id' -> + if Id.compare id id' = Eq + then Resolve.return () + else Error.incompatible_boot id id' + | _, _ -> Resolve.return () + ;; + + let maybe_add_boot ~boot ~use_stdlib ~is_boot theories = + if use_stdlib && not is_boot + then + let open Resolve.O in + let* boot = boot in + let+ theories = theories in + Option.to_list boot @ theories + else theories + ;; + + let resolve_boot ~rocq_db (boot_id : Id.t option) = + match boot_id with + | Some boot_id -> + let open Resolve.Memo.O in + let+ lib = resolve rocq_db (boot_id.loc, boot_id.name) in + Some (boot_id.loc, lib) + | None -> Resolve.Memo.return None + ;; + + let resolve_theory ~allow_private_deps ~rocq_db ~boot_id (loc, theory_name) = + let open Resolve.Memo.O in + let* theory = resolve rocq_db (loc, theory_name) in + let* () = Resolve.Memo.lift @@ check_boot ~boot_id theory in + let+ () = + if allow_private_deps + then Resolve.Memo.return () + else ( + match theory with + | Dune { package = None; _ } -> Error.private_deps_not_allowed ~loc theory_name + | Legacy _ | Dune _ -> Resolve.Memo.return ()) + in + loc, theory + ;; + + let resolve_theories ~allow_private_deps ~rocq_db ~boot_id theories = + let f = resolve_theory ~allow_private_deps ~rocq_db ~boot_id in + Resolve.Memo.List.map theories ~f + ;; + + let create_from_stanza_impl (rocq_db, db, dir, (s : Rocq_stanza.Theory.t)) = + let name = s.name in + let id = Id.create ~path:(Path.build dir) ~name in + let open Memo.O in + let boot_id = if s.boot then None else boot_library_id rocq_db in + let allow_private_deps = Option.is_none s.package in + let use_stdlib = s.buildable.use_stdlib in + let+ libraries = + resolve_plugins ~db ~allow_private_deps ~name:(snd name) s.buildable.plugins + and+ theories = + resolve_theories ~rocq_db ~allow_private_deps ~boot_id s.buildable.theories + and+ boot = resolve_boot ~rocq_db boot_id in + let theories = maybe_add_boot ~boot ~use_stdlib ~is_boot:s.boot theories in + let map_error x = + let human_readable_description () = Id.pp id in + Resolve.push_stack_frame ~human_readable_description x + in + let theories = map_error theories in + let libraries = map_error libraries in + { Dune.loc = s.buildable.loc + ; boot_id + ; id + ; use_stdlib + ; implicit = s.boot + ; obj_root = dir + ; src_root = dir + ; theories + ; libraries + ; theories_closure = + lazy + (Resolve.bind theories ~f:(fun theories -> + List.map theories ~f:snd |> top_closure)) + ; package = s.package + } + ;; + + module Input = struct + type nonrec t = t * Lib.DB.t * Path.Build.t * Rocq_stanza.Theory.t + + let equal (rocq_db, ml_db, path, stanza) (rocq_db', ml_db', path', stanza') = + phys_equal rocq_db rocq_db' + && phys_equal ml_db ml_db' + && Path.Build.equal path path' + && phys_equal stanza stanza' + ;; + + let hash = Poly.hash + let to_dyn = Dyn.opaque + end + + let memo = + Memo.create + "create-from-stanza" + ~human_readable_description:(fun (_, _, path, theory) -> + Id.pp (Id.create ~path:(Path.build path) ~name:theory.name)) + ~input:(module Input) + create_from_stanza_impl + ;; + + let create_from_stanza rocq_db db dir stanza = + Memo.exec memo (rocq_db, db, dir, stanza) + ;; + + (* XXX: Memoize? This is pretty cheap so not sure worth the cost, + still called too much I have observed, suspicious! *) + let create_from_rocqpath ~boot_id cp = + let name = Rocq_path.name cp in + let installed_root = Rocq_path.path cp in + let implicit = Rocq_path.corelib cp in + let vo = Rocq_path.vo cp in + let id = Id.create ~path:installed_root ~name:(Loc.none, name) in + Resolve.Memo.return { Legacy.boot_id; id; implicit; installed_root; vo } + ;; + + module Resolve_result_no_redirect = struct + (** In our second iteration, we remove all the redirects *) + type t = + | Theory of Lib.db * Path.Build.t * Rocq_stanza.Theory.t + | Legacy_theory of Rocq_path.t + | Not_found + end + + let rec find rocq_db name : Resolve_result_no_redirect.t = + match rocq_db.resolve name with + | Theory (db, dir, stanza) -> Theory (db, dir, stanza) + | Legacy_theory cp -> Legacy_theory cp + | Redirect rocq_db -> find rocq_db name + | Not_found -> + (match rocq_db.parent with + | None -> Not_found + | Some parent -> find parent name) + ;; + + module Resolve_final_result = struct + (** Next we find corresponding Rocq libraries for the various cases *) + type t = + | Found_stanza of Lib.DB.t * Path.Build.t * Rocq_stanza.Theory.t + | Found_path of Rocq_path.t + | Not_found + end + + let find rocq_db name : Resolve_final_result.t = + match find rocq_db name with + | Not_found -> Not_found + | Theory (mldb, dir, stanza) -> Found_stanza (mldb, dir, stanza) + | Legacy_theory cp -> Found_path cp + ;; + + (** Our final final resolve is used externally, and should return the + library data found from the previous iterations. *) + let resolve rocq_db (loc, name) = + match find rocq_db name with + | Not_found -> Error.theory_not_found ~loc name + | Found_stanza (db, dir, stanza) -> + let open Memo.O in + let+ theory = create_from_stanza rocq_db db dir stanza in + let open Resolve.O in + let* (_ : (Loc.t * Lib.t) list) = theory.libraries in + let+ (_ : (Loc.t * lib) list) = theory.theories in + Dune theory + | Found_path cp -> + let open Resolve.Memo.O in + let boot_id = rocq_db.boot_id in + let+ theory = create_from_rocqpath ~boot_id cp in + Legacy theory + ;; + + let resolve_boot rocq_db = + let boot_id = boot_library_id rocq_db in + resolve_boot ~rocq_db boot_id + ;; + end + + include R + + let select_boot_id entries = + match + List.find_all entries ~f:(fun ((theory : Rocq_stanza.Theory.t), _entry) -> + theory.boot) + with + | [] -> None + | [ ((theory, entry) : Rocq_stanza.Theory.t * Entry.t) ] -> + (match entry with + | Theory path -> Some (Id.create ~path:(Path.build path) ~name:theory.name) + | Redirect lib -> lib.boot_id) + | boots -> + let stanzas = List.map boots ~f:fst in + Error.duplicate_boot_lib stanzas + ;; + + let create_from_rocqlib_stanzas + ~(parent : t option) + ~find_db + (entries : (Rocq_stanza.Theory.t * Entry.t) list) + = + let boot_id = select_boot_id entries in + let map = + match + Rocq_lib_name.Map.of_list_map + entries + ~f:(fun ((theory : Rocq_stanza.Theory.t), entry) -> + snd theory.name, (theory, entry)) + with + | Ok m -> m + | Error (_name, (theory1, entry1), (theory2, entry2)) -> + let path entry = + match (entry : Entry.t) with + | Theory dir -> Path.build dir + | Redirect db -> + Code_error.raise "created stanza redirected to a library" [ "db", to_dyn db ] + in + let id1 = Id.create ~path:(path entry1) ~name:theory1.name in + let id2 = Id.create ~path:(path entry2) ~name:theory2.name in + Error.duplicate_theory_name id1 id2 + in + let resolve name : t Resolve_result.t = + match Rocq_lib_name.Map.find map name with + | None -> Not_found + | Some (theory, entry) -> + (match entry with + | Theory dir -> Theory (find_db dir, dir, theory) + | Redirect db -> Redirect db) + in + { boot_id; resolve; parent } + ;; + + (* XXX: This is basically duplicated from create_from_rocqlib_stanzas + except for the slightly different input type *) + let select_boot_path (cp : Rocq_path.t list) = + match List.find_all cp ~f:Rocq_path.corelib with + | [] -> None + | [ stdlib ] -> + let name = Loc.none, Rocq_path.name stdlib in + let path = Rocq_path.path stdlib in + Some (Id.create ~path ~name) + | paths -> Error.duplicate_boot_path paths + ;; + + let create_from_rocqpaths cps = + (* No parent for rocqpaths for now *) + let parent = None in + let boot_id = select_boot_path cps in + (* Map is eager, this may not be very convenient in large trees, + but should be fine for now *) + let map = + List.rev_map cps ~f:(fun cp -> Rocq_path.name cp, cp) + (* Since we reversed the order, the second rocqpath should take + precedence. This is in line with Rocq semantics. *) + |> Rocq_lib_name.Map.of_list_reducei ~f:(fun _name _cp1 cp2 -> cp2) + in + let resolve name : t Resolve_result.t = + match Rocq_lib_name.Map.find map name with + | None -> Not_found + | Some cp -> Legacy_theory cp + in + { parent; resolve; boot_id } + ;; + + (* Resolve helpers *) + let find_many t theories = Resolve.Memo.List.map theories ~f:(resolve t) +end + +let theories_closure = function + | Dune t -> Lazy.force t.theories_closure + | Legacy _ -> Resolve.return [] +;; diff --git a/src/dune_rules/rocq/rocq_lib.mli b/src/dune_rules/rocq/rocq_lib.mli new file mode 100644 index 00000000000..366439ffca9 --- /dev/null +++ b/src/dune_rules/rocq/rocq_lib.mli @@ -0,0 +1,92 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import + +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* Written by: Emilio Jesús Gallego Arias *) + +module Dune : sig + type t + + (** Source directory *) + val src_root : t -> Path.Build.t + + (** ML libraries *) + val libraries : t -> (Loc.t * Lib.t) list Resolve.t +end + +module Legacy : sig + type t + + (** For each legacy library, we need: + + - the list of [.vo] files, this is because we need to make the call to + [rocqdep] depend on it. If due to external action the list of these files + changes, rocqdep must be re-run. Note that rocqdep sometimes checks for + [.vo] files and sometimes for [.v] files, which is messy (in principle + only checks for [.v] files when compiling the stdlib using make, but + YMMV with rocqdep code). + + In the case of a [Dune.t] lib, this list is obtained from the [src_root], + via [Dir_contents.rocq], maybe we should move that function here and make + it common. + + *) + + (** List of vo files *) + val vo : t -> Path.t list +end + +type t = + | Dune of Dune.t + | Legacy of Legacy.t + +val to_dyn : t -> Dyn.t +val name : t -> Rocq_lib_name.t +val obj_root : t -> Path.t +val implicit : t -> bool + +(** Return the list of dependencies needed for compiling this library *) +val theories_closure : t -> t list Resolve.t + +module DB : sig + type lib := t + type t + + module Entry : sig + type nonrec t = + | Redirect of t + | Theory of Path.Build.t + end + + (** Note the invariant for the [create_*] functions: DB resolution can't be + used yet at the stage they are called from [Scope] and the scope build + process, is not finished. Instead, resolution of dependencies will be done + in [resolve_*] below and properly memoized. *) + val create_from_rocqlib_stanzas + : parent:t option + -> find_db:(Path.Build.t -> Lib.DB.t) + -> (Rocq_stanza.Theory.t * Entry.t) list + -> t + + (** Note that at some point we could fuse this with the above by having a + common type for [Rocq_path.t] and [Rocq_stanza.Theory.t]. In this case, when + libraries are installed, we would infer the right amount of information. *) + val create_from_rocqpaths : Rocq_path.t list -> t + + val find_many : t -> (Loc.t * Rocq_lib_name.t) list -> lib list Resolve.Memo.t + val resolve_boot : t -> (Loc.t * lib) option Resolve.Memo.t + val resolve : t -> Loc.t * Rocq_lib_name.t -> lib Resolve.Memo.t +end diff --git a/src/dune_rules/rocq/rocq_lib_name.ml b/src/dune_rules/rocq/rocq_lib_name.ml new file mode 100644 index 00000000000..86cc5e082ce --- /dev/null +++ b/src/dune_rules/rocq/rocq_lib_name.ml @@ -0,0 +1,47 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open! Import + +(* Rocq Directory Path, example [Stdlib.List] *) +type t = string list + +let compare = List.compare ~compare:String.compare +let equal x y = Ordering.is_eq (compare x y) +let to_string x = String.concat ~sep:"." x +let empty = [] +let corelib = [ "Corelib" ] +let to_list x = x +let append x y = x @ [ y ] +let to_dir x = String.concat ~sep:"/" x +let wrapper x = to_string x +let dir x = to_dir x + +(* We should add some further validation to Rocq library names; the rules in Rocq + itself have been tweaked due to Unicode, etc... so this is not trivial *) +let decode : (Loc.t * t) Dune_lang.Decoder.t = + Dune_lang.Decoder.plain_string (fun ~loc s -> loc, String.split ~on:'.' s) +;; + +let encode : t Dune_lang.Encoder.t = fun lib -> Dune_lang.Encoder.string (to_string lib) +let pp x = Pp.text (to_string x) +let to_dyn = Dyn.(list string) + +module Rep = struct + type nonrec t = t + + let compare = List.compare ~compare:String.compare + let to_dyn = to_dyn +end + +module Map = Map.Make (Rep) diff --git a/src/dune_rules/rocq/rocq_lib_name.mli b/src/dune_rules/rocq/rocq_lib_name.mli new file mode 100644 index 00000000000..c31e1bbfaea --- /dev/null +++ b/src/dune_rules/rocq/rocq_lib_name.mli @@ -0,0 +1,44 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import + +(** A Rocq library name is a dot-separated list of Rocq module identifiers. *) +type t + +val compare : t -> t -> Ordering.t +val equal : t -> t -> bool + +(** Returns the wrapper name, a dot-separated list of Rocq module identifies *) +val wrapper : t -> string + +(** Returns the directory name for a lib name, in this case library name foo.bar + lives in foo/bar *) +val dir : t -> string + +val encode : t Dune_lang.Encoder.t +val decode : (Loc.t * t) Dune_lang.Decoder.t + +(* to be removed in favor of encode / decode *) +val to_string : t -> string + +(** The Rocq standard library name *) +val corelib : t + +val to_list : t -> string list +val append : t -> string -> t +val empty : t +val pp : t -> t Pp.t +val to_dyn : t -> Dyn.t + +module Map : Map.S with type key = t diff --git a/src/dune_rules/rocq/rocq_mode.ml b/src/dune_rules/rocq/rocq_mode.ml new file mode 100644 index 00000000000..c82c61f9b39 --- /dev/null +++ b/src/dune_rules/rocq/rocq_mode.ml @@ -0,0 +1,19 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +type t = + | VoOnly + | Native + | VosOnly + +let decode = Dune_lang.Decoder.(enum' [ "vo", return VoOnly; "vos", return VosOnly ]) diff --git a/src/dune_rules/rocq/rocq_mode.mli b/src/dune_rules/rocq/rocq_mode.mli new file mode 100644 index 00000000000..0c6ab1456a2 --- /dev/null +++ b/src/dune_rules/rocq/rocq_mode.mli @@ -0,0 +1,25 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +(** We support different modes in order to speed up compilation: + [VoOnly], where even if native is enabled, we will skip the + compilation; [Native], meaning compile both .vo and "native" .cmxs + files, [VosOnly], to generate only vos files. *) +type t = + | VoOnly + | Native + | VosOnly + +(** Note that we cannot decode [Native], as it is automatically + inferred *) +val decode : t Dune_lang.Decoder.t diff --git a/src/dune_rules/rocq/rocq_module.ml b/src/dune_rules/rocq/rocq_module.ml new file mode 100644 index 00000000000..fc910e4b3e4 --- /dev/null +++ b/src/dune_rules/rocq/rocq_module.ml @@ -0,0 +1,146 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import + +module Name = struct + module Self = struct + type t = string + + let make x = x + let compare = String.compare + let equal = String.equal + let to_dyn s = Dyn.String s + let to_string s = s + let decode = Dune_lang.Decoder.string + end + + include Self + module Map = Map.Make (Self) +end + +module Module = struct + (* We keep prefix and name separated as the handling of `From Foo Require + Bar.` may benefit from it. *) + type t = + { source : Path.t + ; prefix : string list + ; name : Name.t + } + + let compare { source; prefix; name } t = + let open Ordering.O in + let= () = Path.compare source t.source in + let= () = List.compare prefix t.prefix ~compare:String.compare in + Name.compare name t.name + ;; + + let to_dyn { source; prefix; name } = + Dyn.record + [ "source", Path.to_dyn source + ; "prefix", Dyn.list Dyn.string prefix + ; "name", Name.to_dyn name + ] + ;; +end + +include Module +module Map = Map.Make (Module) + +let make ~source ~prefix ~name = { source; prefix; name } +let source x = x.source +let prefix x = x.prefix +let name x = x.name +let build_vo_dir ~obj_dir x = List.fold_left x.prefix ~init:obj_dir ~f:Path.Build.relative + +let cmxs_of_mod ~wrapper_name x = + let wrapper_split = String.split wrapper_name ~on:'.' in + let native_base = + "N" ^ String.concat ~sep:"_" (wrapper_split @ x.prefix @ [ x.name ]) + in + [ native_base ^ Cm_kind.ext Cmi; native_base ^ Mode.plugin_ext Native ] +;; + +let dep_file x ~obj_dir = + let vo_dir = build_vo_dir ~obj_dir x in + Path.Build.relative vo_dir (x.name ^ ".v.d") +;; + +type obj_files_mode = + | Build + | Install + +let glob_file x ~obj_dir = + let vo_dir = build_vo_dir ~obj_dir x in + Path.Build.relative vo_dir (x.name ^ ".glob") +;; + +(* As of today we do the same for build and install, it used not to be + the case *) +let standard_obj_files ~(mode : Rocq_mode.t) _obj_files_mode name = + let ext, glob = + match mode with + | VosOnly -> ".vos", [] + | _ -> ".vo", [ name ^ ".glob" ] + in + [ name ^ ext ] @ glob +;; + +(* XXX: Remove the install .coq-native hack once rules can output targets in + multiple subdirs *) +let obj_files x ~wrapper_name ~mode ~obj_dir ~obj_files_mode = + let vo_dir = build_vo_dir ~obj_dir x in + let install_vo_dir = String.concat ~sep:"/" x.prefix in + let native_objs = + match mode with + | Rocq_mode.Native -> + let cmxs_obj = cmxs_of_mod ~wrapper_name x in + List.map + ~f:(fun x -> + ( Path.Build.relative vo_dir x + , Filename.(concat (concat install_vo_dir ".coq-native") x) )) + cmxs_obj + | VoOnly | VosOnly -> [] + in + let obj_files = standard_obj_files ~mode obj_files_mode x.name in + List.map obj_files ~f:(fun fname -> + Path.Build.relative vo_dir fname, Filename.concat install_vo_dir fname) + @ native_objs +;; + +let to_dyn { source; prefix; name } = + let open Dyn in + record + [ "source", Path.to_dyn source + ; "prefix", list string prefix + ; "name", Name.to_dyn name + ] +;; + +let parse ~dir ~loc s = + let clist = List.rev @@ String.split s ~on:'.' in + match clist with + | [] -> User_error.raise ~loc [ Pp.text "Invalid Rocq module" ] + | name :: prefix -> + let prefix = List.rev prefix in + let source = List.fold_left prefix ~init:dir ~f:Path.Build.relative in + let source = Path.build @@ Path.Build.relative source (name ^ ".v") in + make ~name ~source ~prefix +;; + +let eval = + let key x = String.concat ~sep:"." (x.prefix @ [ x.name ]) in + let eq_key x y = String.equal (key x) (key y) in + fun ~dir ~standard osl -> + Ordered_set_lang.eval ~parse:(parse ~dir) ~standard ~eq:eq_key osl +;; diff --git a/src/dune_rules/rocq/rocq_module.mli b/src/dune_rules/rocq/rocq_module.mli new file mode 100644 index 00000000000..1f5eac39686 --- /dev/null +++ b/src/dune_rules/rocq/rocq_module.mli @@ -0,0 +1,65 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import + +module Name : sig + type t + + val make : string -> t + val compare : t -> t -> Ordering.t + val equal : t -> t -> bool + val to_dyn : t -> Dyn.t + val to_string : t -> string + val decode : t Dune_lang.Decoder.t + + module Map : Map.S with type key = t +end + +type t + +module Map : Map.S with type key = t + +(** A Rocq module [a.b.foo] defined in file [a/b/foo.v] *) +val make + : source:Path.t (** file = .v source file; module name has to be the same so far *) + -> prefix:string list (** Library-local qualified prefix *) + -> name:Name.t (** Name of the module *) + -> t + +(** Rocq does enforce some invariants wrt module vs file names *) + +val source : t -> Path.t +val prefix : t -> string list +val name : t -> Name.t +val dep_file : t -> obj_dir:Path.Build.t -> Path.Build.t +val glob_file : t -> obj_dir:Path.Build.t -> Path.Build.t + +(** Some of the object files should not be installed, we control this with the + following parameter *) +type obj_files_mode = + | Build + | Install + +(** This returns a list of pairs [(obj_file, install_path)] due to native files + having a different install location *) +val obj_files + : t + -> wrapper_name:string + -> mode:Rocq_mode.t + -> obj_dir:Path.Build.t + -> obj_files_mode:obj_files_mode + -> (Path.Build.t * string) list + +val to_dyn : t -> Dyn.t +val eval : dir:Path.Build.t -> standard:t list -> Ordered_set_lang.t -> t list diff --git a/src/dune_rules/rocq/rocq_path.ml b/src/dune_rules/rocq/rocq_path.ml new file mode 100644 index 00000000000..8af6fee6fcf --- /dev/null +++ b/src/dune_rules/rocq/rocq_path.ml @@ -0,0 +1,205 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import + +type t = + { name : Rocq_lib_name.t + ; path : Path.t + ; vo : Path.t list + ; corelib : bool + } + +let name t = t.name +let path t = t.path +let vo t = t.vo +let corelib t = t.corelib + +let config_path_exn rocq_config key = + Rocq_config.by_name rocq_config key + |> function + | Some path -> + path + |> (function + | Rocq_config.Value.Path p -> p (* We have found a path for key *) + | path -> + (* This should never happen *) + Code_error.raise "key is not a path" [ key, Rocq_config.Value.to_dyn path ]) + | None -> + (* This happens if the output of rocq --config doesn't include the key *) + User_error.raise + [ Pp.concat + ~sep:Pp.space + [ Pp.text "key not found from"; User_message.command "rocq --config" ] + |> Pp.hovbox + ; Pp.text key + ] +;; + +let build_user_contrib ~vo ~path ~name = { name; path; vo; corelib = false } + +(* Scanning todos: blacklist? *) +let scan_vo ~dir dir_contents = + let f (d, kind) = + match kind with + (* Skip some files as Rocq does, for now files with '-' *) + | _ when String.contains d '-' -> None + | (File_kind.S_REG | S_LNK) when Filename.check_suffix d ".vo" -> + Some (Path.relative dir d) + | _ -> None + in + List.filter_map ~f dir_contents +;; + +(* Note this will only work for absolute paths *) +let retrieve_vo cps = List.concat_map ~f:vo cps + +module Scan_action = struct + type ('prefix, 'res) t = + dir:Path.t + -> prefix:'prefix + -> subresults:'res list + -> (Filename.t * File_kind.t) list + -> 'res list Memo.t +end + +(** [scan_path ~f ~acc ~prefix ~dir dir_contents] Given + [f ~dir + ~prefix ~subresults dir_contents], [scan_path] will call [f] + forall the subdirs of [dir] with [dir] set to the subpath, [prefix] set to + [acc prefix d] for each subdirectory [d] and [subresults] the results of the + scanning of children directories *) +let rec scan_path ~(f : ('prefix, 'res) Scan_action.t) ~acc ~prefix ~dir dir_contents + : 'a list Memo.t + = + let open Memo.O in + let f (d, kind) = + match kind with + (* We skip directories starting by . , this is mainly to avoid + .coq-native *) + | (File_kind.S_DIR | S_LNK) when d.[0] = '.' -> Memo.return [] + (* Need to check the link resolves to a directory! *) + | File_kind.S_DIR | S_LNK -> + let dir = Path.relative dir d in + let* dir_contents = Fs_memo.dir_contents (Path.as_outside_build_dir_exn dir) in + (match dir_contents with + | Error _ -> Memo.return [] + | Ok dir_contents -> + let dir_contents = Fs_cache.Dir_contents.to_list dir_contents in + let prefix = acc prefix d in + let* subresults = scan_path ~f ~acc ~prefix ~dir dir_contents in + f ~dir ~prefix ~subresults dir_contents) + | _ -> Memo.return [] + in + Memo.List.concat_map ~f dir_contents +;; + +let scan_path ~f ~acc ~prefix dir = + let open Memo.O in + let* dir_contents = Fs_memo.dir_contents (Path.as_outside_build_dir_exn dir) in + match dir_contents with + | Error _ -> Memo.return [] + | Ok dir_contents -> + let dir_contents = Fs_cache.Dir_contents.to_list dir_contents in + scan_path ~f ~acc ~prefix ~dir dir_contents +;; + +(** [scan_user_path path] Note that we already have very similar functionality + in [Dir_status] *) +let scan_user_path root_path = + let f ~dir ~prefix ~subresults dir_contents = + let vo = scan_vo ~dir dir_contents in + let vo_r = retrieve_vo subresults in + let vo = vo @ vo_r in + Memo.return (build_user_contrib ~vo ~path:dir ~name:prefix :: subresults) + in + scan_path ~f ~acc:Rocq_lib_name.append ~prefix:Rocq_lib_name.empty root_path +;; + +let scan_vo root_path = + let f ~dir ~prefix:() ~subresults dir_contents = + let vo = scan_vo ~dir dir_contents in + Memo.return (vo @ subresults) + in + let acc _ _ = () in + scan_path ~f ~acc ~prefix:() root_path +;; + +let of_rocq_install rocq = + let open Memo.O in + let* rocq_config = Rocq_config.make ~rocq:(Ok rocq) in + match rocq_config with + | Error msg -> + User_warning.emit + [ Pp.concat + ~sep:Pp.space + [ Pp.text "Skipping installed theories due to" + ; User_message.command "rocq --config" + ; Pp.text "failure:" + ] + |> Pp.hovbox + ; Pp.enumerate ~f:Fun.id [ msg ] + ] + ~hints: + [ Pp.concat + ~sep:Pp.space + [ Pp.text "Try running" + ; User_message.command "rocq --config" + ; Pp.text "manually to see the error." + ] + |> Pp.hovbox + ]; + Memo.return [] + | Ok rocq_config -> + (* Now we query for rocqlib *) + let rocqlib_path = config_path_exn rocq_config "rocqlib" in + let* vo = scan_vo rocqlib_path in + let corelib = + { name = Rocq_lib_name.corelib + ; path = Path.relative rocqlib_path "theories" + ; vo + ; corelib = true + } + in + let* user_contrib = + let contrib_path = Path.relative rocqlib_path "user-contrib" in + scan_user_path contrib_path + in + Memo.return (corelib :: user_contrib) +;; + +let of_rocq_install rocq = + (* If rocq was found in the _build directory then we must be composing + with Rocq and therefore cannot have any installed libs *) + if Path.is_in_build_dir rocq then Memo.return [] else of_rocq_install rocq +;; + +let of_rocq_install context = + let open Memo.O in + let* rocq = Context.which context "rocq" in + match rocq with + | None -> Memo.return [] + | Some rocq -> of_rocq_install rocq +;; + +let of_env env = + let rocqpath = + (* windows uses ';' *) + let rocqpath_sep = if Sys.cygwin then ';' else Bin.path_sep in + Env.get env "ROCQPATH" + |> function + | None -> [] + | Some rocqpath -> Bin.parse_path ~sep:rocqpath_sep rocqpath + in + Memo.List.concat_map rocqpath ~f:scan_user_path +;; diff --git a/src/dune_rules/rocq/rocq_path.mli b/src/dune_rules/rocq/rocq_path.mli new file mode 100644 index 00000000000..1e3e76f255e --- /dev/null +++ b/src/dune_rules/rocq/rocq_path.mli @@ -0,0 +1,36 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import + +(** A Rocq Path is a non-dune source of Rocq theories, these can come from Rocq's + stdlib and user-contrib location, and [ROCQPATH] environment variable. *) + +(** This module is similar to [Dir_contents] but for globally installed libs *) + +type t + +val name : t -> Rocq_lib_name.t +val path : t -> Path.t + +(** List of .vo files in a path *) +val vo : t -> Path.t list + +(** Does the path correspond to Rocq's [Corelib]? *) +val corelib : t -> bool + +(** Build list of Rocq paths from a Rocq install ([ROCQLIB] and [coqc -config]) *) +val of_rocq_install : Context.t -> t list Memo.t + +(** Build list of Rocq paths from [ROCQPATH] variable *) +val of_env : Env.t -> t list Memo.t diff --git a/src/dune_rules/rocq/rocq_rules.ml b/src/dune_rules/rocq/rocq_rules.ml new file mode 100644 index 00000000000..e6b59a382c3 --- /dev/null +++ b/src/dune_rules/rocq/rocq_rules.ml @@ -0,0 +1,1342 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import +open Memo.O + +(* Utilities independent from Rocq, they should be eventually moved + elsewhere; don't mix with the rest of the code. *) +module Util : sig + val include_flags : Lib.t list -> _ Command.Args.t + val meta_info : loc:Loc.t option -> context:Context_name.t -> Lib.t -> Path.t option + + (** Given a list of library names, we try to resolve them in order, returning + the first one that exists. *) + val resolve_first : Lib.DB.t -> string list -> Lib.t Resolve.Memo.t +end = struct + let include_paths ts = + Path.Set.of_list_map ts ~f:(fun t -> + let info = Lib.info t in + Lib_info.src_dir info) + ;; + + let include_flags ts = include_paths ts |> Lib_flags.L.to_iflags + + let meta_info ~loc ~context (lib : Lib.t) = + let name = Lib.name lib |> Lib_name.to_string in + match Lib_info.status (Lib.info lib) with + | Public (_, pkg) -> + let package = Package.name pkg in + let meta_i = + Path.Build.relative (Install.Context.lib_dir ~context ~package) "META" + in + Some (Path.build meta_i) + | Installed -> None + | Installed_private | Private _ -> + User_error.raise + ?loc + [ Pp.textf "Using private library %s as a Rocq plugin is not supported" name ] + ;; + + (* CR alizter: move this to Lib.DB *) + + (** Given a list of library names, we try to resolve them in order, returning + the first one that exists. *) + let rec resolve_first lib_db = function + | [] -> Code_error.raise "resolve_first: empty list" [] + | [ n ] -> Lib.DB.resolve lib_db (Loc.none, Lib_name.of_string n) + | n :: l -> + let open Memo.O in + Lib.DB.resolve_when_exists lib_db (Loc.none, Lib_name.of_string n) + >>= (function + | Some l -> Resolve.Memo.lift l + | None -> resolve_first lib_db l) + ;; +end + +let rocq ~loc ~dir ~sctx = + Super_context.resolve_program_memo + sctx + "rocq" + ~where:Original_path + ~dir + ~loc:(Some loc) + ~hint:"opam install rocq-runtime" +;; + +let select_native_mode ~sctx ~dir (buildable : Rocq_stanza.Buildable.t) = + match buildable.mode with + | Some x -> Memo.return x + | None -> + let* rocq = rocq ~sctx ~dir ~loc:buildable.loc in + let+ config = Rocq_config.make ~rocq in + (match config with + | Error _ -> Rocq_mode.VoOnly + | Ok config -> + (match Rocq_config.by_name config "rocq_native_compiler_default" with + | Some (String "yes") | Some (String "ondemand") -> Rocq_mode.Native + | _ -> Rocq_mode.VoOnly)) +;; + +let rocq_env = + let f = + Env_stanza_db_flags.flags + ~name:"rocq-env" + ~root:(fun _ _ -> Memo.return (Action_builder.return Rocq_flags.default)) + ~f:(fun ~parent expander (config : Dune_env.config) -> + Memo.return + @@ + let open Action_builder.O in + let+ rocq_flags = + let standard = + let+ x = Action_builder.of_memo_join parent in + x.rocq_flags + in + Expander.expand_and_eval_set expander (Rocq_env.flags config.rocq) ~standard + and+ rocqdep_flags = + let standard = + let+ x = Action_builder.of_memo_join parent in + x.rocqdep_flags + in + Expander.expand_and_eval_set + expander + (Rocq_env.rocqdep_flags config.rocq) + ~standard + and+ rocqdoc_flags = + let standard = + let+ x = Action_builder.of_memo_join parent in + x.rocqdoc_flags + in + Expander.expand_and_eval_set + expander + (Rocq_env.rocqdoc_flags config.rocq) + ~standard + and+ rocqdoc_header = + match Rocq_env.rocqdoc_header config.rocq with + | None -> + let+ x = Action_builder.of_memo_join parent in + x.rocqdoc_header + | Some s -> + let+ path = Expander.expand_path expander s in + Some path + and+ rocqdoc_footer = + match Rocq_env.rocqdoc_footer config.rocq with + | None -> + let+ x = Action_builder.of_memo_join parent in + x.rocqdoc_footer + | Some s -> + let+ path = Expander.expand_path expander s in + Some path + in + { Rocq_flags.rocq_flags + ; rocqdep_flags + ; rocqdoc_flags + ; rocqdoc_header + ; rocqdoc_footer + }) + in + fun ~dir -> + (let* () = Memo.return () in + (Staged.unstage f) dir) + |> Action_builder.of_memo_join +;; + +let rocq_flags ~dir ~stanza_flags ~per_file_flags ~expander = + let standard, flags_to_expand = + match per_file_flags with + | None -> + ( Action_builder.map + ~f:(fun { Rocq_flags.rocq_flags; _ } -> rocq_flags) + (rocq_env ~dir) + , stanza_flags ) + | Some per_file_flags -> + ( Action_builder.bind + ~f:(fun { Rocq_flags.rocq_flags; _ } -> + let standard = Action_builder.return rocq_flags in + Expander.expand_and_eval_set expander stanza_flags ~standard) + (rocq_env ~dir) + , per_file_flags ) + in + Expander.expand_and_eval_set expander flags_to_expand ~standard +;; + +let rocqdep_flags ~dir ~stanza_rocqdep_flags ~expander = + Expander.expand_and_eval_set + expander + stanza_rocqdep_flags + ~standard: + (Action_builder.map + ~f:(fun { Rocq_flags.rocqdep_flags; _ } -> rocqdep_flags) + (rocq_env ~dir)) +;; + +let rocqdoc_flags ~dir ~stanza_rocqdoc_flags ~expander = + Expander.expand_and_eval_set + expander + stanza_rocqdoc_flags + ~standard: + (Action_builder.map + ~f:(fun { Rocq_flags.rocqdoc_flags; _ } -> rocqdoc_flags) + (rocq_env ~dir)) +;; + +let rocqdoc_header ~dir ~stanza_rocqdoc_header ~expander = + match stanza_rocqdoc_header with + | None -> + Action_builder.map + ~f:(fun { Rocq_flags.rocqdoc_header; _ } -> rocqdoc_header) + (rocq_env ~dir) + | Some s -> Action_builder.map ~f:Option.some (Expander.expand_path expander s) +;; + +let rocqdoc_footer ~dir ~stanza_rocqdoc_footer ~expander = + match stanza_rocqdoc_footer with + | None -> + Action_builder.map + ~f:(fun { Rocq_flags.rocqdoc_footer; _ } -> rocqdoc_footer) + (rocq_env ~dir) + | Some s -> Action_builder.map ~f:Option.some (Expander.expand_path expander s) +;; + +let theory_rocqc_flag lib = + let name = Rocq_lib_name.wrapper (Rocq_lib.name lib) in + let dir = Rocq_lib.obj_root lib in + let binding_flag = if Rocq_lib.implicit lib then "-R" else "-Q" in + Command.Args.S [ A binding_flag; Path dir; A name ] +;; + +let theories_flags ~theories_deps = + Resolve.Memo.args + (let open Resolve.Memo.O in + let+ libs = theories_deps in + Command.Args.S (List.map ~f:theory_rocqc_flag libs)) +;; + +module Bootstrap : sig + type t = + | No_corelib (** The user set corelib = no , or we are compiling corelib itself *) + | Corelib of Rocq_lib.t (** Regular case, where [Corelib] is implicit *) + + val empty : t + + val make + : scope:Scope.t + -> use_stdlib:bool + -> wrapper_name:string + -> Rocq_module.t + -> t Resolve.Memo.t + + val flags : t -> 'a Command.Args.t +end = struct + type t = + | No_corelib (** The user set corelib = no , or we are compiling corelib itself *) + | Corelib of Rocq_lib.t (** Regular case, where [Corelib] is implicit *) + + (* For empty set of modules, we return Prelude which is kinda + conservative. *) + let empty = No_corelib + + (* Hack to know if a module is a prelude module *) + let check_init_module bootlib wrapper_name rocq_module = + String.equal (Rocq_lib_name.wrapper (Rocq_lib.name bootlib)) wrapper_name + && Option.equal + String.equal + (List.hd_opt (Rocq_module.prefix rocq_module)) + (Some "Init") + ;; + + (* [Bootstrap.t] determines, for a concrete Rocq module, how the Rocq + "standard library" is being handled. See the main modes above. *) + let make ~scope ~use_stdlib ~wrapper_name rocq_module = + let open Resolve.Memo.O in + let* boot_lib = + Scope.rocq_libs scope |> Resolve.Memo.lift_memo >>= Rocq_lib.DB.resolve_boot + in + if use_stdlib + then ( + match boot_lib with + | None -> + Resolve.Memo.fail + (User_message.make + [ Pp.text + "Couldn't find Rocq standard library, and theory is not using (stdlib \ + no)" + ]) + | Some (_loc, boot_lib) -> + Resolve.Memo.return + @@ + (* TODO: replace with per_file flags *) + let init = check_init_module boot_lib wrapper_name rocq_module in + if init then No_corelib else Corelib boot_lib) + else Resolve.Memo.return No_corelib + ;; + + let flags t : _ Command.Args.t = + match t with + | Corelib _ -> As [ "-boot" ] + | No_corelib -> As [ "-noinit"; "-boot" ] + ;; +end + +let rocqc_file_flags ~dir ~theories_deps ~wrapper_name ~ml_flags : _ Command.Args.t list = + let file_flags : _ Command.Args.t list = + [ Dyn (Resolve.Memo.read ml_flags) + ; theories_flags ~theories_deps + ; A "-R" + ; Path (Path.build dir) + ; A wrapper_name + ] + in + [ S file_flags ] +;; + +let native_includes ~dir = + let* scope = Scope.DB.find_by_dir dir in + let lib_db = Scope.libs scope in + (* We want the cmi files *) + Resolve.Memo.map ~f:(fun lib -> + let info = Lib.info lib in + let obj_dir = Obj_dir.public_cmi_ocaml_dir (Lib_info.obj_dir info) in + Path.Set.singleton obj_dir) + @@ Util.resolve_first lib_db [ "rocq-runtime.kernel" ] +;; + +let directories_of_lib ~sctx lib = + let name = Rocq_lib.name lib in + match lib with + | Rocq_lib.Dune lib -> + let dir = Rocq_lib.Dune.src_root lib in + let* dir_contents = Dir_contents.get sctx ~dir in + let+ rocq_sources = Dir_contents.rocq dir_contents in + Rocq_sources.directories rocq_sources ~name + | Rocq_lib.Legacy _ -> + (* TODO: we could return this if we don't restrict ourselves to + Path.Build.t here. + + EJGA: We need to understand how this interacts with globally + installed stuff, that's more tricky than it looks actually! + + This function is used in order to determine the -nI flags that + Rocq native compiler will pass to OCaml so it can find the .cmxs + files. For things in user-contrib we don't need to pass these + flags but only because Rocq has a very large hack adding this + directories on require. *) + Memo.return [] +;; + +let setup_native_theory_includes ~sctx ~theories_deps ~theory_dirs = + Resolve.Memo.bind theories_deps ~f:(fun theories_deps -> + let+ l = + Memo.parallel_map theories_deps ~f:(fun lib -> + let+ theory_dirs = directories_of_lib ~sctx lib in + Path.Build.Set.of_list theory_dirs) + in + Resolve.return (Path.Build.Set.union_all (theory_dirs :: l))) +;; + +let rocqc_native_flags ~sctx ~dir ~theories_deps ~theory_dirs ~(mode : Rocq_mode.t) = + match mode with + | VoOnly -> + Command.Args.As + [ "-w" + ; "-deprecated-native-compiler-option" + ; "-w" + ; "-native-compiler-disabled" + ; "-native-compiler" + ; "ondemand" + ] + | VosOnly -> + Command.Args.As + [ "-vos" + ; "-w" + ; "-deprecated-native-compiler-option" + ; "-w" + ; "-native-compiler-disabled" + ; "-native-compiler" + ; "ondemand" + ] + | Native -> + let args = + let open Action_builder.O in + let* native_includes = Resolve.Memo.read @@ native_includes ~dir in + let+ native_theory_includes = + Resolve.Memo.read + @@ setup_native_theory_includes ~sctx ~theories_deps ~theory_dirs + in + let include_ dir acc = Command.Args.Path dir :: A "-nI" :: acc in + let native_include_ml_args = Path.Set.fold native_includes ~init:[] ~f:include_ in + let native_include_theory_output = + Path.Build.Set.fold native_theory_includes ~init:[] ~f:(fun dir acc -> + include_ (Path.build dir) acc) + in + (* This dir is relative to the file, by default [.coq-native/] *) + Command.Args.S + [ Command.Args.As [ "-w"; "-deprecated-native-compiler-option" ] + ; As [ "-native-output-dir"; "." ] + ; As [ "-native-compiler"; "on" ] + ; S (List.rev native_include_ml_args) + ; S (List.rev native_include_theory_output) + ] + in + Command.Args.Dyn args +;; + +(* closure of all the ML libs a theory depends on *) +let libs_of_theory ~lib_db ~theories_deps plugins : (Lib.t list * _) Resolve.Memo.t = + let open Resolve.Memo.O in + let* libs = + Resolve.Memo.List.map plugins ~f:(fun (loc, name) -> + let+ lib = Lib.DB.resolve lib_db (loc, name) in + loc, lib) + in + let* theories = theories_deps in + (* Filter dune theories *) + let f (t : Rocq_lib.t) = + match t with + | Dune t -> Left t + | Legacy t -> Right t + in + let dune_theories, legacy_theories = List.partition_map ~f theories in + let* dlibs = + Resolve.List.concat_map ~f:Rocq_lib.Dune.libraries dune_theories |> Resolve.Memo.lift + in + let libs = libs @ dlibs in + let+ findlib_libs = Lib.closure ~linking:false (List.map ~f:snd libs) in + findlib_libs, legacy_theories +;; + +(* compute include flags and mlpack rules *) +let ml_pack_and_meta_rule ~context ~all_libs (buildable : Rocq_stanza.Buildable.t) + : unit Action_builder.t + = + (* rocqdep expects an mlpack file next to the sources otherwise it will + omit the cmxs deps *) + let plugin_loc = List.hd_opt buildable.plugins |> Option.map ~f:fst in + let meta_info = Util.meta_info ~loc:plugin_loc ~context in + Action_builder.paths (List.filter_map ~f:meta_info all_libs) +;; + +let ml_flags_and_ml_pack_rule + ~context + ~lib_db + ~theories_deps + (buildable : Rocq_stanza.Buildable.t) + = + let res = + let open Resolve.Memo.O in + let+ all_libs, _legacy_theories = + libs_of_theory ~lib_db ~theories_deps buildable.plugins + in + let findlib_plugin_flags = Util.include_flags all_libs in + let ml_flags = Command.Args.S [ findlib_plugin_flags ] in + ml_flags, ml_pack_and_meta_rule ~context ~all_libs buildable + in + let mlpack_rule = + let open Action_builder.O in + let* _, mlpack_rule = Resolve.Memo.read res in + mlpack_rule + in + Resolve.Memo.map ~f:fst res, mlpack_rule +;; + +let dep_theory_file ~dir ~wrapper_name = + Path.Build.relative dir ("." ^ wrapper_name) + |> Path.Build.set_extension ~ext:".theory.d" +;; + +let theory_rocq_args + ~sctx + ~dir + ~wrapper_name + ~boot_flags + ~stanza_flags + ~ml_flags + ~theories_deps + ~theory_dirs + = + let+ rocq_stanza_flags = + let+ expander = Super_context.expander sctx ~dir in + let rocq_flags = + let rocq_flags = rocq_flags ~expander ~dir ~stanza_flags ~per_file_flags:None in + (* By default we have the -q flag. We don't want to pass this to rocqtop to + allow users to load their .rocqrc files for interactive development. + Therefore we manually scrub the -q setting when passing arguments to + rocqtop. *) + let rec remove_q = function + | "-q" :: l -> remove_q l + | x :: l -> x :: remove_q l + | [] -> [] + in + let open Action_builder.O in + rocq_flags >>| remove_q + in + Command.Args.dyn rocq_flags (* stanza flags *) + in + let rocq_native_flags = + let mode = Rocq_mode.VoOnly in + rocqc_native_flags ~sctx ~dir ~theories_deps ~theory_dirs ~mode + in + let file_flags = rocqc_file_flags ~dir ~theories_deps ~wrapper_name ~ml_flags in + [ rocq_stanza_flags; rocq_native_flags; Dyn boot_flags; S file_flags ] +;; + +let setup_rocqproject_for_theory_rule + ~scope + ~sctx + ~dir + ~loc + ~theories_deps + ~wrapper_name + ~use_stdlib + ~ml_flags + ~stanza_flags + ~theory_dirs + rocq_modules + = + (* Process rocqdep and generate rules *) + let boot_type = + match rocq_modules with + | [] -> Resolve.Memo.return Bootstrap.empty + | m :: _ -> Bootstrap.make ~scope ~use_stdlib ~wrapper_name m + in + let boot_flags = Resolve.Memo.read boot_type |> Action_builder.map ~f:Bootstrap.flags in + let* args = + theory_rocq_args + ~sctx + ~dir + ~wrapper_name + ~boot_flags + ~stanza_flags + ~ml_flags + ~theories_deps + ~theory_dirs + in + let contents : string With_targets.t = + let open With_targets.O in + let dir = Path.build dir in + let+ args_bld = Command.expand ~dir (Command.Args.S args) + and+ args_src = + let dir = Path.source (Path.drop_build_context_exn dir) in + Command.expand ~dir (Command.Args.S args) + in + let contents = Buffer.create 73 in + let rec add_args args_bld args_src = + match args_bld, args_src with + | (("-R" | "-Q") as o) :: db :: mb :: args_bld, _ :: ds :: ms :: args_src -> + Buffer.add_string contents o; + Buffer.add_char contents ' '; + Buffer.add_string contents db; + Buffer.add_char contents ' '; + Buffer.add_string contents mb; + Buffer.add_char contents '\n'; + if db <> ds + then ( + Buffer.add_string contents o; + Buffer.add_char contents ' '; + Buffer.add_string contents ds; + Buffer.add_char contents ' '; + Buffer.add_string contents ms; + Buffer.add_char contents '\n'); + add_args args_bld args_src + | "-I" :: _ :: args_bld, "-I" :: d :: args_src -> + Buffer.add_string contents "-I "; + Buffer.add_string contents d; + Buffer.add_char contents '\n'; + add_args args_bld args_src + | o :: args_bld, _ :: args_src -> + Buffer.add_string contents "-arg "; + Buffer.add_string contents o; + Buffer.add_char contents '\n'; + add_args args_bld args_src + | [], [] -> () + | _, _ -> assert false + in + add_args args_bld args_src; + Buffer.contents contents + in + let mode = + let open Rule.Promote in + let lifetime = Lifetime.Until_clean in + Rule.Mode.Promote { lifetime; into = None; only = None } + in + let rocqproject = Path.Build.relative dir "_RocqProject" in + Super_context.add_rule + ~mode + ~loc + sctx + ~dir + (Action_builder.write_file_dyn rocqproject contents.build) +;; + +let setup_rocqdep_for_theory_rule + ~sctx + ~dir + ~loc + ~theories_deps + ~wrapper_name + ~source_rule + ~ml_flags + ~mlpack_rule + ~boot_flags + ~stanza_rocqdep_flags + rocq_modules + = + (* rocqdep needs the full source + plugin's mlpack to be present :( *) + let sources = List.rev_map ~f:Rocq_module.source rocq_modules in + let file_flags = + [ Command.Args.S (rocqc_file_flags ~dir ~theories_deps ~wrapper_name ~ml_flags) + ; As [ "-dyndep"; "opt"; "-vos" ] + ; Deps sources + ] + in + let extra_rocqdep_flags = + (* Standard flags for rocqdep *) + let open Action_builder.O in + let* expander = Action_builder.of_memo @@ Super_context.expander sctx ~dir in + rocqdep_flags ~dir ~stanza_rocqdep_flags ~expander + in + let rocqdep_flags = + Command.Args.A "dep" + :: Command.Args.Dyn boot_flags + :: Command.Args.dyn extra_rocqdep_flags + :: file_flags + in + let stdout_to = dep_theory_file ~dir ~wrapper_name in + let* rocq = rocq ~loc ~sctx ~dir in + (* Rocqdep has to be called in the stanza's directory *) + Super_context.add_rule + ~loc + sctx + ~dir + (let open Action_builder.With_targets.O in + Action_builder.with_no_targets mlpack_rule + >>> Action_builder.(with_no_targets (goal source_rule)) + >>> Command.run ~dir:(Path.build dir) ~stdout_to rocq rocqdep_flags) +;; + +module Dep_map = Stdune.Map.Make (Path) + +let rocqdep_invalid phase line = + Code_error.raise + "coqdep returned invalid output" + [ "phase", Dyn.string phase; "line", Dyn.string line ] +;; + +(* Handle the case where the path contains ":" and rocqdep escapes this + as "\:" causing Dune to misinterpret the path. We revert + the escaping, which allows dune to work on Windows. + + Note that rocqdep escapes a few more things, including spaces, $, #, + [], ?, %, homedir... How to handle that seems tricky. +*) +let escaped_colon = Re.compile (Re.str "\\:") +let unescape_rocqdep string = Re.replace_string escaped_colon ~by:":" string + +let parse_line ~dir line = + match String.lsplit2 line ~on:':' with + | None -> rocqdep_invalid "split" line + | Some (basename, deps) -> + (* This should always have a file, but let's handle the error + properly *) + let target = + match String.extract_blank_separated_words basename with + | [] -> rocqdep_invalid "target" line + | vo :: _ -> vo + in + (* let depname, ext = Filename.split_extension ff in *) + let target = Path.relative (Path.build dir) target in + (* EJGA: XXX using `String.extract_blank_separated_words` works + for OCaml, but not for Rocq as we don't use `-modules` *) + let deps = unescape_rocqdep deps |> String.extract_blank_separated_words in + (* Add prelude deps for when stdlib is in scope and we are not actually + compiling the prelude *) + let deps = List.map ~f:(Path.relative (Path.build dir)) deps in + target, deps +;; + +let get_dep_map ~dir ~wrapper_name : Path.t list Dep_map.t Action_builder.t = + let file = dep_theory_file ~dir ~wrapper_name in + let open Action_builder.O in + let f = parse_line ~dir in + Action_builder.lines_of (Path.build file) + >>| fun lines -> + List.map ~f lines + |> Dep_map.of_list + |> function + | Ok map -> map + | Error (k, r1, r2) -> + Code_error.raise + "get_dep_map: duplicate keys" + [ "lines", Dyn.list Dyn.string lines + ; "key", Path.to_dyn k + ; "entry 1", Dyn.list Path.to_dyn r1 + ; "entry 2", Dyn.list Path.to_dyn r2 + ] +;; + +(* EJGA: Would be nice to have a functor in [Stdune.Tuple] to do this *) +module DWInput : Memo.Input with type t = Path.Build.t * string = struct + type t = Path.Build.t * string + + let hash = Tuple.T2.hash Path.Build.hash String.hash + let equal = Tuple.T2.equal Path.Build.equal String.equal + let to_dyn = Tuple.T2.to_dyn Path.Build.to_dyn String.to_dyn +end + +(* EJGA: with this code, we have a combined memo node that will be + re-executed iff [dir], [wrapper_name], or the deps of the original + action builder (the [.v.d] file from [dep_theory_file ~dir + ~wrapper_name]) change *) +let memo_get_dep_map = + Action_builder.create_memo + "rocq_dep_map" + ~input:(module DWInput) + (fun (dir, wrapper_name) -> get_dep_map ~dir ~wrapper_name) +;; + +let deps_of ~dir ~boot_type ~wrapper_name ~mode rocq_module = + let open Action_builder.O in + let vo_target = + let ext = + match mode with + | Rocq_mode.VosOnly -> ".vos" + | _ -> ".vo" + in + Path.set_extension ~ext (Rocq_module.source rocq_module) + in + let* dep_map = Action_builder.exec_memo memo_get_dep_map (dir, wrapper_name) in + let* boot_type = Resolve.Memo.read boot_type in + match Dep_map.find dep_map vo_target with + | None -> + Code_error.raise + "Dep_map.find failed for" + [ "rocq_module", Rocq_module.to_dyn rocq_module + ; "dep_map", Dep_map.to_dyn (Dyn.list Path.to_dyn) dep_map + ] + | Some deps -> + (* Inject prelude deps *) + let deps = + let prelude = "Init/Prelude.vo" in + match boot_type with + | Bootstrap.No_corelib -> deps + | Bootstrap.Corelib lib -> Path.relative (Rocq_lib.obj_root lib) prelude :: deps + in + Action_builder.paths deps +;; + +let generic_rocq_args + ~sctx + ~dir + ~wrapper_name + ~boot_flags + ~per_file_flags + ~mode + ~rocq_prog + ~stanza_flags + ~ml_flags + ~theories_deps + ~theory_dirs + rocq_module + = + let+ rocq_stanza_flags = + let+ expander = Super_context.expander sctx ~dir in + let rocq_flags = + let rocq_flags = rocq_flags ~expander ~dir ~stanza_flags ~per_file_flags in + (* By default we have the -q flag. We don't want to pass this to rocqtop to + allow users to load their .rocqrc files for interactive development. + Therefore we manually scrub the -q setting when passing arguments to + rocqtop. *) + match rocq_prog with + | `Rocqtop -> + let rec remove_q = function + | "-q" :: l -> remove_q l + | x :: l -> x :: remove_q l + | [] -> [] + in + let open Action_builder.O in + rocq_flags >>| remove_q + | _ -> rocq_flags + in + Command.Args.dyn rocq_flags (* stanza flags *) + in + let rocq_native_flags = + let mode = + (* Tweak the modes for rocqtop since it has no "-vos" option *) + match mode, rocq_prog with + | Rocq_mode.VosOnly, `Rocqtop -> Rocq_mode.VoOnly + | _ -> mode + in + rocqc_native_flags ~sctx ~dir ~theories_deps ~theory_dirs ~mode + in + let file_flags = rocqc_file_flags ~dir ~theories_deps ~wrapper_name ~ml_flags in + match rocq_prog with + | `Rocqc -> + [ rocq_stanza_flags + ; rocq_native_flags + ; Dyn boot_flags + ; S file_flags + ; Dep (Rocq_module.source rocq_module) + ] + | `Rocqtop -> [ rocq_stanza_flags; rocq_native_flags; Dyn boot_flags; S file_flags ] +;; + +module Per_file = struct + let match_ map rocq_module = + let open Option.O in + let* map = map in + let rocq_lib_name = Rocq_module.name rocq_module in + Rocq_module.Name.Map.find map rocq_lib_name + ;; +end + +let setup_rocqc_rule + ~scope + ~loc + ~dir + ~sctx + ~rocqc_dir + ~file_targets + ~stanza_flags + ~modules_flags + ~theories_deps + ~mode + ~wrapper_name + ~use_stdlib + ~ml_flags + ~theory_dirs + rocq_module + = + (* Process rocqdep and generate rules *) + let boot_type = Bootstrap.make ~scope ~use_stdlib ~wrapper_name rocq_module in + let boot_flags = Resolve.Memo.read boot_type |> Action_builder.map ~f:Bootstrap.flags in + (* TODO: merge with boot_type *) + let per_file_flags = Per_file.match_ modules_flags rocq_module in + let* rocq = rocq ~loc ~dir ~sctx in + let obj_files = + Rocq_module.obj_files + ~wrapper_name + ~mode + ~obj_files_mode:Rocq_module.Build + ~obj_dir:dir + rocq_module + |> List.map ~f:fst + in + let target_obj_files = Command.Args.Hidden_targets obj_files in + let* args = + generic_rocq_args + ~sctx + ~dir + ~wrapper_name + ~boot_flags + ~per_file_flags + ~stanza_flags + ~ml_flags + ~theories_deps + ~theory_dirs + ~mode + ~rocq_prog:`Rocqc + rocq_module + in + let deps_of = deps_of ~dir ~boot_type ~wrapper_name ~mode rocq_module in + let cflag = Command.Args.A "compile" in + let open Action_builder.With_targets.O in + Super_context.add_rule + ~loc + ~dir + sctx + (Action_builder.with_no_targets deps_of + >>> Action_builder.With_targets.add ~file_targets + @@ Command.run + ~dir:(Path.build rocqc_dir) + rocq + (cflag :: target_obj_files :: args) + (* The way we handle the transitive dependencies of .vo files is not safe for + sandboxing *) + >>| Action.Full.add_sandbox Sandbox_config.no_sandboxing) +;; + +let rocq_modules_of_theory ~sctx lib = + Action_builder.of_memo + @@ + let name = Rocq_lib.name lib in + match lib with + | Rocq_lib.Legacy lib -> Memo.return @@ Rocq_lib.Legacy.vo lib + | Rocq_lib.Dune lib -> + let dir = Rocq_lib.Dune.src_root lib in + let* dir_contents = Dir_contents.get sctx ~dir in + let+ rocq_sources = Dir_contents.rocq dir_contents in + Rocq_sources.library rocq_sources ~name |> List.rev_map ~f:Rocq_module.source +;; + +let source_rule ~sctx theories = + (* sources for depending libraries rocqdep requires all the files to be in the + tree to produce correct dependencies, including those of dependencies *) + Action_builder.dyn_paths_unit + (let open Action_builder.O in + let+ l = Action_builder.List.map theories ~f:(rocq_modules_of_theory ~sctx) in + List.concat l) +;; + +let setup_rocqdoc_rules ~sctx ~dir ~theories_deps (s : Rocq_stanza.Theory.t) rocq_modules = + let loc, name = s.buildable.loc, snd s.name in + let rule = + let file_flags = + (* BUG: We need to pass --rocqlib depending on the boot_type otherwise + rocqdoc will not work. *) + [ theories_flags ~theories_deps + ; A "-R" + ; Path (Path.build dir) + ; A (Rocq_lib_name.wrapper (snd s.name)) + ] + in + fun mode -> + let* () = + let* rocq = rocq ~loc ~sctx ~dir in + (let doc_dir = Rocq_doc.rocqdoc_directory ~mode ~obj_dir:dir ~name in + let file_flags = + let globs = + let open Action_builder.O in + let* theories_deps = Resolve.Memo.read theories_deps in + Action_builder.of_memo + @@ + let open Memo.O in + let+ deps = + Memo.parallel_map theories_deps ~f:(fun theory -> + let+ theory_dirs = directories_of_lib ~sctx theory in + Dep.Set.of_list_map theory_dirs ~f:(fun dir -> + (* TODO *) + Glob.of_string_exn Loc.none "*.glob" + |> File_selector.of_glob ~dir:(Path.build dir) + |> Dep.file_selector)) + in + Command.Args.Hidden_deps (Dep.Set.union_all deps) + in + let mode_flag = + match mode with + | `Html -> "--html" + | `Latex -> "--latex" + in + let extra_rocqdoc_flags = + (* Standard flags for rocqdoc *) + let open Action_builder.O in + let* expander = Action_builder.of_memo @@ Super_context.expander sctx ~dir in + let standard = + rocqdoc_flags ~dir ~stanza_rocqdoc_flags:s.rocqdoc_flags ~expander + in + Expander.expand_and_eval_set expander s.rocqdoc_flags ~standard + in + let header = + let open Action_builder.O in + let* expander = Action_builder.of_memo @@ Super_context.expander sctx ~dir in + let+ header = + rocqdoc_header ~dir ~stanza_rocqdoc_header:s.rocqdoc_header ~expander + in + match header with + | None -> Command.Args.empty + | Some path -> Command.Args.S [ A "--with-header"; Dep path ] + in + let footer = + let open Action_builder.O in + let* expander = Action_builder.of_memo @@ Super_context.expander sctx ~dir in + let+ footer = + rocqdoc_footer ~dir ~stanza_rocqdoc_footer:s.rocqdoc_footer ~expander + in + match footer with + | None -> Command.Args.empty + | Some path -> Command.Args.S [ A "--with-footer"; Dep path ] + in + let when_html dyn = + match mode with + | `Html -> Command.Args.Dyn dyn + | `Latex -> Command.Args.empty + in + [ Command.Args.A "doc" + ; Command.Args.S file_flags + ; Command.Args.dyn extra_rocqdoc_flags + ; when_html header + ; when_html footer + ; A mode_flag + ; A "-d" + ; Path (Path.build doc_dir) + ; Deps (List.map ~f:Rocq_module.source rocq_modules) + ; Dyn globs + ; Hidden_deps + (Dep.Set.of_files + @@ List.map ~f:Path.build + @@ List.map ~f:(Rocq_module.glob_file ~obj_dir:dir) rocq_modules) + ] + in + Command.run + ~sandbox:Sandbox_config.needs_sandboxing + ~dir:(Path.build dir) + rocq + file_flags + |> Action_builder.With_targets.map + ~f: + (Action.Full.map ~f:(fun rocqdoc -> + Action.Progn [ Action.mkdir doc_dir; rocqdoc ])) + |> Action_builder.With_targets.add_directories ~directory_targets:[ doc_dir ]) + |> Super_context.add_rule ~loc ~dir sctx + in + let alias = + match mode with + | `Html -> Alias.make Alias0.doc ~dir + | `Latex -> Alias.make (Alias.Name.of_string "doc-latex") ~dir + in + Rocq_doc.rocqdoc_directory ~mode ~obj_dir:dir ~name + |> Path.build + |> Action_builder.path + |> Rules.Produce.Alias.add_deps alias ~loc + in + rule `Html >>> rule `Latex +;; + +(* Common context for a theory, deps and rules *) +let theory_context ~context ~scope ~name buildable = + let theory = + let* rocq_lib_db = Scope.rocq_libs scope in + Rocq_lib.DB.resolve rocq_lib_db name + in + let theories_deps = + Resolve.Memo.bind theory ~f:(fun theory -> + Resolve.Memo.lift @@ Rocq_lib.theories_closure theory) + in + (* ML-level flags for depending libraries *) + let ml_flags, mlpack_rule = + let lib_db = Scope.libs scope in + ml_flags_and_ml_pack_rule ~context ~theories_deps ~lib_db buildable + in + theory, theories_deps, ml_flags, mlpack_rule +;; + +(* Common context for extraction, almost the same than above *) +let extraction_context ~context ~scope (buildable : Rocq_stanza.Buildable.t) = + let rocq_lib_db = Scope.rocq_libs scope in + let theories_deps = + let* rocq_lib_db = rocq_lib_db in + Resolve.Memo.List.map buildable.theories ~f:(Rocq_lib.DB.resolve rocq_lib_db) + in + (* Extraction requires a boot library so we do this unconditionally + for now. We must do this because it can happen that + s.buildable.theories is empty *) + let boot = + let* rocq_lib_db = rocq_lib_db in + Rocq_lib.DB.resolve_boot rocq_lib_db + in + let theories_deps = + let open Resolve.Memo.O in + let+ boot = boot + and+ theories_deps = theories_deps in + match boot with + | None -> theories_deps + | Some (_, boot) -> boot :: theories_deps + in + let ml_flags, mlpack_rule = + let lib_db = Scope.libs scope in + ml_flags_and_ml_pack_rule ~context ~theories_deps ~lib_db buildable + in + theories_deps, ml_flags, mlpack_rule +;; + +let setup_theory_rules ~sctx ~dir ~dir_contents (s : Rocq_stanza.Theory.t) = + let* scope = Scope.DB.find_by_dir dir in + let name = s.name in + let theory, theories_deps, ml_flags, mlpack_rule = + let context = Super_context.context sctx |> Context.name in + theory_context ~context ~scope ~name s.buildable + in + let wrapper_name = Rocq_lib_name.wrapper (snd s.name) in + let use_stdlib = s.buildable.use_stdlib in + let name = snd s.name in + let loc = s.buildable.loc in + let stanza_flags = s.buildable.flags in + let modules_flags = Option.map s.modules_flags ~f:Rocq_module.Name.Map.of_list_exn in + let* rocq_dir_contents = Dir_contents.rocq dir_contents in + let theory_dirs = + Rocq_sources.directories rocq_dir_contents ~name |> Path.Build.Set.of_list + in + let rocq_modules = Rocq_sources.library rocq_dir_contents ~name in + let source_rule = + let theories = + let open Resolve.Memo.O in + let+ theory = theory + and+ theories = theories_deps in + theory :: theories + in + let open Action_builder.O in + let* theories = Resolve.Memo.read theories in + source_rule ~sctx theories + in + let rocqc_dir = Super_context.context sctx |> Context.build_dir in + let* mode = select_native_mode ~sctx ~dir s.buildable in + (* First we setup the rule calling rocqdep *) + let boot_type = + (* If rocq_modules are empty it doesn't really matter, so we take + the more conservative path and pass -boot, we don't care here + about -noinit as rocqdep ignores it *) + match rocq_modules with + | [] -> Resolve.Memo.return Bootstrap.empty + | m :: _ -> Bootstrap.make ~scope ~use_stdlib ~wrapper_name m + in + let boot_flags = Resolve.Memo.read boot_type |> Action_builder.map ~f:Bootstrap.flags in + (if not (snd s.generate_project_file) + then Memo.return () + else + setup_rocqproject_for_theory_rule + ~scope + ~sctx + ~dir + ~loc + ~theories_deps + ~wrapper_name + ~use_stdlib + ~ml_flags + ~stanza_flags + ~theory_dirs + rocq_modules) + >>> setup_rocqdep_for_theory_rule + ~sctx + ~dir + ~loc + ~theories_deps + ~wrapper_name + ~source_rule + ~ml_flags + ~mlpack_rule + ~boot_flags + ~stanza_rocqdep_flags:s.rocqdep_flags + rocq_modules + >>> Memo.parallel_iter + rocq_modules + ~f: + (setup_rocqc_rule + ~scope + ~loc + ~dir + ~sctx + ~file_targets:[] + ~stanza_flags + ~modules_flags + ~rocqc_dir + ~theories_deps + ~mode + ~wrapper_name + ~use_stdlib + ~ml_flags + ~theory_dirs) + (* And finally the rocqdoc rules *) + >>> setup_rocqdoc_rules ~sctx ~dir ~theories_deps s rocq_modules +;; + +let rocqtop_args_theory ~sctx ~dir ~dir_contents (s : Rocq_stanza.Theory.t) rocq_module = + let* scope = Scope.DB.find_by_dir dir in + let name = s.name in + let _theory, theories_deps, ml_flags, _mlpack_rule = + let context = Super_context.context sctx |> Context.name in + theory_context ~context ~scope ~name s.buildable + in + let wrapper_name = Rocq_lib_name.wrapper (snd s.name) in + let* mode = select_native_mode ~sctx ~dir s.buildable in + let name = snd s.name in + let use_stdlib = s.buildable.use_stdlib in + let boot_type = Bootstrap.make ~scope ~use_stdlib ~wrapper_name rocq_module in + let* rocq_dir_contents = Dir_contents.rocq dir_contents in + let theory_dirs = + Rocq_sources.directories rocq_dir_contents ~name |> Path.Build.Set.of_list + in + let boot_flags = Resolve.Memo.read boot_type |> Action_builder.map ~f:Bootstrap.flags in + let per_file_flags = None in + generic_rocq_args + ~sctx + ~dir + ~wrapper_name + ~boot_flags + ~per_file_flags + ~mode + ~rocq_prog:`Rocqtop + ~stanza_flags:s.buildable.flags + ~ml_flags + ~theories_deps + ~theory_dirs + rocq_module +;; + +(******************************************************************************) +(* Install rules *) +(******************************************************************************) + +let install_rules ~sctx ~dir s = + match s with + | { Rocq_stanza.Theory.package = None; _ } -> Memo.return [] + | { Rocq_stanza.Theory.package = Some _package; buildable; _ } -> + let loc = s.buildable.loc in + let* mode = select_native_mode ~sctx ~dir buildable in + let* scope = Scope.DB.find_by_dir dir in + (* We force the rocq scope for this DB as to fail early in case of + some library conflicts that would also generate conflicting + install rules. This is needed as now install rules less lazy + than the theory rules. *) + let _ = Scope.rocq_libs scope in + let* dir_contents = Dir_contents.get sctx ~dir in + let name = snd s.name in + (* This must match the wrapper prefix for now to remain compatible *) + let dst_suffix = Rocq_lib_name.dir name in + (* These are the rules for now, rocq lang 2.0 will make this uniform *) + let dst_dir = + if s.boot + then (* We drop the "Corelib" prefix (!) *) + Path.Local.of_string "coq/theories" + else ( + let rocq_root = Path.Local.of_string "coq/user-contrib" in + Path.Local.relative rocq_root dst_suffix) + in + let wrapper_name = Rocq_lib_name.wrapper name in + let to_path f = Path.reach ~from:(Path.build dir) (Path.build f) in + let to_dst f = Path.Local.to_string @@ Path.Local.relative dst_dir f in + let make_entry (orig_file : Path.Build.t) (dst_file : string) = + let entry = + Install.Entry.make Section.Lib_root ~dst:(to_dst dst_file) orig_file ~kind:`File + in + Install.Entry.Sourced.create ~loc entry + in + let+ rocq_sources = Dir_contents.rocq dir_contents in + rocq_sources + |> Rocq_sources.library ~name + |> List.concat_map ~f:(fun (vfile : Rocq_module.t) -> + let obj_files = + Rocq_module.obj_files + ~wrapper_name + ~mode + ~obj_dir:dir + ~obj_files_mode:Rocq_module.Install + vfile + |> List.map ~f:(fun ((vo_file : Path.Build.t), (install_vo_file : string)) -> + make_entry vo_file install_vo_file) + in + let vfile = Rocq_module.source vfile |> Path.as_in_build_dir_exn in + let vfile_dst = to_path vfile in + make_entry vfile vfile_dst :: obj_files) +;; + +let setup_rocqpp_rules ~sctx ~dir ({ loc; modules } : Rocq_stanza.Rocqpp.t) = + let* rocq = rocq ~loc ~sctx ~dir + and* mlg_files = Rocq_sources.mlg_files ~sctx ~dir ~modules in + let mlg_rule m = + let source = Path.build m in + let target = Path.Build.set_extension m ~ext:".ml" in + let args = [ Command.Args.A "pp-mlg"; Dep source; Hidden_targets [ target ] ] in + let build_dir = Super_context.context sctx |> Context.build_dir in + Command.run ~dir:(Path.build build_dir) rocq args + in + List.rev_map ~f:mlg_rule mlg_files |> Super_context.add_rules ~loc ~dir sctx +;; + +let setup_extraction_rules ~sctx ~dir ~dir_contents (s : Rocq_stanza.Extraction.t) = + let wrapper_name = "DuneExtraction" in + let* rocq_module = + let+ rocq = Dir_contents.rocq dir_contents in + Rocq_sources.extract rocq s + in + let file_targets = + Rocq_stanza.Extraction.ml_target_fnames s |> List.map ~f:(Path.Build.relative dir) + in + let loc = s.buildable.loc in + let use_stdlib = s.buildable.use_stdlib in + let* scope = Scope.DB.find_by_dir dir in + let theories_deps, ml_flags, mlpack_rule = + let context = Super_context.context sctx |> Context.name in + extraction_context ~context ~scope s.buildable + in + let source_rule = + let open Action_builder.O in + let* theories_deps = Resolve.Memo.read theories_deps in + source_rule ~sctx theories_deps + >>> Action_builder.path (Rocq_module.source rocq_module) + in + let* mode = select_native_mode ~sctx ~dir s.buildable in + let boot_type = + (* If rocq_modules are empty it doesn't really matter, so we take + the more conservative path and pass -boot, we don't care here + about -noinit as rocqdep ignores it *) + match [ rocq_module ] with + | [] -> Resolve.Memo.return Bootstrap.empty + | m :: _ -> Bootstrap.make ~scope ~use_stdlib ~wrapper_name m + in + let boot_flags = Resolve.Memo.read boot_type |> Action_builder.map ~f:Bootstrap.flags in + let modules_flags = None in + setup_rocqdep_for_theory_rule + ~sctx + ~dir + ~loc + ~theories_deps + ~wrapper_name + ~source_rule + ~ml_flags + ~mlpack_rule + ~boot_flags + ~stanza_rocqdep_flags:Ordered_set_lang.Unexpanded.standard + [ rocq_module ] + >>> setup_rocqc_rule + ~scope + ~file_targets + ~stanza_flags:s.buildable.flags + ~modules_flags + ~sctx + ~loc + ~rocqc_dir:dir + rocq_module + ~dir + ~theories_deps + ~mode + ~wrapper_name + ~use_stdlib:s.buildable.use_stdlib + ~ml_flags + ~theory_dirs:Path.Build.Set.empty +;; + +let rocqtop_args_extraction ~sctx ~dir (s : Rocq_stanza.Extraction.t) rocq_module = + let use_stdlib = s.buildable.use_stdlib in + let* scope = Scope.DB.find_by_dir dir in + let theories_deps, ml_flags, _mlpack_rule = + let context = Super_context.context sctx |> Context.name in + extraction_context ~context ~scope s.buildable + in + let wrapper_name = "DuneExtraction" in + let boot_type = Bootstrap.make ~scope ~use_stdlib ~wrapper_name rocq_module in + let boot_flags = Resolve.Memo.read boot_type |> Action_builder.map ~f:Bootstrap.flags in + let per_file_flags = None in + let* mode = select_native_mode ~sctx ~dir s.buildable in + generic_rocq_args + ~sctx + ~dir + ~wrapper_name + ~boot_flags + ~per_file_flags + ~mode + ~rocq_prog:`Rocqtop + ~stanza_flags:s.buildable.flags + ~ml_flags + ~theories_deps + ~theory_dirs:Path.Build.Set.empty + rocq_module +;; + +(* Version for export *) +let deps_of ~dir ~use_stdlib ~wrapper_name ~mode rocq_module = + let boot_type = + let open Memo.O in + let* scope = Scope.DB.find_by_dir dir in + Bootstrap.make ~scope ~use_stdlib ~wrapper_name rocq_module + in + deps_of ~dir ~boot_type ~wrapper_name ~mode rocq_module +;; diff --git a/src/dune_rules/rocq/rocq_rules.mli b/src/dune_rules/rocq/rocq_rules.mli new file mode 100644 index 00000000000..9e7216cb64f --- /dev/null +++ b/src/dune_rules/rocq/rocq_rules.mli @@ -0,0 +1,76 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import + +(** [deps_of ~dir ~use_stdlib ~wrapper_name rocq_module] action that builds the + deps of [rocq_module] *) +val deps_of + : dir:Path.Build.t + -> use_stdlib:bool + -> wrapper_name:string + -> mode:Rocq_mode.t + -> Rocq_module.t + -> unit Dune_engine.Action_builder.t + +(** ** Rules for Rocq stanzas *) + +(** [rocq.theory] stanza rules *) +val setup_theory_rules + : sctx:Super_context.t + -> dir:Path.Build.t + -> dir_contents:Dir_contents.t + -> Rocq_stanza.Theory.t + -> unit Memo.t + +(** Arguments for `dune rocq top` in presence of rocq.theory. *) +val rocqtop_args_theory + : sctx:Super_context.t + -> dir:Path.Build.t + -> dir_contents:Dir_contents.t + -> Rocq_stanza.Theory.t + -> Rocq_module.t + -> 'a Command.Args.t list Memo.t + +(** rocq.extraction stanza rules *) +val setup_extraction_rules + : sctx:Super_context.t + -> dir:Path.Build.t + -> dir_contents:Dir_contents.t + -> Rocq_stanza.Extraction.t + -> unit Memo.t + +(** Arguments for `dune rocq top` in presence of rocq.extraction. *) +val rocqtop_args_extraction + : sctx:Super_context.t + -> dir:Path.Build.t + -> Rocq_stanza.Extraction.t + -> Rocq_module.t + -> 'a Command.Args.t list Memo.t + +(** Rules for .mlg to .ml transformation *) +val setup_rocqpp_rules + : sctx:Super_context.t + -> dir:Path.Build.t + -> Rocq_stanza.Rocqpp.t + -> unit Memo.t + +(** Install rules for a Rocq package *) +val install_rules + : sctx:Super_context.t + -> dir:Path.Build.t + -> Rocq_stanza.Theory.t + -> Install.Entry.Sourced.t list Memo.t + +(** Compute the effective Rocq enviroment *) +val rocq_env : dir:Path.Build.t -> Rocq_flags.t Action_builder.t diff --git a/src/dune_rules/rocq/rocq_scope.ml b/src/dune_rules/rocq/rocq_scope.ml new file mode 100644 index 00000000000..41f8a59bfc0 --- /dev/null +++ b/src/dune_rules/rocq/rocq_scope.ml @@ -0,0 +1,85 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import +open Memo.O + +type t = { scopes : Rocq_lib.DB.t Lazy.t Path.Source.Map.t Memo.Lazy.t } + +let public_theories context public_libs rocq_stanzas = + let+ installed_theories = + let+ rocqpaths_of_rocq = Rocq_path.of_rocq_install context + and+ rocqpaths_of_env = Context.installed_env context >>= Rocq_path.of_env in + Rocq_lib.DB.create_from_rocqpaths (rocqpaths_of_env @ rocqpaths_of_rocq) + in + List.filter_map rocq_stanzas ~f:(fun (dir, (stanza : Rocq_stanza.Theory.t)) -> + if Option.is_some stanza.package + then Some (stanza, Rocq_lib.DB.Entry.Theory dir) + else None) + |> Rocq_lib.DB.create_from_rocqlib_stanzas + ~find_db:(Fun.const public_libs) + ~parent:(Some installed_theories) +;; + +let rocq_scopes_by_dir + db_by_project_dir + projects_by_dir + public_theories + rocq_stanzas_by_project_dir + = + let parent = Some public_theories in + let find_db dir = + snd (Find_closest_source_dir.find_by_dir_exn db_by_project_dir ~dir) + in + Path.Source.Map.merge + projects_by_dir + rocq_stanzas_by_project_dir + ~f:(fun _dir project rocq_stanzas -> + assert (Option.is_some project); + Option.some + @@ lazy + (let rocq_stanzas = Option.value rocq_stanzas ~default:[] in + List.map rocq_stanzas ~f:(fun (dir, (stanza : Rocq_stanza.Theory.t)) -> + let (entry : Rocq_lib.DB.Entry.t) = + match stanza.package with + | None -> Theory dir + | Some _ -> Redirect public_theories + in + stanza, entry) + |> Rocq_lib.DB.create_from_rocqlib_stanzas ~parent ~find_db)) +;; + +let rocq_stanzas_by_project_dir rocq_stanzas = + List.map rocq_stanzas ~f:(fun (dir, (stanza : Rocq_stanza.Theory.t)) -> + let project = stanza.project in + Dune_project.root project, (dir, stanza)) + |> Path.Source.Map.of_list_multi +;; + +let make context ~public_libs ~db_by_project_dir ~projects_by_root rocq_stanzas = + { scopes = + Memo.lazy_ (fun () -> + let+ public_theories = public_theories context public_libs rocq_stanzas in + let rocq_stanzas_by_project_dir = rocq_stanzas_by_project_dir rocq_stanzas in + rocq_scopes_by_dir + db_by_project_dir + projects_by_root + public_theories + rocq_stanzas_by_project_dir) + } +;; + +let find t ~dir = + let+ scopes = Memo.Lazy.force t.scopes in + Path.Source.Map.find_exn scopes dir |> Lazy.force +;; diff --git a/src/dune_rules/rocq/rocq_scope.mli b/src/dune_rules/rocq/rocq_scope.mli new file mode 100644 index 00000000000..40f7ee70154 --- /dev/null +++ b/src/dune_rules/rocq/rocq_scope.mli @@ -0,0 +1,26 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import + +type t + +val make + : Context.t + -> public_libs:Lib.DB.t + -> db_by_project_dir:('a * Lib.DB.t) Path.Source.Map.t + -> projects_by_root:'b Path.Source.Map.t + -> (Path.Build.t * Rocq_stanza.Theory.t) list + -> t + +val find : t -> dir:Path.Source.t -> Rocq_lib.DB.t Memo.t diff --git a/src/dune_rules/rocq/rocq_sources.ml b/src/dune_rules/rocq/rocq_sources.ml new file mode 100644 index 00000000000..20973182118 --- /dev/null +++ b/src/dune_rules/rocq/rocq_sources.ml @@ -0,0 +1,143 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import +open Rocq_stanza + +(* TODO: Build reverse map and check duplicates, however, are duplicates + harmful? + + In Rocq all libs are "wrapped" so including a module twice is not so bad. *) +type t = + { libraries : Rocq_module.t list Rocq_lib_name.Map.t + ; directories : Path.Build.t list Rocq_lib_name.Map.t + (* [directories] is used to compute the include paths for Rocq's native + mode *) + ; extract : Rocq_module.t Loc.Map.t + ; rev_map : [ `Theory of Theory.t | `Extraction of Extraction.t ] Rocq_module.Map.t + } + +let find_module ~source t = + let f m = Path.equal (Path.build source) (Rocq_module.source m) in + Rocq_lib_name.Map.Multi.find_elt t.libraries ~f +;; + +let empty = + { libraries = Rocq_lib_name.Map.empty + ; directories = Rocq_lib_name.Map.empty + ; extract = Loc.Map.empty + ; rev_map = Rocq_module.Map.empty + } +;; + +let rocq_modules_of_files ~dirs = + let filter_v_files + ({ Source_file_dir.dir = _; path_to_root = _; files; source_dir = _ } as sd) + = + { sd with files = String.Set.filter files ~f:(fun f -> Filename.check_suffix f ".v") } + in + let dirs = List.map dirs ~f:filter_v_files in + let build_mod_dir { Source_file_dir.dir; path_to_root = prefix; files; source_dir = _ } = + String.Set.to_list_map files ~f:(fun file -> + let name, _ = Filename.split_extension file in + let name = Rocq_module.Name.make name in + Rocq_module.make ~source:(Path.build @@ Path.Build.relative dir file) ~prefix ~name) + in + List.concat_map ~f:build_mod_dir dirs +;; + +let library t ~name = Rocq_lib_name.Map.find_exn t.libraries name +let directories t ~name = Rocq_lib_name.Map.find_exn t.directories name + +let check_no_unqualified (loc, (qualif_mode : Include_subdirs.t)) = + if qualif_mode = Include Unqualified + then + User_error.raise + ~loc + [ Pp.text + "(include_subdirs unqualified) is not supported yet with (rocq.theory ...) \ + stanzas" + ] +;; + +let extract t (stanza : Extraction.t) = Loc.Map.find_exn t.extract stanza.buildable.loc + +let of_dir stanzas ~dir ~include_subdirs ~dirs = + check_no_unqualified include_subdirs; + let modules = rocq_modules_of_files ~dirs in + List.fold_left stanzas ~init:empty ~f:(fun acc stanza -> + match Stanza.repr stanza with + | Theory.T rocq -> + let modules = Rocq_module.eval ~dir rocq.modules ~standard:modules in + let directories = + Rocq_lib_name.Map.add_exn + acc.directories + (snd rocq.name) + (List.map dirs ~f:(fun (d : Source_file_dir.t) -> d.dir)) + in + let libraries = Rocq_lib_name.Map.add_exn acc.libraries (snd rocq.name) modules in + let rev_map = + List.fold_left modules ~init:acc.rev_map ~f:(fun acc m -> + Rocq_module.Map.add acc m (`Theory rocq) + |> function + | Ok acc -> acc + | Error _ -> + User_error.raise + ~loc:rocq.buildable.loc + [ Pp.textf + "Duplicate Rocq module %S." + (Rocq_module.name m |> Rocq_module.Name.to_string) + ]) + in + { acc with directories; libraries; rev_map } + | Extraction.T extr -> + let loc, prelude = extr.prelude in + let m = + match + List.find modules ~f:(fun m -> + Rocq_module.Name.equal (Rocq_module.name m) prelude) + with + | Some m -> m + | None -> + User_error.raise + ~loc + [ Pp.text "no Rocq source corresponding to prelude field" ] + in + let extract = Loc.Map.add_exn acc.extract extr.buildable.loc m in + let rev_map = Rocq_module.Map.add_exn acc.rev_map m (`Extraction extr) in + { acc with extract; rev_map } + | _ -> acc) +;; + +let lookup_module t m = Rocq_module.Map.find t.rev_map m + +let mlg_files ~sctx ~dir ~modules = + let open Memo.O in + let+ standard = + (* All .mlg files in the current directory *) + let filter_mlg file = + if Path.Source.extension file = ".mlg" + then + Some + (Path.Build.append_source + (Super_context.context sctx |> Context.build_dir) + file) + else None + in + Source_tree.files_of (Path.Build.drop_build_context_exn dir) + >>| Path.Source.Set.to_list + >>| List.filter_map ~f:filter_mlg + in + let parse ~loc:_ file = Path.Build.relative dir (file ^ ".mlg") in + Ordered_set_lang.eval modules ~standard ~parse ~eq:Path.Build.equal +;; diff --git a/src/dune_rules/rocq/rocq_sources.mli b/src/dune_rules/rocq/rocq_sources.mli new file mode 100644 index 00000000000..f626abc4250 --- /dev/null +++ b/src/dune_rules/rocq/rocq_sources.mli @@ -0,0 +1,49 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +(** Handling of Rocq source files *) +open Import + +open Rocq_stanza + +type t + +val empty : t + +(** Rocq modules of library [name] is the Rocq library name. *) +val library : t -> name:Rocq_lib_name.t -> Rocq_module.t list + +val directories : t -> name:Rocq_lib_name.t -> Path.Build.t list +val extract : t -> Extraction.t -> Rocq_module.t + +val of_dir + : Stanza.t list + -> dir:Path.Build.t + -> include_subdirs:Loc.t * Include_subdirs.t + -> dirs:Source_file_dir.t list + -> t + +(** [find_module ~source t] finds a Rocq library name and module corresponding to + file [source], if there is one. *) +val find_module : source:Path.Build.t -> t -> (Rocq_lib_name.t * Rocq_module.t) option + +val lookup_module + : t + -> Rocq_module.t + -> [ `Theory of Theory.t | `Extraction of Extraction.t ] option + +val mlg_files + : sctx:Super_context.t + -> dir:Path.Build.t + -> modules:Ordered_set_lang.t + -> Path.Build.t list Memo.t diff --git a/src/dune_rules/rocq/rocq_stanza.ml b/src/dune_rules/rocq/rocq_stanza.ml new file mode 100644 index 00000000000..4fbeded729b --- /dev/null +++ b/src/dune_rules/rocq/rocq_stanza.ml @@ -0,0 +1,204 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import +open Dune_lang.Decoder + +let rocq_syntax = + Dune_lang.Syntax.create + ~name:"rocq" + ~desc:"Rocq Prover build language" + [ (0, 11), `Since (3, 21) ] +;; + +let get_rocq_syntax () = Dune_lang.Syntax.get_exn rocq_syntax + +module Rocqpp = struct + type t = + { modules : Ordered_set_lang.t + ; loc : Loc.t + } + + let decode = + fields + (let+ modules = Ordered_set_lang.field "modules" + and+ loc = loc in + { modules; loc }) + ;; + + include Stanza.Make (struct + type nonrec t = t + + include Poly + end) + + let p = "rocq.pp", decode_stanza decode +end + +module Buildable = struct + type t = + { flags : Ordered_set_lang.Unexpanded.t + ; rocq_lang_version : Dune_sexp.Syntax.Version.t + ; mode : Rocq_mode.t option + ; use_stdlib : bool + ; plugins : (Loc.t * Lib_name.t) list (** ocaml libraries *) + ; theories : (Loc.t * Rocq_lib_name.t) list (** rocq libraries *) + ; loc : Loc.t + } + + let decode = + let* rocq_lang_version = get_rocq_syntax () in + let+ loc = loc + and+ flags = Ordered_set_lang.Unexpanded.field "flags" + and+ mode = field_o "mode" Rocq_mode.decode + and+ use_stdlib = field ~default:true "stdlib" (enum [ "yes", true; "no", false ]) + and+ plugins = field "plugins" (repeat (located Lib_name.decode)) ~default:[] + and+ theories = field "theories" (repeat Rocq_lib_name.decode) ~default:[] in + { flags; mode; use_stdlib; rocq_lang_version; plugins; theories; loc } + ;; +end + +module Extraction = struct + type t = + { (* not a list of modules because we want to preserve whatever case Rocq + uses *) + extracted_modules : string list + ; prelude : Loc.t * Rocq_module.Name.t + ; buildable : Buildable.t + } + + let ml_target_fnames t = + List.concat_map t.extracted_modules ~f:(fun m -> [ m ^ ".ml"; m ^ ".mli" ]) + ;; + + let decode = + fields + (let+ extracted_modules = field "extracted_modules" (repeat string) + and+ prelude = field "prelude" (located (string >>| Rocq_module.Name.make)) + and+ buildable = Buildable.decode in + { prelude; extracted_modules; buildable }) + ;; + + include Stanza.Make (struct + type nonrec t = t + + include Poly + end) + + let p = "rocq.extraction", decode_stanza decode +end + +module Theory = struct + type t = + { name : Loc.t * Rocq_lib_name.t + ; package : Package.t option + ; project : Dune_project.t + ; synopsis : string option + ; modules : Ordered_set_lang.t + ; modules_flags : (Rocq_module.Name.t * Ordered_set_lang.Unexpanded.t) list option + ; boot : bool + ; generate_project_file : Loc.t * bool + ; enabled_if : Blang.t + ; buildable : Buildable.t + ; rocqdep_flags : Ordered_set_lang.Unexpanded.t + ; rocqdoc_flags : Ordered_set_lang.Unexpanded.t + ; rocqdoc_header : String_with_vars.t option + ; rocqdoc_footer : String_with_vars.t option + } + + let boot_has_deps loc = + User_error.raise ~loc [ Pp.textf "(boot) libraries cannot have dependencies" ] + ;; + + let check_boot_has_no_deps boot { Buildable.theories; _ } = + if boot + then ( + match theories with + | [] -> () + | (loc, _) :: _ -> boot_has_deps loc) + ;; + + let check_generate_project_file (loc, generate_project_file) modules_flags = + if generate_project_file + then ( + match modules_flags with + | None -> () + | Some _ -> + User_error.raise + ~loc + [ Pp.textf "(generate_project_file) is not compatible with (modules_flags ...)" + ]) + ;; + + module Per_file = struct + let decode_pair = + let+ mod_ = Rocq_module.Name.decode + and+ flags = Ordered_set_lang.Unexpanded.decode in + mod_, flags + ;; + + let decode = repeat (enter decode_pair) + end + + let decode = + fields + (let+ name = field "name" Rocq_lib_name.decode + and+ package = Stanza_pkg.field_opt () >>| Option.map ~f:snd + and+ project = Dune_project.get_exn () + and+ synopsis = field_o "synopsis" string + and+ boot = field_b "boot" ~check:(Dune_lang.Syntax.since rocq_syntax (0, 2)) + and+ generate_project_file = located @@ field_b "generate_project_file" + and+ modules = Ordered_set_lang.field "modules" + and+ modules_flags = field_o "modules_flags" Per_file.decode + and+ enabled_if = Enabled_if.decode ~allowed_vars:Any ~since:None () + and+ buildable = Buildable.decode + and+ rocqdep_flags = Ordered_set_lang.Unexpanded.field "rocqdep_flags" + and+ rocqdoc_flags = Ordered_set_lang.Unexpanded.field "rocqdoc_flags" + and+ rocqdoc_header = field_o "rocqdoc_header" String_with_vars.decode + and+ rocqdoc_footer = field_o "rocqdoc_footer" String_with_vars.decode in + (* boot libraries cannot depend on other theories *) + check_boot_has_no_deps boot buildable; + (* project files can only be generated when no per-module flags are configured. *) + check_generate_project_file generate_project_file modules_flags; + { name + ; package + ; project + ; synopsis + ; modules + ; modules_flags + ; boot + ; generate_project_file + ; buildable + ; enabled_if + ; rocqdep_flags + ; rocqdoc_flags + ; rocqdoc_header + ; rocqdoc_footer + }) + ;; + + include Stanza.Make (struct + type nonrec t = t + + include Poly + end) + + let p = "rocq.theory", decode_stanza decode +end + +let unit_stanzas = + let+ r = return [ Theory.p; Rocqpp.p; Extraction.p ] in + (), r +;; + +let key = Dune_project.Extension.register rocq_syntax unit_stanzas Unit.to_dyn diff --git a/src/dune_rules/rocq/rocq_stanza.mli b/src/dune_rules/rocq/rocq_stanza.mli new file mode 100644 index 00000000000..106c5498944 --- /dev/null +++ b/src/dune_rules/rocq/rocq_stanza.mli @@ -0,0 +1,70 @@ +(***********************************************) +(* This file is licensed under The MIT License *) +(* (c) MINES ParisTech 2018-2019 *) +(* (c) INRIA 2019-2024 *) +(* (c) Emilio J. Gallego Arias 2024-2025 *) +(* (c) CNRS 2025 *) +(***********************************************) +(* Written by: Ali Caglayan *) +(* Written by: Emilio Jesús Gallego Arias *) +(* Written by: Rudi Grinberg *) +(* Written by: Rodolphe Lepigre *) +(***********************************************) + +open Import + +module Buildable : sig + type t = + { flags : Ordered_set_lang.Unexpanded.t + ; rocq_lang_version : Dune_sexp.Syntax.Version.t + ; mode : Rocq_mode.t option + ; use_stdlib : bool + ; plugins : (Loc.t * Lib_name.t) list (** ocaml plugins *) + ; theories : (Loc.t * Rocq_lib_name.t) list (** rocq libraries *) + ; loc : Loc.t + } +end + +module Extraction : sig + type t = + { extracted_modules : string list + ; prelude : Loc.t * Rocq_module.Name.t + ; buildable : Buildable.t + } + + val ml_target_fnames : t -> string list + + include Stanza.S with type t := t +end + +module Theory : sig + type t = + { name : Loc.t * Rocq_lib_name.t + ; package : Package.t option + ; project : Dune_project.t + ; synopsis : string option + ; modules : Ordered_set_lang.t + ; modules_flags : (Rocq_module.Name.t * Ordered_set_lang.Unexpanded.t) list option + ; boot : bool + ; generate_project_file : Loc.t * bool + ; enabled_if : Blang.t + ; buildable : Buildable.t + ; rocqdep_flags : Ordered_set_lang.Unexpanded.t + ; rocqdoc_flags : Ordered_set_lang.Unexpanded.t + ; rocqdoc_header : String_with_vars.t option + ; rocqdoc_footer : String_with_vars.t option + } + + include Stanza.S with type t := t +end + +module Rocqpp : sig + type t = + { modules : Ordered_set_lang.t + ; loc : Loc.t + } + + include Stanza.S with type t := t +end + +val key : unit Dune_project.Extension.t diff --git a/src/dune_rules/scope.ml b/src/dune_rules/scope.ml index bdab91a86b3..df539aff66e 100644 --- a/src/dune_rules/scope.ml +++ b/src/dune_rules/scope.ml @@ -5,6 +5,7 @@ type t = { project : Dune_project.t ; db : Lib.DB.t ; coq_db : Coq_lib.DB.t Memo.t + ; rocq_db : Rocq_lib.DB.t Memo.t ; root : Path.Build.t } @@ -12,6 +13,7 @@ let root t = t.root let project t = t.project let libs t = t.db let coq_libs t = t.coq_db +let rocq_libs t = t.rocq_db module DB = struct type scope = t @@ -305,6 +307,7 @@ module DB = struct context stanzas coq_stanzas + rocq_stanzas = let stanzas_by_project_dir = List.map stanzas ~f:(fun (dir, stanza) -> @@ -334,13 +337,22 @@ module DB = struct let coq_scopes = Coq_scope.make context ~public_libs coq_stanzas ~db_by_project_dir ~projects_by_root in + let rocq_scopes = + Rocq_scope.make + context + ~public_libs + rocq_stanzas + ~db_by_project_dir + ~projects_by_root + in Path.Source.Map.mapi db_by_project_dir ~f:(fun dir (project, db) -> let root = Path.Build.append_source build_dir (Dune_project.root project) in let coq_db = Coq_scope.find coq_scopes ~dir in - { project; db; coq_db; root }) + let rocq_db = Rocq_scope.find rocq_scopes ~dir in + { project; db; coq_db; rocq_db; root }) ;; - let create ~context ~projects_by_root stanzas coq_stanzas = + let create ~context ~projects_by_root stanzas coq_stanzas rocq_stanzas = let t = Fdecl.create Dyn.opaque in let* context = Context.DB.get context in let build_dir = Context.build_dir context in @@ -363,6 +375,7 @@ module DB = struct context stanzas coq_stanzas + rocq_stanzas in let value = { by_dir } in Fdecl.set t value; @@ -370,28 +383,31 @@ module DB = struct ;; let create_from_stanzas ~projects_by_root ~(context : Context_name.t) stanzas = - let stanzas, coq_stanzas = + let stanzas, coq_stanzas, rocq_stanzas = let build_dir = Context_name.build_dir context in Dune_file.fold_static_stanzas stanzas - ~init:([], []) - ~f:(fun dune_file stanza (acc, coq_acc) -> + ~init:([], [], []) + ~f:(fun dune_file stanza (acc, coq_acc, rocq_acc) -> match Stanza.repr stanza with | Library.T lib -> let ctx_dir = Path.Build.append_source build_dir (Dune_file.dir dune_file) in - (ctx_dir, Library_related_stanza.Library lib) :: acc, coq_acc + (ctx_dir, Library_related_stanza.Library lib) :: acc, coq_acc, rocq_acc | Deprecated_library_name.T d -> let ctx_dir = Path.Build.append_source build_dir (Dune_file.dir dune_file) in - (ctx_dir, Deprecated_library_name d) :: acc, coq_acc + (ctx_dir, Deprecated_library_name d) :: acc, coq_acc, rocq_acc | Library_redirect.Local.T d -> let ctx_dir = Path.Build.append_source build_dir (Dune_file.dir dune_file) in - (ctx_dir, Library_redirect d) :: acc, coq_acc + (ctx_dir, Library_redirect d) :: acc, coq_acc, rocq_acc | Coq_stanza.Theory.T coq_lib -> let ctx_dir = Path.Build.append_source build_dir (Dune_file.dir dune_file) in - acc, (ctx_dir, coq_lib) :: coq_acc - | _ -> acc, coq_acc) + acc, (ctx_dir, coq_lib) :: coq_acc, rocq_acc + | Rocq_stanza.Theory.T rocq_lib -> + let ctx_dir = Path.Build.append_source build_dir (Dune_file.dir dune_file) in + acc, coq_acc, (ctx_dir, rocq_lib) :: rocq_acc + | _ -> acc, coq_acc, rocq_acc) in - create ~projects_by_root ~context stanzas coq_stanzas + create ~projects_by_root ~context stanzas coq_stanzas rocq_stanzas ;; let all = diff --git a/src/dune_rules/scope.mli b/src/dune_rules/scope.mli index bc985bfc39b..01402e0846a 100644 --- a/src/dune_rules/scope.mli +++ b/src/dune_rules/scope.mli @@ -12,8 +12,11 @@ val project : t -> Dune_project.t (** Return the library database associated to this scope *) val libs : t -> Lib.DB.t +(** Return the Rocq library database associated to this scope *) val coq_libs : t -> Coq_lib.DB.t Memo.t +val rocq_libs : t -> Rocq_lib.DB.t Memo.t + (** Scope databases *) module DB : sig val find_by_dir : Path.Build.t -> t Memo.t diff --git a/src/dune_rules/stanzas/stanzas.ml b/src/dune_rules/stanzas/stanzas.ml index 5957fe8bee2..1d7fb8587e7 100644 --- a/src/dune_rules/stanzas/stanzas.ml +++ b/src/dune_rules/stanzas/stanzas.ml @@ -99,7 +99,9 @@ let stanzas : Stanza.Parser.t list = @@ decode ~qualified: (let* project = Dune_project.get_exn () in - if Dune_project.is_extension_set project Coq_stanza.key + if + Dune_project.is_extension_set project Coq_stanza.key + || Dune_project.is_extension_set project Rocq_stanza.key then return () else Syntax.since Stanza.syntax (3, 7))) ) ; "toplevel", Toplevel_stanza.decode_stanza Toplevel_stanza.decode @@ -132,6 +134,7 @@ let stanza_package stanza = | Documentation.T { package; _ } | Tests.T { package = Some package; _ } -> Some package | Coq_stanza.Theory.T { package = Some package; _ } -> Some package + | Rocq_stanza.Theory.T { package = Some package; _ } -> Some package | _ -> None) |> Option.map ~f:Package.id with diff --git a/test/blackbox-tests/test-cases/pkg/portable-lockdirs/portable-lockdirs-platform-dependant-dependencies.t b/test/blackbox-tests/test-cases/pkg/portable-lockdirs/portable-lockdirs-platform-dependant-dependencies.t index be445efb5fe..8e43d20f614 100644 --- a/test/blackbox-tests/test-cases/pkg/portable-lockdirs/portable-lockdirs-platform-dependant-dependencies.t +++ b/test/blackbox-tests/test-cases/pkg/portable-lockdirs/portable-lockdirs-platform-dependant-dependencies.t @@ -74,13 +74,13 @@ A package that conditionally depends on packages depending on the OS: Build the project as if we were on linux and confirm that only the linux-specific dependency is installed: $ DUNE_CONFIG__OS=linux DUNE_CONFIG__ARCH=arm64 DUNE_CONFIG__OS_FAMILY=debian DUNE_CONFIG__OS_DISTRIBUTION=ubuntu DUNE_CONFIG__OS_VERSION=24.11 dune build $ ls $pkg_root/ - foo.0.0.1-9b0ae1f26c9a79e6ae8bca96ec389858 - linux-only.0.0.1-f1f7456a7bf1c70f9203f8caadf79f6d + foo.0.0.1-5e48eb7073ada94c09fb13ac3853f1e9 + linux-only.0.0.1-f754e8cf64f80c214f1a86ee403f0dc3 $ dune clean Build the project as if we were on macos and confirm that only the macos-specific dependency is installed: $ DUNE_CONFIG__OS=macos DUNE_CONFIG__ARCH=x86_64 DUNE_CONFIG__OS_FAMILY=homebrew DUNE_CONFIG__OS_DISTRIBUTION=homebrew DUNE_CONFIG__OS_VERSION=15.3.1 dune build $ ls $pkg_root/ - foo.0.0.1-dace34542257af51bf0bfc5cd45a7ece - macos-only.0.0.1-45b66a146d607b34b06be6c1cafeeb83 + foo.0.0.1-c8f5e41510b06a6875f85e9639e1a288 + macos-only.0.0.1-6fa10e046474f147e8ea1a1932a87966 diff --git a/test/blackbox-tests/test-cases/rocq-native/base-unsound.t/bar.v b/test/blackbox-tests/test-cases/rocq-native/base-unsound.t/bar.v new file mode 100644 index 00000000000..aaaf57b5190 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/base-unsound.t/bar.v @@ -0,0 +1,3 @@ +From basic Require Import foo. + +Definition false : t := t. diff --git a/test/blackbox-tests/test-cases/rocq-native/base-unsound.t/base.opam b/test/blackbox-tests/test-cases/rocq-native/base-unsound.t/base.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq-native/base-unsound.t/dune b/test/blackbox-tests/test-cases/rocq-native/base-unsound.t/dune new file mode 100644 index 00000000000..f11be27b12d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/base-unsound.t/dune @@ -0,0 +1,9 @@ +(rocq.theory + (name basic) + (package base) + (modules :standard) + (synopsis "Test Coq library")) + +(rule + (alias default) + (action (echo "%{read:base.install}"))) diff --git a/test/blackbox-tests/test-cases/rocq-native/base-unsound.t/dune-project b/test/blackbox-tests/test-cases/rocq-native/base-unsound.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/base-unsound.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/base-unsound.t/dune-workspace b/test/blackbox-tests/test-cases/rocq-native/base-unsound.t/dune-workspace new file mode 100644 index 00000000000..98a41b3f6f9 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/base-unsound.t/dune-workspace @@ -0,0 +1,2 @@ +(lang dune 3.21) +(env (unsound (rocq (flags -type-in-type)))) diff --git a/test/blackbox-tests/test-cases/rocq-native/base-unsound.t/foo.v b/test/blackbox-tests/test-cases/rocq-native/base-unsound.t/foo.v new file mode 100644 index 00000000000..fea01705199 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/base-unsound.t/foo.v @@ -0,0 +1 @@ +Definition t := Type. \ No newline at end of file diff --git a/test/blackbox-tests/test-cases/rocq-native/base-unsound.t/run.t b/test/blackbox-tests/test-cases/rocq-native/base-unsound.t/run.t new file mode 100644 index 00000000000..36c9244e0c1 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/base-unsound.t/run.t @@ -0,0 +1,4 @@ + $ dune build --display short --profile unsound --debug-dependency-path @all + rocq .basic.theory.d + rocq Nbasic_foo.{cmi,cmxs},foo.{glob,vo} + rocq Nbasic_bar.{cmi,cmxs},bar.{glob,vo} diff --git a/test/blackbox-tests/test-cases/rocq-native/base.t/bar.v b/test/blackbox-tests/test-cases/rocq-native/base.t/bar.v new file mode 100644 index 00000000000..4627b76131c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/base.t/bar.v @@ -0,0 +1,3 @@ +From basic Require Import foo. + +Definition mynum (i : mynat) := 3. diff --git a/test/blackbox-tests/test-cases/rocq-native/base.t/base.opam b/test/blackbox-tests/test-cases/rocq-native/base.t/base.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq-native/base.t/dune b/test/blackbox-tests/test-cases/rocq-native/base.t/dune new file mode 100644 index 00000000000..f11be27b12d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/base.t/dune @@ -0,0 +1,9 @@ +(rocq.theory + (name basic) + (package base) + (modules :standard) + (synopsis "Test Coq library")) + +(rule + (alias default) + (action (echo "%{read:base.install}"))) diff --git a/test/blackbox-tests/test-cases/rocq-native/base.t/dune-project b/test/blackbox-tests/test-cases/rocq-native/base.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/base.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/base.t/foo.v b/test/blackbox-tests/test-cases/rocq-native/base.t/foo.v new file mode 100644 index 00000000000..53e0ce1b152 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/base.t/foo.v @@ -0,0 +1 @@ +Definition mynat := nat. diff --git a/test/blackbox-tests/test-cases/rocq-native/base.t/run.t b/test/blackbox-tests/test-cases/rocq-native/base.t/run.t new file mode 100644 index 00000000000..0f4ca56a3c7 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/base.t/run.t @@ -0,0 +1,23 @@ + $ dune build --display short --debug-dependency-path @all --always-show-command-line + rocq .basic.theory.d + rocq Nbasic_foo.{cmi,cmxs},foo.{glob,vo} + rocq Nbasic_bar.{cmi,cmxs},bar.{glob,vo} + + $ dune build --debug-dependency-path @default + lib: [ + "_build/install/default/lib/base/META" + "_build/install/default/lib/base/dune-package" + "_build/install/default/lib/base/opam" + ] + lib_root: [ + "_build/install/default/lib/coq/user-contrib/basic/.coq-native/Nbasic_bar.cmi" {"coq/user-contrib/basic/.coq-native/Nbasic_bar.cmi"} + "_build/install/default/lib/coq/user-contrib/basic/.coq-native/Nbasic_bar.cmxs" {"coq/user-contrib/basic/.coq-native/Nbasic_bar.cmxs"} + "_build/install/default/lib/coq/user-contrib/basic/.coq-native/Nbasic_foo.cmi" {"coq/user-contrib/basic/.coq-native/Nbasic_foo.cmi"} + "_build/install/default/lib/coq/user-contrib/basic/.coq-native/Nbasic_foo.cmxs" {"coq/user-contrib/basic/.coq-native/Nbasic_foo.cmxs"} + "_build/install/default/lib/coq/user-contrib/basic/bar.glob" {"coq/user-contrib/basic/bar.glob"} + "_build/install/default/lib/coq/user-contrib/basic/bar.v" {"coq/user-contrib/basic/bar.v"} + "_build/install/default/lib/coq/user-contrib/basic/bar.vo" {"coq/user-contrib/basic/bar.vo"} + "_build/install/default/lib/coq/user-contrib/basic/foo.glob" {"coq/user-contrib/basic/foo.glob"} + "_build/install/default/lib/coq/user-contrib/basic/foo.v" {"coq/user-contrib/basic/foo.v"} + "_build/install/default/lib/coq/user-contrib/basic/foo.vo" {"coq/user-contrib/basic/foo.vo"} + ] diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/Coq/coq-boot.opam b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/Coq/coq-boot.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/Coq/dune-project b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/Coq/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/Coq/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/Coq/plugins/boot_plugin.mlpack b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/Coq/plugins/boot_plugin.mlpack new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/Coq/plugins/dune b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/Coq/plugins/dune new file mode 100644 index 00000000000..c9a2d0618ba --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/Coq/plugins/dune @@ -0,0 +1,4 @@ +(library + (name boot_plugin) + (public_name coq-boot.boot_plugin)) + diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/Coq/plugins/main.ml b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/Coq/plugins/main.ml new file mode 100644 index 00000000000..752bae9ceed --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/Coq/plugins/main.ml @@ -0,0 +1 @@ +let () = Format.eprintf "plugin loaded@\n%!" diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/Coq/theories/Init/Prelude.v b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/Coq/theories/Init/Prelude.v new file mode 100644 index 00000000000..0ac0180df80 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/Coq/theories/Init/Prelude.v @@ -0,0 +1,2 @@ +Declare ML Module "coq-boot.boot_plugin". +Inductive AnotherBeginning := Of | The | Universe. diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/Coq/theories/dune b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/Coq/theories/dune new file mode 100644 index 00000000000..7c58337a68a --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/Coq/theories/dune @@ -0,0 +1,7 @@ +(rocq.theory + (name Coq) + (boot) + (package coq-boot) + (plugins coq-boot.boot_plugin)) + +(include_subdirs qualified) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/User/coq-user.opam b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/User/coq-user.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/User/dune b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/User/dune new file mode 100644 index 00000000000..417d6e9428f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/User/dune @@ -0,0 +1,5 @@ +(rocq.theory + (name User) + (package coq-user)) + + diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/User/dune-project b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/User/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/User/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/User/user.v b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/User/user.v new file mode 100644 index 00000000000..7ae6d680982 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/User/user.v @@ -0,0 +1 @@ +Definition from_boot : AnotherBeginning := Universe. diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/dune-workspace b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/dune-workspace new file mode 100644 index 00000000000..e1b8e598780 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/dune-workspace @@ -0,0 +1 @@ +(lang dune 3.21) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/run.t b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/run.t new file mode 100644 index 00000000000..57e0db989ba --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-boot-plugins.t/run.t @@ -0,0 +1,14 @@ +Testing composition with a boot library with plugins + + $ dune build + plugin loaded + File "Coq/theories/dune", lines 1-5, characters 0-85: + 1 | (rocq.theory + 2 | (name Coq) + 3 | (boot) + 4 | (package coq-boot) + 5 | (plugins coq-boot.boot_plugin)) + Error: Rule failed to generate the following targets: + - Coq/theories/Init/NCoq_Init_Prelude.cmi + - Coq/theories/Init/NCoq_Init_Prelude.cmxs + [1] diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-compat.t/A/a.v b/test/blackbox-tests/test-cases/rocq-native/compose-installed-compat.t/A/a.v new file mode 100644 index 00000000000..ebcb8bf8f39 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-compat.t/A/a.v @@ -0,0 +1,2 @@ +From B Require Import b. +Print hello. diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-compat.t/A/dune b/test/blackbox-tests/test-cases/rocq-native/compose-installed-compat.t/A/dune new file mode 100644 index 00000000000..52a9f05b182 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-compat.t/A/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name A) + (theories Corelib B)) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-compat.t/A/dune-project b/test/blackbox-tests/test-cases/rocq-native/compose-installed-compat.t/A/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-compat.t/A/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-compat.t/B/b.v b/test/blackbox-tests/test-cases/rocq-native/compose-installed-compat.t/B/b.v new file mode 100644 index 00000000000..858e4927197 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-compat.t/B/b.v @@ -0,0 +1 @@ +Inductive hello := I | am | an | install | loc. \ No newline at end of file diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-compat.t/B/dune b/test/blackbox-tests/test-cases/rocq-native/compose-installed-compat.t/B/dune new file mode 100644 index 00000000000..904c3119b45 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-compat.t/B/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name B) + (package B) + (theories Corelib)) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-compat.t/B/dune-project b/test/blackbox-tests/test-cases/rocq-native/compose-installed-compat.t/B/dune-project new file mode 100644 index 00000000000..1145d420f9a --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-compat.t/B/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) +(using rocq 0.11) +(package (name "B")) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-compat.t/run.t b/test/blackbox-tests/test-cases/rocq-native/compose-installed-compat.t/run.t new file mode 100644 index 00000000000..f9f97592b1e --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-compat.t/run.t @@ -0,0 +1,69 @@ +We make sure that Coq lang versions < 0.8 can still somewhat compose with +installed theories. The way this was done before was due to `-boot` not being +passed to Coq. This meant that we essentially have `-Q "" user-contrib` being +passed. In order to restore this behaviour for Coq lang < 0.8 we explicitly add +that flag. This PR makes sure that this is indeed the case. + +We configure ROCQLIB to be lib/coq. Coq will search for user-contrib from here. +We also need to set up a fake Coq install. + + $ mkdir -p lib/coq + $ export ROCQLIB=$PWD/lib/coq + $ echo $ROCQLIB + $TESTCASE_ROOT/lib/coq + + $ mkdir -p lib/coq/theories/Init/ + $ cat > lib/coq/theories/Init/Prelude.v << EOF + > Inductive PreludeLoaded := Yes. + > EOF + +We need to manually compile the prelude. + + $ rocq compile -boot -noinit -w -deprecated-native-compiler-option -w -native-compiler-disabled -native-compiler no -R lib/coq/theories/ Corelib lib/coq/theories/Init/Prelude.v + +We also setup some plugins + + $ mkdir -p lib/rocq-runtime/plugins + +We setup an installed theory. Note that lib/coq/user-contrib doesn't exist yet, +so this also tests that it won't be a problem. + + $ dune build --root B @install + Entering directory 'B' + Leaving directory 'B' + $ dune install --root B --prefix=$PWD --display=short + Installing $TESTCASE_ROOT/lib/B/META + Installing $TESTCASE_ROOT/lib/B/dune-package + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/.coq-native/NB_b.cmi + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/.coq-native/NB_b.cmxs + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.glob + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.v + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.vo + + +Next we go into our Dune project and build it. + $ dune build --root A + Entering directory 'A' + Inductive hello : Set := + I : hello | am : hello | an : hello | install : hello | loc : hello. + Leaving directory 'A' + +Now we check the flags that were passed to coqdep and coqc: + + $ tail -4 A/_build/log | head -2 | ../scrub_coq_args.sh + rocq dep + -boot + -R coq/theories Corelib + -Q $TESTCASE_ROOT/lib/coq/user-contrib/B B + -R . A -dyndep opt -vos a.v > + _build/default/.A.theory.d + rocq compile -q + -w -deprecated-native-compiler-option -native-output-dir . + -native-compiler on + -nI lib/rocq-runtime/kernel + -nI . + -boot + -R coq/theories Corelib + -Q $TESTCASE_ROOT/lib/coq/user-contrib/B B + -R . A + a.v diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-rebuild.t/A/a.v b/test/blackbox-tests/test-cases/rocq-native/compose-installed-rebuild.t/A/a.v new file mode 100644 index 00000000000..ebcb8bf8f39 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-rebuild.t/A/a.v @@ -0,0 +1,2 @@ +From B Require Import b. +Print hello. diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-rebuild.t/A/dune b/test/blackbox-tests/test-cases/rocq-native/compose-installed-rebuild.t/A/dune new file mode 100644 index 00000000000..52a9f05b182 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-rebuild.t/A/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name A) + (theories Corelib B)) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-rebuild.t/A/dune-project b/test/blackbox-tests/test-cases/rocq-native/compose-installed-rebuild.t/A/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-rebuild.t/A/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-rebuild.t/B/dune b/test/blackbox-tests/test-cases/rocq-native/compose-installed-rebuild.t/B/dune new file mode 100644 index 00000000000..904c3119b45 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-rebuild.t/B/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name B) + (package B) + (theories Corelib)) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-rebuild.t/B/dune-project b/test/blackbox-tests/test-cases/rocq-native/compose-installed-rebuild.t/B/dune-project new file mode 100644 index 00000000000..1145d420f9a --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-rebuild.t/B/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) +(using rocq 0.11) +(package (name "B")) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-rebuild.t/run.t b/test/blackbox-tests/test-cases/rocq-native/compose-installed-rebuild.t/run.t new file mode 100644 index 00000000000..5a44d35d33f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-rebuild.t/run.t @@ -0,0 +1,121 @@ +We test that installed Coq theories, when updated, prompt Dune to rebuild + + $ mkdir -p lib/coq + $ export ROCQLIB=$PWD/lib/coq + $ echo $ROCQLIB + $TESTCASE_ROOT/lib/coq + + $ mkdir -p lib/coq/theories/Init/ + $ cat > lib/coq/theories/Init/Prelude.v << EOF + > Inductive PreludeLoaded := Yes. + > EOF + +We need to manually compile the prelude. + + $ rocq compile -boot -noinit -w -deprecated-native-compiler-option -w -native-compiler-disabled -native-compiler no -R lib/coq/theories/ Corelib lib/coq/theories/Init/Prelude.v + +We also setup some plugins + + $ mkdir -p lib/rocq-runtime/plugins + +We setup an installed theory. Note that lib/coq/user-contrib doesn't exist yet, +so this also tests that it won't be a problem. + + $ cat > B/b.v << EOF + > Inductive hello := I | am | an | install | loc. + > EOF + + $ dune build --root B @install + Entering directory 'B' + Leaving directory 'B' + $ dune install --root B --prefix=$PWD --display=short + Installing $TESTCASE_ROOT/lib/B/META + Installing $TESTCASE_ROOT/lib/B/dune-package + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/.coq-native/NB_b.cmi + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/.coq-native/NB_b.cmxs + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.glob + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.v + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.vo + + +Next we go into our Dune project and build it. + $ dune build --root A + Entering directory 'A' + Inductive hello : Set := + I : hello | am : hello | an : hello | install : hello | loc : hello. + Leaving directory 'A' + +Next we update B and install it again. + + $ cat > B/b.v << EOF + > Inductive hello := I | am | an | install | loc | but | updated. + > EOF + + $ dune build --root B @install + Entering directory 'B' + Leaving directory 'B' + $ dune install --root B --prefix=$PWD --display=short + Deleting $TESTCASE_ROOT/lib/B/META + Installing $TESTCASE_ROOT/lib/B/META + Deleting $TESTCASE_ROOT/lib/B/dune-package + Installing $TESTCASE_ROOT/lib/B/dune-package + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/.coq-native/NB_b.cmi + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/.coq-native/NB_b.cmi + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/.coq-native/NB_b.cmxs + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/.coq-native/NB_b.cmxs + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/b.glob + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.glob + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/b.v + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.v + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/b.vo + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.vo + +Now we should see that A is rebuilt + + $ dune build --root A + Entering directory 'A' + Inductive hello : Set := + I : hello + | am : hello + | an : hello + | install : hello + | loc : hello + | but : hello + | updated : hello. + Leaving directory 'A' + +Next we add a new file to B that should cause a call to coqdep, but no rebuild. + + $ cat > B/c.v << EOF + > Inductive bye := I | am | a | new | install | loc. + > EOF + + $ dune build --root B @install + Entering directory 'B' + Leaving directory 'B' + $ dune install --root B --prefix=$PWD --display=short + Deleting $TESTCASE_ROOT/lib/B/META + Installing $TESTCASE_ROOT/lib/B/META + Deleting $TESTCASE_ROOT/lib/B/dune-package + Installing $TESTCASE_ROOT/lib/B/dune-package + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/.coq-native/NB_b.cmi + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/.coq-native/NB_b.cmi + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/.coq-native/NB_b.cmxs + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/.coq-native/NB_b.cmxs + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/.coq-native/NB_c.cmi + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/.coq-native/NB_c.cmxs + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/b.glob + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.glob + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/b.v + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.v + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/b.vo + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.vo + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/c.glob + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/c.v + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/c.vo + +Now we should see that A is not rebuilt, however coqdep is called, this seems to fail + + $ dune build --root A --display=short + Entering directory 'A' + Leaving directory 'A' diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-stdlib.t/dune-project b/test/blackbox-tests/test-cases/rocq-native/compose-installed-stdlib.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-stdlib.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-stdlib.t/run.t b/test/blackbox-tests/test-cases/rocq-native/compose-installed-stdlib.t/run.t new file mode 100644 index 00000000000..d8b83c3d441 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-stdlib.t/run.t @@ -0,0 +1,11 @@ +Testing the composition of the installed stdlib + + $ cat > dune << EOF + > (rocq.theory + > (name test) + > (theories Corelib)) + > EOF + + $ dune build test.vo --display=short --always-show-command-line + rocq .test.theory.d + rocq Ntest_test.{cmi,cmxs},test.{glob,vo} diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-stdlib.t/test.v b/test/blackbox-tests/test-cases/rocq-native/compose-installed-stdlib.t/test.v new file mode 100644 index 00000000000..a8d287ba538 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-stdlib.t/test.v @@ -0,0 +1 @@ +From Corelib Require Import Classes.Init. diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/global/algebra/b_alg.v b/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/global/algebra/b_alg.v new file mode 100644 index 00000000000..ca9bc124d7d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/global/algebra/b_alg.v @@ -0,0 +1 @@ +Inductive hello_alg := I | am | an | install | loc | at_alg. diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/global/algebra/dune b/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/global/algebra/dune new file mode 100644 index 00000000000..65e6a102e73 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/global/algebra/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name global.algebra) + (package global)) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/global/dune-project b/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/global/dune-project new file mode 100644 index 00000000000..1693895f8bb --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/global/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) +(using rocq 0.11) +(package (name "global")) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/global/field/b_field.v b/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/global/field/b_field.v new file mode 100644 index 00000000000..2e219771088 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/global/field/b_field.v @@ -0,0 +1 @@ +Inductive hello_field := I | am | an | install | loc | at_field. diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/global/field/dune b/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/global/field/dune new file mode 100644 index 00000000000..e4d81b8048c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/global/field/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name global.field) + (package global)) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/run.t b/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/run.t new file mode 100644 index 00000000000..5238b91f322 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/run.t @@ -0,0 +1,215 @@ +We test composing a project with an installed Coq theory. The installed theory +does *not* have to be a dune project. But for the purpose of this test, we use +the installation of a Dune project. + +We configure ROCQLIB to be lib/coq. Coq will search for user-contrib from here. +We also need to set up a fake Coq install. + + $ mkdir -p lib/coq + $ export ROCQLIB=$PWD/lib/coq + $ echo $ROCQLIB + $TESTCASE_ROOT/lib/coq + + $ mkdir -p lib/coq/theories/Init/ + $ cat > lib/coq/theories/Init/Prelude.v << EOF + > Inductive PreludeLoaded := Yes. + > EOF + +We need to manually compile the prelude. + + $ rocq compile -boot -noinit -w -deprecated-native-compiler-option -w -native-compiler-disabled -native-compiler no -R lib/coq/theories/ Corelib lib/coq/theories/Init/Prelude.v + +We also setup some plugins + + $ mkdir -p lib/rocq-runtime/plugins + +Setting up a subdirectory theory: + + $ cat > user/dune << EOF + > (rocq.theory + > (name user) + > (theories global.field global.algebra)) + > EOF + +We setup an installed theory. Note that lib/coq/user-contrib doesn't exist yet, +so this also tests that it won't be a problem. + + $ dune build --root global @install + Entering directory 'global' + Leaving directory 'global' + $ dune install --root global --prefix=$PWD --display=short + Installing $TESTCASE_ROOT/lib/global/META + Installing $TESTCASE_ROOT/lib/global/dune-package + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/.coq-native/Nglobal_algebra_b_alg.cmi + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/.coq-native/Nglobal_algebra_b_alg.cmxs + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/b_alg.glob + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/b_alg.v + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/b_alg.vo + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/field/.coq-native/Nglobal_field_b_field.cmi + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/field/.coq-native/Nglobal_field_b_field.cmxs + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/field/b_field.glob + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/field/b_field.v + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/field/b_field.vo + + +Next we go into our Dune project and build it. + $ dune build --root user + Entering directory 'user' + Inductive hello_alg : Set := + I : hello_alg + | am : hello_alg + | an : hello_alg + | install : hello_alg + | loc : hello_alg + | at_alg : hello_alg. + Inductive hello_field : Set := + I : hello_field + | am : hello_field + | an : hello_field + | install : hello_field + | loc : hello_field + | at_field : hello_field. + Leaving directory 'user' + +Next we uninstall B from the standard location, user-contrib, and install it +somewhere else. + $ dune uninstall --root global --prefix=$PWD --display=short + Deleting $TESTCASE_ROOT/lib/global/META + Deleting $TESTCASE_ROOT/lib/global/dune-package + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/.coq-native/Nglobal_algebra_b_alg.cmi + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/.coq-native/Nglobal_algebra_b_alg.cmxs + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/b_alg.glob + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/b_alg.v + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/b_alg.vo + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/global/field/.coq-native/Nglobal_field_b_field.cmi + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/global/field/.coq-native/Nglobal_field_b_field.cmxs + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/global/field/b_field.glob + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/global/field/b_field.v + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/global/field/b_field.vo + Deleting empty directory $TESTCASE_ROOT/lib/global + Deleting empty directory $TESTCASE_ROOT/lib/coq/user-contrib/global/field/.coq-native + Deleting empty directory $TESTCASE_ROOT/lib/coq/user-contrib/global/field + Deleting empty directory $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/.coq-native + Deleting empty directory $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra + + $ dune install --root global --prefix=$PWD/another-place --display=short + Installing $TESTCASE_ROOT/another-place/lib/global/META + Installing $TESTCASE_ROOT/another-place/lib/global/dune-package + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/global/algebra/.coq-native/Nglobal_algebra_b_alg.cmi + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/global/algebra/.coq-native/Nglobal_algebra_b_alg.cmxs + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/global/algebra/b_alg.glob + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/global/algebra/b_alg.v + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/global/algebra/b_alg.vo + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/global/field/.coq-native/Nglobal_field_b_field.cmi + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/global/field/.coq-native/Nglobal_field_b_field.cmxs + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/global/field/b_field.glob + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/global/field/b_field.v + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/global/field/b_field.vo + $ rmdir lib/coq/user-contrib/global + +As expected, Dune can no longer build A: + + $ dune build --root user + Entering directory 'user' + File "dune", line 3, characters 11-23: + 3 | (theories global.field global.algebra)) + ^^^^^^^^^^^^ + Theory "global.field" has not been found. + -> required by theory user in dune:2 + -> required by _build/default/.user.theory.d + -> required by alias all + -> required by alias default + Leaving directory 'user' + [1] + +We therefore set a variable called ROCQPATH which allows for library install +locations alternative to user-contrib. + + $ export ROCQPATH=$PWD/another-place/lib/coq/user-contrib + +Now Dune should be able to build `user` again, since we scan both user-contrib and +all the directories found in ROCQPATH. + + $ dune build --root user + Entering directory 'user' + Inductive hello_alg : Set := + I : hello_alg + | am : hello_alg + | an : hello_alg + | install : hello_alg + | loc : hello_alg + | at_alg : hello_alg. + Inductive hello_field : Set := + I : hello_field + | am : hello_field + | an : hello_field + | install : hello_field + | loc : hello_field + | at_field : hello_field. + Leaving directory 'user' + +We test if having global in the workspace and in user-contrib will cause Dune +any problems. It shouldn't do, as the workspace should take precedence. + + $ dune build user + Inductive hello_alg : Set := + I : hello_alg + | am : hello_alg + | an : hello_alg + | install : hello_alg + | loc : hello_alg + | at_alg : hello_alg. + Inductive hello_field : Set := + I : hello_field + | am : hello_field + | an : hello_field + | install : hello_field + | loc : hello_field + | at_field : hello_field. + +We test updating the dune file for user to use the super-theory works: + + $ cat > user/dune << EOF + > (rocq.theory + > (name user) + > (theories global)) + > EOF + $ dune build --root user + Entering directory 'user' + Inductive hello_alg : Set := + I : hello_alg + | am : hello_alg + | an : hello_alg + | install : hello_alg + | loc : hello_alg + | at_alg : hello_alg. + Inductive hello_field : Set := + I : hello_field + | am : hello_field + | an : hello_field + | install : hello_field + | loc : hello_field + | at_field : hello_field. + Leaving directory 'user' + +We test whether installing `global` again in user-contrib will cause Dune to reject the +build. Currently this is not the case and the first theory is preferred inline +with the loadpath semantics of Coq. + + $ dune install --root global --prefix=$PWD --display=short + Installing $TESTCASE_ROOT/lib/global/META + Installing $TESTCASE_ROOT/lib/global/dune-package + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/.coq-native/Nglobal_algebra_b_alg.cmi + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/.coq-native/Nglobal_algebra_b_alg.cmxs + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/b_alg.glob + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/b_alg.v + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/b_alg.vo + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/field/.coq-native/Nglobal_field_b_field.cmi + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/field/.coq-native/Nglobal_field_b_field.cmxs + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/field/b_field.glob + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/field/b_field.v + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/field/b_field.vo + + $ dune build --root user + Entering directory 'user' + Leaving directory 'user' diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/user/a.v b/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/user/a.v new file mode 100644 index 00000000000..50d248ca6d3 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/user/a.v @@ -0,0 +1,3 @@ +From global Require Import b_alg b_field. +Print hello_alg. +Print hello_field. diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/user/dune-project b/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/user/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed-sub.t/user/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed.t/A/a.v b/test/blackbox-tests/test-cases/rocq-native/compose-installed.t/A/a.v new file mode 100644 index 00000000000..ebcb8bf8f39 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed.t/A/a.v @@ -0,0 +1,2 @@ +From B Require Import b. +Print hello. diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed.t/A/dune b/test/blackbox-tests/test-cases/rocq-native/compose-installed.t/A/dune new file mode 100644 index 00000000000..52a9f05b182 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed.t/A/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name A) + (theories Corelib B)) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed.t/A/dune-project b/test/blackbox-tests/test-cases/rocq-native/compose-installed.t/A/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed.t/A/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed.t/B/b.v b/test/blackbox-tests/test-cases/rocq-native/compose-installed.t/B/b.v new file mode 100644 index 00000000000..858e4927197 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed.t/B/b.v @@ -0,0 +1 @@ +Inductive hello := I | am | an | install | loc. \ No newline at end of file diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed.t/B/dune b/test/blackbox-tests/test-cases/rocq-native/compose-installed.t/B/dune new file mode 100644 index 00000000000..904c3119b45 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed.t/B/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name B) + (package B) + (theories Corelib)) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed.t/B/dune-project b/test/blackbox-tests/test-cases/rocq-native/compose-installed.t/B/dune-project new file mode 100644 index 00000000000..1145d420f9a --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed.t/B/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) +(using rocq 0.11) +(package (name "B")) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-installed.t/run.t b/test/blackbox-tests/test-cases/rocq-native/compose-installed.t/run.t new file mode 100644 index 00000000000..807cb911e23 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-installed.t/run.t @@ -0,0 +1,123 @@ +We test composing a project with an installed Coq theory. The installed theory +does *not* have to be a dune project. But for the purpose of this test, we use +the installation of a Dune project. + +We configure ROCQLIB to be lib/coq. Coq will search for user-contrib from here. +We also need to set up a fake Coq install. + + $ mkdir -p lib/coq + $ export ROCQLIB=$PWD/lib/coq + $ echo $ROCQLIB + $TESTCASE_ROOT/lib/coq + + $ mkdir -p lib/coq/theories/Init/ + $ cat > lib/coq/theories/Init/Prelude.v << EOF + > Inductive PreludeLoaded := Yes. + > EOF + +We need to manually compile the prelude. + + $ rocq compile -boot -noinit -w -deprecated-native-compiler-option -w -native-compiler-disabled -native-compiler no -R lib/coq/theories/ Corelib lib/coq/theories/Init/Prelude.v + +We also setup some plugins + + $ mkdir -p lib/rocq-runtime/plugins + +We setup an installed theory. Note that lib/coq/user-contrib doesn't exist yet, +so this also tests that it won't be a problem. + + $ dune build --root B @install + Entering directory 'B' + Leaving directory 'B' + $ dune install --root B --prefix=$PWD --display=short + Installing $TESTCASE_ROOT/lib/B/META + Installing $TESTCASE_ROOT/lib/B/dune-package + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/.coq-native/NB_b.cmi + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/.coq-native/NB_b.cmxs + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.glob + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.v + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.vo + + +Next we go into our Dune project and build it. + $ dune build --root A + Entering directory 'A' + Inductive hello : Set := + I : hello | am : hello | an : hello | install : hello | loc : hello. + Leaving directory 'A' + +Next we uninstall B from the standard location, user-contrib, and install it +somewhere else. + $ dune uninstall --root B --prefix=$PWD --display=short + Deleting $TESTCASE_ROOT/lib/B/META + Deleting $TESTCASE_ROOT/lib/B/dune-package + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/.coq-native/NB_b.cmi + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/.coq-native/NB_b.cmxs + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/b.glob + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/b.v + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/b.vo + Deleting empty directory $TESTCASE_ROOT/lib/coq/user-contrib/B/.coq-native + Deleting empty directory $TESTCASE_ROOT/lib/coq/user-contrib/B + Deleting empty directory $TESTCASE_ROOT/lib/B + + $ dune install --root B --prefix=$PWD/another-place --display=short + Installing $TESTCASE_ROOT/another-place/lib/B/META + Installing $TESTCASE_ROOT/another-place/lib/B/dune-package + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/B/.coq-native/NB_b.cmi + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/B/.coq-native/NB_b.cmxs + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/B/b.glob + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/B/b.v + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/B/b.vo + +As expected, Dune can no longer build A: + + $ dune build --root A + Entering directory 'A' + File "dune", line 3, characters 19-20: + 3 | (theories Corelib B)) + ^ + Theory "B" has not been found. + -> required by theory A in dune:2 + -> required by _build/default/.A.theory.d + -> required by alias all + -> required by alias default + Leaving directory 'A' + [1] + +We therefore set a variable called ROCQPATH which allows for library install +locations alternative to user-contrib. + + $ export ROCQPATH=$PWD/another-place/lib/coq/user-contrib + +Now Dune should be able to build A again, since we scan both user-contrib and +all the directories found in ROCQPATH. + + $ dune build --root A + Entering directory 'A' + Inductive hello : Set := + I : hello | am : hello | an : hello | install : hello | loc : hello. + Leaving directory 'A' + +We test if having B in the workspace and in user-contrib will cause Dune +any problems. It shouldn't do, as the workspace should take precedence. + + $ dune build A + Inductive hello : Set := + I : hello | am : hello | an : hello | install : hello | loc : hello. + +We test whether installing B again in user-contrib will cause Dune to reject the +build. Currently this is not the case and the first theory is preferred inline +with the loadpath semantics of Coq. + + $ dune install --root B --prefix=$PWD --display=short + Installing $TESTCASE_ROOT/lib/B/META + Installing $TESTCASE_ROOT/lib/B/dune-package + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/.coq-native/NB_b.cmi + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/.coq-native/NB_b.cmxs + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.glob + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.v + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.vo + + $ dune build --root A + Entering directory 'A' + Leaving directory 'A' diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/A/a.v b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/A/a.v new file mode 100644 index 00000000000..953a3b7b657 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/A/a.v @@ -0,0 +1,9 @@ + + +Print Prelude. + +Require Import mytheory. + +Check Hello. + + diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/A/dune b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/A/dune new file mode 100644 index 00000000000..0b2080e1dcb --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/A/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name A) + (theories Coq)) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/A/dune-project b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/A/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/A/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/B/Coq/Init/Prelude.v b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/B/Coq/Init/Prelude.v new file mode 100644 index 00000000000..e6778dee030 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/B/Coq/Init/Prelude.v @@ -0,0 +1,2 @@ +Unset Elimination Schemes. +Inductive PrivateBootType := private_boot | private_type. diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/B/Foo.opam b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/B/Foo.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/B/Stuff/b.v b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/B/Stuff/b.v new file mode 100644 index 00000000000..8a23f1a1419 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/B/Stuff/b.v @@ -0,0 +1 @@ +Check private_boot. diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/B/Stuff/dune b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/B/Stuff/dune new file mode 100644 index 00000000000..aae43938a8b --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/B/Stuff/dune @@ -0,0 +1,3 @@ + (rocq.theory + (name B) + (modules b)) \ No newline at end of file diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/B/dune-project b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/B/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/B/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/Coq/Coq.opam b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/Coq/Coq.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/Coq/Init/Prelude.v b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/Coq/Init/Prelude.v new file mode 100644 index 00000000000..9de480a5ab8 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/Coq/Init/Prelude.v @@ -0,0 +1,2 @@ +Unset Elimination Schemes. +Inductive BootType := boot | type. diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/Coq/dune b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/Coq/dune new file mode 100644 index 00000000000..1bc6d233edc --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/Coq/dune @@ -0,0 +1,6 @@ +(rocq.theory + (name Coq) + (package Coq) + (boot)) + +(include_subdirs qualified) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/Coq/dune-project b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/Coq/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/Coq/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/Coq/mytheory.v b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/Coq/mytheory.v new file mode 100644 index 00000000000..831752c569d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/Coq/mytheory.v @@ -0,0 +1,2 @@ + +Inductive Hello := World | Bye. diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/dune-workspace b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/dune-workspace new file mode 100644 index 00000000000..e1b8e598780 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/dune-workspace @@ -0,0 +1 @@ +(lang dune 3.21) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/run.t b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/run.t new file mode 100644 index 00000000000..4709c2d8b85 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-projects-boot.t/run.t @@ -0,0 +1,67 @@ +Testing composition of theories across a dune workspace with a boot library. A +boot library must have the following: + +- Under the module prefix "Coq" +- Have a file Init/Prelude.v + +When composing with a (boot) library, every library must have -boot passed to +coqdep and coqc. + + $ dune build A + File "Coq/dune", lines 1-4, characters 0-48: + 1 | (rocq.theory + 2 | (name Coq) + 3 | (package Coq) + 4 | (boot)) + Error: Rule failed to generate the following targets: + - Coq/Init/NCoq_Init_Prelude.cmi + - Coq/Init/NCoq_Init_Prelude.cmxs + [1] + +We can even have a secondary private boot library in another scope and only the +private boot library will be loaded implicitly. + + $ cat > B/Coq/dune << EOF + > (include_subdirs qualified) + > (rocq.theory + > (name Coq) + > (boot)) + > EOF + + $ dune build B + File "B/Coq/dune", lines 2-4, characters 0-33: + 2 | (rocq.theory + 3 | (name Coq) + 4 | (boot)) + Error: Rule failed to generate the following targets: + - B/Coq/Init/NCoq_Init_Prelude.cmi + - B/Coq/Init/NCoq_Init_Prelude.cmxs + [1] + +However if this boot library is public Dune will complain + + $ cat > B/Coq/dune << EOF + > (include_subdirs qualified) + > (rocq.theory + > (name Coq) + > (package Foo) + > (boot)) + > EOF + +Due to lazy loading of installed theories, the error messages for having more +than one boot theory is a bit delayed and comes with the multiple rules error +message together. This is some extra noise for the user, but we are not sure how +to fix this currently. + + $ dune build B + Error: Cannot have more than one boot theory in scope: + - Coq at B/Coq/dune:2 + - Coq at Coq/dune:1 + Error: Multiple rules generated for + _build/install/default/lib/coq/theories/Init/Prelude.vo: + - Coq/dune:1 + - B/Coq/dune:2 + -> required by _build/default/B/Foo.install + -> required by alias B/all + -> required by alias B/default + [1] diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/b/b.v b/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/b/b.v new file mode 100644 index 00000000000..e184683b4d4 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/b/b.v @@ -0,0 +1,3 @@ +From a Require Import a. + +Definition bar := a.foo. diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/b/dune b/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/b/dune new file mode 100644 index 00000000000..47c7b4c0a05 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/b/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name b) + (package cvendor) + (theories a)) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/cvendor.opam b/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/cvendor.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/dune b/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/dune new file mode 100644 index 00000000000..7e780eb3f8e --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/dune @@ -0,0 +1,3 @@ +(rule + (alias default) + (action (echo "%{read:cvendor.install}"))) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/dune-project b/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/run.t b/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/run.t new file mode 100644 index 00000000000..31a233f13c1 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/run.t @@ -0,0 +1,14 @@ + + $ dune build + lib: [ + "_build/install/default/lib/cvendor/META" + "_build/install/default/lib/cvendor/dune-package" + "_build/install/default/lib/cvendor/opam" + ] + lib_root: [ + "_build/install/default/lib/coq/user-contrib/b/.coq-native/Nb_b.cmi" {"coq/user-contrib/b/.coq-native/Nb_b.cmi"} + "_build/install/default/lib/coq/user-contrib/b/.coq-native/Nb_b.cmxs" {"coq/user-contrib/b/.coq-native/Nb_b.cmxs"} + "_build/install/default/lib/coq/user-contrib/b/b.glob" {"coq/user-contrib/b/b.glob"} + "_build/install/default/lib/coq/user-contrib/b/b.v" {"coq/user-contrib/b/b.v"} + "_build/install/default/lib/coq/user-contrib/b/b.vo" {"coq/user-contrib/b/b.vo"} + ] diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/vendor/a/a.v b/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/vendor/a/a.v new file mode 100644 index 00000000000..d4389c6d37d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/vendor/a/a.v @@ -0,0 +1 @@ +Definition foo := 3. diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/vendor/a/dune b/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/vendor/a/dune new file mode 100644 index 00000000000..3eb00403877 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/vendor/a/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name a) + (package cvendor2)) diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/vendor/cvendor2.opam b/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/vendor/cvendor2.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/vendor/dune-project b/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/vendor/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/compose-two-scopes.t/vendor/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/coqdep-on-rebuild.t/a/a.v b/test/blackbox-tests/test-cases/rocq-native/coqdep-on-rebuild.t/a/a.v new file mode 100644 index 00000000000..d4389c6d37d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqdep-on-rebuild.t/a/a.v @@ -0,0 +1 @@ +Definition foo := 3. diff --git a/test/blackbox-tests/test-cases/rocq-native/coqdep-on-rebuild.t/a/dune b/test/blackbox-tests/test-cases/rocq-native/coqdep-on-rebuild.t/a/dune new file mode 100644 index 00000000000..6137494caa5 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqdep-on-rebuild.t/a/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name a) + (package csimple)) diff --git a/test/blackbox-tests/test-cases/rocq-native/coqdep-on-rebuild.t/csimple.opam b/test/blackbox-tests/test-cases/rocq-native/coqdep-on-rebuild.t/csimple.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq-native/coqdep-on-rebuild.t/dune-project b/test/blackbox-tests/test-cases/rocq-native/coqdep-on-rebuild.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqdep-on-rebuild.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/coqdep-on-rebuild.t/run.t b/test/blackbox-tests/test-cases/rocq-native/coqdep-on-rebuild.t/run.t new file mode 100644 index 00000000000..6dc3860006d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqdep-on-rebuild.t/run.t @@ -0,0 +1,29 @@ + $ mkdir b + $ cat > b/dune < (rocq.theory + > (name b) + > (theories a) + > (package csimple)) + > EOF + $ cat > b/b.v < From a Require Import a. + > Definition bar := a.foo. + > EOF + $ cat > b/d.v < From a Require Import a. + > Definition doo := a.foo. + > EOF + $ dune build --display short --debug-dependency-path + rocq a/.a.theory.d + rocq b/.b.theory.d + rocq a/Na_a.{cmi,cmxs},a/a.{glob,vo} + rocq b/Nb_b.{cmi,cmxs},b/b.{glob,vo} + rocq b/Nb_d.{cmi,cmxs},b/d.{glob,vo} + $ cat > b/b.v < From a Require Import a. + > Definition bar := a.foo. + > Definition zoo := 4. + > EOF + $ dune build --display short --debug-dependency-path + rocq b/.b.theory.d + rocq b/Nb_b.{cmi,cmxs},b/b.{glob,vo} diff --git a/test/blackbox-tests/test-cases/rocq-native/coqdoc.t/bar.v b/test/blackbox-tests/test-cases/rocq-native/coqdoc.t/bar.v new file mode 100644 index 00000000000..4627b76131c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqdoc.t/bar.v @@ -0,0 +1,3 @@ +From basic Require Import foo. + +Definition mynum (i : mynat) := 3. diff --git a/test/blackbox-tests/test-cases/rocq-native/coqdoc.t/dune b/test/blackbox-tests/test-cases/rocq-native/coqdoc.t/dune new file mode 100644 index 00000000000..3c373327984 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqdoc.t/dune @@ -0,0 +1,5 @@ +(rocq.theory + (name basic) + (package base) + (modules :standard) + (synopsis "Test Coq library")) diff --git a/test/blackbox-tests/test-cases/rocq-native/coqdoc.t/dune-project b/test/blackbox-tests/test-cases/rocq-native/coqdoc.t/dune-project new file mode 100644 index 00000000000..3e5f50e6bcc --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqdoc.t/dune-project @@ -0,0 +1,6 @@ +(lang dune 3.21) +(using directory-targets 0.1) +(using rocq 0.11) + +(package + (name base)) diff --git a/test/blackbox-tests/test-cases/rocq-native/coqdoc.t/foo.v b/test/blackbox-tests/test-cases/rocq-native/coqdoc.t/foo.v new file mode 100644 index 00000000000..53e0ce1b152 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqdoc.t/foo.v @@ -0,0 +1 @@ +Definition mynat := nat. diff --git a/test/blackbox-tests/test-cases/rocq-native/coqdoc.t/run.t b/test/blackbox-tests/test-cases/rocq-native/coqdoc.t/run.t new file mode 100644 index 00000000000..bfea5b23e56 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqdoc.t/run.t @@ -0,0 +1,47 @@ +We build the coqdoc html target: + $ dune build basic.html/ + +Now we inspect it: + $ ls _build/default/basic.html + basic.bar.html + basic.foo.html + coqdoc.css + index.html + toc.html + +We build the coqdoc latex target: + $ dune build basic.tex/ + +Now we inspect it: + $ ls _build/default/basic.tex + basic.bar.tex + basic.foo.tex + coqdoc.sty + +Next from a clean build we make sure that @all does *not* build any doc targets: + $ dune clean + $ dune build @all +Note that this currently works due to a bug in @all detecting directory targets. + $ ls _build/default + META.base + Nbasic_bar.cmi + Nbasic_bar.cmx + Nbasic_bar.cmxs + Nbasic_bar.o + Nbasic_foo.cmi + Nbasic_foo.cmx + Nbasic_foo.cmxs + Nbasic_foo.o + bar.glob + bar.v + bar.vo + bar.vok + bar.vos + base.dune-package + base.install + foo.glob + foo.v + foo.vo + foo.vok + foo.vos + diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-flags.t/Test.v b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-flags.t/Test.v new file mode 100644 index 00000000000..55d1fa98f60 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-flags.t/Test.v @@ -0,0 +1 @@ +Inductive foo := . diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-flags.t/dune b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-flags.t/dune new file mode 100644 index 00000000000..0d2922aae9f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-flags.t/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name minimal) + (flags -w -notation-overridden)) diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-flags.t/dune-project b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-flags.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-flags.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-flags.t/run.t b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-flags.t/run.t new file mode 100644 index 00000000000..9a0a42aa7aa --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-flags.t/run.t @@ -0,0 +1,26 @@ +Testing that the correct flags are being passed to dune rocq top + +The flags passed to coqc: + $ dune build && tail -1 _build/log | ../../scrub_coq_args.sh + rocq compile + -w -notation-overridden + -w -deprecated-native-compiler-option -native-output-dir . + -native-compiler on + -nI lib/rocq-runtime/kernel + -nI . + -boot + -R coq/theories Corelib + -R . minimal + Test.v + +The flags passed to coqtop: + $ dune rocq top --toplevel=echo Test.v | ../../scrub_coq_args.sh + -topfile $TESTCASE_ROOT/_build/default/Test.v + -w -notation-overridden + -w -deprecated-native-compiler-option -native-output-dir . + -native-compiler on + -nI lib/rocq-runtime/kernel + -nI $TESTCASE_ROOT/_build/default + -boot + -R coq/theories Corelib + -R $TESTCASE_ROOT/_build/default minimal diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-gen-file.t b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-gen-file.t new file mode 100644 index 00000000000..3e1b217aee4 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-gen-file.t @@ -0,0 +1,22 @@ +Running the Coq Toplevel on a generated file with a dependency. + + $ cat >bar.v < From basic Require Import foo. + > Definition mynum (i : mynat) := 3. + > EOF + $ cat >foo.v < Definition mynat := nat. + > EOF + $ cat >dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + $ cat >dune < (rocq.theory + > (name basic)) + > (rule + > (target bar_gen.v) + > (deps bar.v) + > (action (copy %{deps} %{target}))) + > EOF + $ cat bar.v | dune rocq top bar_gen.v > /dev/null 2> /dev/null diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-nested.t/dune-project b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-nested.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-nested.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-nested.t/run.t b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-nested.t/run.t new file mode 100644 index 00000000000..cd66f25841c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-nested.t/run.t @@ -0,0 +1,28 @@ +Checking that we compute the directory and file for dune rocq top correctly + + $ dune build theories/c.vo + $ dune build theories/b/b.vo + $ dune rocq top --toplevel=echo theories/c.v | ../../scrub_coq_args.sh + -topfile $TESTCASE_ROOT/_build/default/theories/c.v + -w -deprecated-native-compiler-option -native-output-dir . + -native-compiler on + -nI lib/rocq-runtime/kernel + -nI $TESTCASE_ROOT/_build/default/theories + -nI $TESTCASE_ROOT/_build/default/theories/a + -nI $TESTCASE_ROOT/_build/default/theories/b + -boot + -R coq/theories Corelib + -R $TESTCASE_ROOT/_build/default/theories foo + + $ dune rocq top --toplevel=echo theories/b/b.v | ../../scrub_coq_args.sh + -topfile $TESTCASE_ROOT/_build/default/theories/b/b.v + -w -deprecated-native-compiler-option -native-output-dir . + -native-compiler on + -nI lib/rocq-runtime/kernel + -nI $TESTCASE_ROOT/_build/default/theories + -nI $TESTCASE_ROOT/_build/default/theories/a + -nI $TESTCASE_ROOT/_build/default/theories/b + -boot + -R coq/theories Corelib + -R $TESTCASE_ROOT/_build/default/theories foo + diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-nested.t/theories/a/a.v b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-nested.t/theories/a/a.v new file mode 100644 index 00000000000..3085bc9cedc --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-nested.t/theories/a/a.v @@ -0,0 +1 @@ +Definition bar := 3. diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-nested.t/theories/b/b.v b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-nested.t/theories/b/b.v new file mode 100644 index 00000000000..d5bde6eccc8 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-nested.t/theories/b/b.v @@ -0,0 +1,3 @@ +Require a. + +Definition moo := a.bar. diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-nested.t/theories/c.v b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-nested.t/theories/c.v new file mode 100644 index 00000000000..2bbebffd410 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-nested.t/theories/c.v @@ -0,0 +1,3 @@ +Require d. + +Definition uuhh := d.aike. diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-nested.t/theories/d.v b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-nested.t/theories/d.v new file mode 100644 index 00000000000..d678e8cb591 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-nested.t/theories/d.v @@ -0,0 +1 @@ +Definition aike := 3. diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-nested.t/theories/dune b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-nested.t/theories/dune new file mode 100644 index 00000000000..174d3d16185 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-nested.t/theories/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name foo)) + +(include_subdirs qualified) diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-no-build.t b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-no-build.t new file mode 100644 index 00000000000..22de41da80c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-no-build.t @@ -0,0 +1,44 @@ +Testing the -no-build option of dune rocq top: + + $ mkdir dir + $ cat >dir/bar.v < From basic Require Import foo. + > Definition mynum (i : mynat) := 3. + > EOF + $ cat >dir/foo.v < Definition mynat := nat. + > EOF + $ cat >dir/dune < (rocq.theory + > (name basic)) + > EOF + $ cat >dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + +On a fresh build, this should do nothing but should pass the correct flags: + + $ dune rocq top --no-build --display short --toplevel echo dir/bar.v | ../scrub_coq_args.sh + -topfile $TESTCASE_ROOT/_build/default/dir/bar.v + -w -deprecated-native-compiler-option -native-output-dir . + -native-compiler on + -nI lib/rocq-runtime/kernel + -nI $TESTCASE_ROOT/_build/default/dir + -boot + -R coq/theories Corelib + -R $TESTCASE_ROOT/_build/default/dir basic + +And for comparison normally a build would happen: + + $ dune rocq top --display short --toplevel echo dir/bar.v | ../scrub_coq_args.sh + rocq dir/.basic.theory.d + rocq dir/Nbasic_foo.{cmi,cmxs},dir/foo.{glob,vo} + -topfile $TESTCASE_ROOT/_build/default/dir/bar.v + -w -deprecated-native-compiler-option -native-output-dir . + -native-compiler on + -nI lib/rocq-runtime/kernel + -nI $TESTCASE_ROOT/_build/default/dir + -boot + -R coq/theories Corelib + -R $TESTCASE_ROOT/_build/default/dir basic diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-no-stanza.t b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-no-stanza.t new file mode 100644 index 00000000000..7394740db99 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-no-stanza.t @@ -0,0 +1,14 @@ +Running the Coq Toplevel on a file that is not part of a stanza. + + $ cat >foo.v < Definition mynat := nat. + > EOF + $ cat >dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + $ dune rocq top foo.v || echo failed + Error: Cannot find file: foo.v + Hint: Is the file part of a stanza? + Hint: Has the file been written to disk? + failed diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-recomp.t b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-recomp.t new file mode 100644 index 00000000000..15b7def2541 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-recomp.t @@ -0,0 +1,66 @@ +Check that dependencies are not recompiled when this is not necessary. This +was initially an issue, and was reported by @MackieLoeffel in #5457 (see +https://github.com/ocaml/dune/pull/5457#issuecomment-1084161587). + + $ mkdir dir + $ cat >dir/bar.v < From basic Require Import foo. + > Definition mynum (i : mynat) := 3. + > EOF + $ cat >dir/foo.v < Definition mynat := nat. + > EOF + $ cat >dir/dune < (rocq.theory + > (name basic)) + > EOF + $ cat >dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + $ dune rocq top --display short --toplevel echo dir/bar.v | ../scrub_coq_args.sh + rocq dir/.basic.theory.d + rocq dir/Nbasic_foo.{cmi,cmxs},dir/foo.{glob,vo} + -topfile $TESTCASE_ROOT/_build/default/dir/bar.v + -w -deprecated-native-compiler-option -native-output-dir . + -native-compiler on + -nI lib/rocq-runtime/kernel + -nI $TESTCASE_ROOT/_build/default/dir + -boot + -R coq/theories Corelib + -R $TESTCASE_ROOT/_build/default/dir basic + $ dune rocq top --display short --toplevel echo dir/bar.v | ../scrub_coq_args.sh + -topfile $TESTCASE_ROOT/_build/default/dir/bar.v + -w -deprecated-native-compiler-option -native-output-dir . + -native-compiler on + -nI lib/rocq-runtime/kernel + -nI $TESTCASE_ROOT/_build/default/dir + -boot + -R coq/theories Corelib + -R $TESTCASE_ROOT/_build/default/dir basic + $ dune clean + $ (cd dir && dune rocq top --root .. --display short --toplevel echo dir/bar.v) | ../scrub_coq_args.sh + Entering directory '..' + rocq dir/.basic.theory.d + rocq dir/Nbasic_foo.{cmi,cmxs},dir/foo.{glob,vo} + Leaving directory '..' + -topfile $TESTCASE_ROOT/_build/default/dir/bar.v + -w -deprecated-native-compiler-option -native-output-dir . + -native-compiler on + -nI lib/rocq-runtime/kernel + -nI $TESTCASE_ROOT/_build/default/dir + -boot + -R coq/theories Corelib + -R $TESTCASE_ROOT/_build/default/dir basic + $ (cd dir && dune rocq top --root .. --display short --toplevel echo dir/bar.v) | ../scrub_coq_args.sh + Entering directory '..' + Leaving directory '..' + -topfile $TESTCASE_ROOT/_build/default/dir/bar.v + -w -deprecated-native-compiler-option -native-output-dir . + -native-compiler on + -nI lib/rocq-runtime/kernel + -nI $TESTCASE_ROOT/_build/default/dir + -boot + -R coq/theories Corelib + -R $TESTCASE_ROOT/_build/default/dir basic + diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-root.t/dune-project b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-root.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-root.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-root.t/run.t b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-root.t/run.t new file mode 100644 index 00000000000..cc979720ca8 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-root.t/run.t @@ -0,0 +1,27 @@ +All dune commands work when you run them in sub-directories, so this should be no exception. + + $ dune rocq top --toplevel=echo -- theories/foo.v | ../../scrub_coq_args.sh + -topfile $TESTCASE_ROOT/_build/default/theories/foo.v + -w -deprecated-native-compiler-option -native-output-dir . + -native-compiler on + -nI lib/rocq-runtime/kernel + -nI $TESTCASE_ROOT/_build/default/theories + -boot + -R coq/theories Corelib + -R $TESTCASE_ROOT/_build/default/theories foo + $ cd theories + +This test is currently broken due to the workspace resolution being faulty #5899. + $ dune rocq top --toplevel=echo -- foo.v + File ".", line 1, characters 0-0: + Warning: No dune-project file has been found in directory ".". A default one + is assumed but the project might break when dune is upgraded. Please create a + dune-project file. + Hint: generate the project file with: $ dune init project + File "dune", lines 1-2, characters 0-25: + 1 | (rocq.theory + 2 | (name foo)) + Error: 'rocq.theory' is available only when rocq is enabled in the + dune-project file. You must enable it using (using rocq 0.11) in your + dune-project file. + [1] diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-root.t/theories/dune b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-root.t/theories/dune new file mode 100644 index 00000000000..5c5490c5030 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-root.t/theories/dune @@ -0,0 +1,2 @@ +(rocq.theory + (name foo)) diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-root.t/theories/foo.v b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-root.t/theories/foo.v new file mode 100644 index 00000000000..8ac4c3baeac --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-root.t/theories/foo.v @@ -0,0 +1 @@ +Definition answer := 42. diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/coq_dir1/dir1/file3.v b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/coq_dir1/dir1/file3.v new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/coq_dir1/dune b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/coq_dir1/dune new file mode 100644 index 00000000000..f6a64602a38 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/coq_dir1/dune @@ -0,0 +1,3 @@ +(include_subdirs qualified) +(rocq.theory + (name theory2)) diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/coq_dir1/file2.v b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/coq_dir1/file2.v new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/dune b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/dune new file mode 100644 index 00000000000..784b4143d4e --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/dune @@ -0,0 +1,2 @@ +(rocq.theory + (name theory1)) diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/dune-project b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/dune-workspace b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/dune-workspace new file mode 100644 index 00000000000..e1b8e598780 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/dune-workspace @@ -0,0 +1 @@ +(lang dune 3.21) diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/file1.v b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/file1.v new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/project/coq_dir2/dir2/file6.v b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/project/coq_dir2/dir2/file6.v new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/project/coq_dir2/dune b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/project/coq_dir2/dune new file mode 100644 index 00000000000..c8a814bf474 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/project/coq_dir2/dune @@ -0,0 +1,3 @@ +(include_subdirs qualified) +(rocq.theory + (name theory4)) diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/project/coq_dir2/file5.v b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/project/coq_dir2/file5.v new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/project/dune b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/project/dune new file mode 100644 index 00000000000..dd6bd6a5c96 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/project/dune @@ -0,0 +1,2 @@ +(rocq.theory + (name theory3)) diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/project/dune-project b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/project/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/project/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/project/file4.v b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/project/file4.v new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/run.t b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/run.t new file mode 100644 index 00000000000..b78350d9d07 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/run.t @@ -0,0 +1,108 @@ +Running "dune rocq top" from different directories in a workspace. The setup is +a workspace whose root is the root of a first project, and a second project is +contained under directory "project". + + $ unset INSIDE_DUNE + $ . ./util.sh + +Calling "dune rocq top" from the workspace root. + + $ coqtop_test file1.v + $ coqtop_test coq_dir1/file2.v + $ coqtop_test coq_dir1/dir1/file3.v + $ coqtop_test project/file4.v + $ coqtop_test project/coq_dir2/file5.v + $ coqtop_test project/coq_dir2/dir2/file6.v + +Calling "dune rocq top" from the "coq_dir1" directory. + + $ cd coq_dir1 + + $ coqtop_test ../file1.v + $ coqtop_test ../file1.v + $ coqtop_test ../coq_dir1/file2.v + $ coqtop_test ../coq_dir1/dir1/file3.v + $ coqtop_test ../project/file4.v + $ coqtop_test ../project/coq_dir2/file5.v + $ coqtop_test ../project/coq_dir2/dir2/file6.v + + $ coqtop_test file2.v + $ coqtop_test dir1/file3.v + + $ cd .. + +Calling "dune rocq top" from the "coq_dir1/dir1" directory. + + $ cd coq_dir1/dir1 + + $ coqtop_test ../../file1.v + $ coqtop_test ../../file1.v + $ coqtop_test ../../coq_dir1/file2.v + $ coqtop_test ../../coq_dir1/dir1/file3.v + $ coqtop_test ../../project/file4.v + $ coqtop_test ../../project/coq_dir2/file5.v + $ coqtop_test ../../project/coq_dir2/dir2/file6.v + + $ coqtop_test ../file2.v + $ coqtop_test ../dir1/file3.v + $ coqtop_test file3.v + + $ cd ../.. + +Calling "dune rocq top" from the "project" directory. + + $ cd project + + $ coqtop_test ../file1.v + $ coqtop_test ../coq_dir1/file2.v + $ coqtop_test ../coq_dir1/dir1/file3.v + $ coqtop_test ../project/file4.v + $ coqtop_test ../project/coq_dir2/file5.v + $ coqtop_test ../project/coq_dir2/dir2/file6.v + + $ coqtop_test file4.v + $ coqtop_test coq_dir2/file5.v + $ coqtop_test coq_dir2/dir2/file6.v + + $ cd .. + +Calling "dune rocq top" from the "project/coq_dir2" directory. + + $ cd project/coq_dir2 + + $ coqtop_test ../../file1.v + $ coqtop_test ../../file1.v + $ coqtop_test ../../coq_dir1/file2.v + $ coqtop_test ../../coq_dir1/dir1/file3.v + $ coqtop_test ../../project/file4.v + $ coqtop_test ../../project/coq_dir2/file5.v + $ coqtop_test ../../project/coq_dir2/dir2/file6.v + + $ coqtop_test ../file4.v + $ coqtop_test ../coq_dir2/file5.v + $ coqtop_test ../coq_dir2/dir2/file6.v + $ coqtop_test file5.v + $ coqtop_test dir2/file6.v + + $ cd ../.. + +Calling "dune rocq top" from the "project/coq_dir2/dir2" directory. + + $ cd project/coq_dir2/dir2 + + $ coqtop_test ../../../file1.v + $ coqtop_test ../../../file1.v + $ coqtop_test ../../../coq_dir1/file2.v + $ coqtop_test ../../../coq_dir1/dir1/file3.v + $ coqtop_test ../../../project/file4.v + $ coqtop_test ../../../project/coq_dir2/file5.v + $ coqtop_test ../../../project/coq_dir2/dir2/file6.v + + $ coqtop_test ../../file4.v + $ coqtop_test ../../coq_dir2/file5.v + $ coqtop_test ../../coq_dir2/dir2/file6.v + $ coqtop_test ../file5.v + $ coqtop_test ../dir2/file6.v + $ coqtop_test file6.v + + $ cd ../../.. diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/util.sh b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/util.sh new file mode 100755 index 00000000000..69c9dbdbcf9 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop-workspace.t/util.sh @@ -0,0 +1,5 @@ +OUTPUT="$PWD/coqtop_test.tmp" + +coqtop_test() { + (true | (dune rocq top "$1" 1>$OUTPUT 2>&1)) || cat $OUTPUT +} diff --git a/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop.t b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop.t new file mode 100644 index 00000000000..249948acd97 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/coqtop/coqtop.t @@ -0,0 +1,18 @@ +Running the Coq Toplevel on a file with a dependency. + + $ cat >bar.v < From basic Require Import foo. + > Definition mynum (i : mynat) := 3. + > EOF + $ cat >foo.v < Definition mynat := nat. + > EOF + $ cat >dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + $ cat >dune < (rocq.theory + > (name basic)) + > EOF + $ cat bar.v | dune rocq top bar.v > /dev/null 2> /dev/null diff --git a/test/blackbox-tests/test-cases/rocq-native/dune b/test/blackbox-tests/test-cases/rocq-native/dune new file mode 100644 index 00000000000..d465a438c04 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/dune @@ -0,0 +1,11 @@ +; Coq for macos does not support native compilation yet. +; TODO Enable tests when ready + +(cram + (applies_to :whole_subtree) + (deps %{bin:rocq} scrub_coq_args.sh) + (alias runtest-rocq-native) + (enabled_if + (and + (= %{env:DUNE_ROCQ_NATIVE_TEST=disable} enable) + (<> %{system} macosx)))) diff --git a/test/blackbox-tests/test-cases/rocq-native/extract.t b/test/blackbox-tests/test-cases/rocq-native/extract.t new file mode 100644 index 00000000000..489dc44f435 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/extract.t @@ -0,0 +1,60 @@ + $ cat >dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + + $ cat >extract.v < Definition nb (b : bool) : bool := + > match b with + > | false => true + > | true => false + > end. + > + > Require Extraction. + > Separate Extraction nb. + > EOF + + $ cat >dune < (rocq.extraction + > (prelude extract) + > (extracted_modules Datatypes extract)) + > + > (executable + > (name foo)) + > EOF + + $ cat >foo.ml < open Datatypes + > let () = + > print_endline ( + > match Extract.nb Datatypes.Coq_true with + > | Coq_true -> "true" + > | Coq_false -> "false" + > ) + > EOF + + $ dune exec ./foo.exe + File "./extract.v", line 8, characters 0-23: + Warning: Setting extraction output directory by default to + "$TESTCASE_ROOT/_build/default". + Use "Set Extraction Output Directory" or command line option + "-output-directory" to set a different directory for extracted files to + appear in. [extraction-default-directory,extraction,default] + false + $ ls _build/default + Datatypes.ml + Datatypes.mli + NDuneExtraction_extract.cmi + NDuneExtraction_extract.cmx + NDuneExtraction_extract.cmxs + NDuneExtraction_extract.o + extract.glob + extract.ml + extract.mli + extract.v + extract.vo + extract.vok + extract.vos + foo.exe + foo.ml + foo.mli diff --git a/test/blackbox-tests/test-cases/rocq-native/flags.t b/test/blackbox-tests/test-cases/rocq-native/flags.t new file mode 100644 index 00000000000..d8c02c0bcd7 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/flags.t @@ -0,0 +1,193 @@ +Test cases to check Coq's flag setting is correct: + + $ cat > dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + + $ cat > foo.v < Definition t := 3. + > EOF + +Test case: default flags + + $ cat > dune < (rocq.theory + > (name foo)) + > EOF + + $ dune build foo.vo && tail -n 1 _build/log | ./scrub_coq_args.sh + rocq compile -q + -w -deprecated-native-compiler-option -native-output-dir . + -native-compiler on + -nI lib/rocq-runtime/kernel + -nI . + -boot + -R coq/theories Corelib + -R . foo + foo.v + +TC: :standard + + $ cat > dune < (rocq.theory + > (name foo) + > (flags :standard)) + > EOF + + $ rm _build/default/foo.vo + $ dune build foo.vo && tail -n 1 _build/log | ./scrub_coq_args.sh + rocq compile -q + -w -deprecated-native-compiler-option -native-output-dir . + -native-compiler on + -nI lib/rocq-runtime/kernel + -nI . + -boot + -R coq/theories Corelib + -R . foo + foo.v + +TC: override :standard + + $ cat > dune < (rocq.theory + > (name foo) + > (flags )) + > EOF + + $ dune build foo.vo && tail -n 1 _build/log | ./scrub_coq_args.sh + rocq compile + -w -deprecated-native-compiler-option -native-output-dir . + -native-compiler on + -nI lib/rocq-runtime/kernel + -nI . + -boot + -R coq/theories Corelib + -R . foo + foo.v + +TC: add to :standard + + $ cat > dune < (rocq.theory + > (name foo) + > (flags :standard -type-in-type)) + > EOF + + $ dune build foo.vo && tail -n 1 _build/log | ./scrub_coq_args.sh + rocq compile -q -type-in-type + -w -deprecated-native-compiler-option -native-output-dir . + -native-compiler on + -nI lib/rocq-runtime/kernel + -nI . + -boot + -R coq/theories Corelib + -R . foo + foo.v + +TC: extend in workspace + override standard + + $ cat > dune < (rocq.theory + > (name foo) + > (flags :standard)) + > EOF + + $ cat > dune-workspace < (lang dune 3.21) + > (env (dev (rocq (flags -type-in-type)))) + > EOF + + $ dune build foo.vo && tail -n 1 _build/log | ./scrub_coq_args.sh + rocq compile -type-in-type + -w -deprecated-native-compiler-option -native-output-dir . + -native-compiler on + -nI lib/rocq-runtime/kernel + -nI . + -boot + -R coq/theories Corelib + -R . foo + foo.v + +TC: extend in workspace + override standard + + $ cat > dune-workspace < (lang dune 3.21) + > (env (dev (rocq (flags :standard -type-in-type)))) + > EOF + + $ dune build foo.vo && tail -n 1 _build/log | ./scrub_coq_args.sh + rocq compile -q -type-in-type + -w -deprecated-native-compiler-option -native-output-dir . + -native-compiler on + -nI lib/rocq-runtime/kernel + -nI . + -boot + -R coq/theories Corelib + -R . foo + foo.v + +TC: extend in dune (env) + override standard + + $ cat > dune < (rocq.theory + > (name foo)) + > (env (dev (rocq (flags -type-in-type)))) + > EOF + + $ rm -rf _build/default/foo.vo + $ dune build foo.vo && tail -n 1 _build/log | ./scrub_coq_args.sh + rocq compile -type-in-type + -w -deprecated-native-compiler-option -native-output-dir . + -native-compiler on + -nI lib/rocq-runtime/kernel + -nI . + -boot + -R coq/theories Corelib + -R . foo + foo.v + +TC: extend in dune (env) + standard + + $ cat > dune < (rocq.theory + > (name foo)) + > (env (dev (rocq (flags :standard -type-in-type)))) + > EOF + + $ rm -rf _build/default/foo.vo + $ dune build foo.vo && tail -n 1 _build/log | ./scrub_coq_args.sh + rocq compile -q -type-in-type -type-in-type + -w -deprecated-native-compiler-option -native-output-dir . + -native-compiler on + -nI lib/rocq-runtime/kernel + -nI . + -boot + -R coq/theories Corelib + -R . foo + foo.v + +TC: extend in dune (env) + workspace + standard + + $ cat > dune < (rocq.theory + > (name foo)) + > (env (dev (rocq (flags :standard -bt)))) + > EOF + + $ cat > dune-workspace < (lang dune 3.21) + > (env (dev (rocq (flags :standard -type-in-type)))) + > EOF + + $ rm -rf _build/default/foo.vo + $ dune build foo.vo && tail -n 1 _build/log | ./scrub_coq_args.sh + rocq compile -q -type-in-type -bt + -w -deprecated-native-compiler-option -native-output-dir . + -native-compiler on + -nI lib/rocq-runtime/kernel + -nI . + -boot + -R coq/theories Corelib + -R . foo + foo.v diff --git a/test/blackbox-tests/test-cases/rocq-native/native-compose.t/bar/bar.v b/test/blackbox-tests/test-cases/rocq-native/native-compose.t/bar/bar.v new file mode 100644 index 00000000000..afe3c3b25d9 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/native-compose.t/bar/bar.v @@ -0,0 +1,3 @@ +From foo Require Import foo. + +Definition mynum (i : mynat) := 3. diff --git a/test/blackbox-tests/test-cases/rocq-native/native-compose.t/bar/dune b/test/blackbox-tests/test-cases/rocq-native/native-compose.t/bar/dune new file mode 100644 index 00000000000..2fe29063093 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/native-compose.t/bar/dune @@ -0,0 +1,6 @@ +(rocq.theory + (name bar.baz) + (package base) + (theories foo) + (modules :standard) + (synopsis "Test Coq library")) diff --git a/test/blackbox-tests/test-cases/rocq-native/native-compose.t/base.opam b/test/blackbox-tests/test-cases/rocq-native/native-compose.t/base.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq-native/native-compose.t/dune b/test/blackbox-tests/test-cases/rocq-native/native-compose.t/dune new file mode 100644 index 00000000000..b53cf1eb053 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/native-compose.t/dune @@ -0,0 +1,3 @@ +(rule + (alias default) + (action (echo "%{read:base.install}"))) diff --git a/test/blackbox-tests/test-cases/rocq-native/native-compose.t/dune-project b/test/blackbox-tests/test-cases/rocq-native/native-compose.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/native-compose.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/native-compose.t/foo/a/a.v b/test/blackbox-tests/test-cases/rocq-native/native-compose.t/foo/a/a.v new file mode 100644 index 00000000000..cb1e5b1bea3 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/native-compose.t/foo/a/a.v @@ -0,0 +1 @@ +Definition aa := 3. diff --git a/test/blackbox-tests/test-cases/rocq-native/native-compose.t/foo/dune b/test/blackbox-tests/test-cases/rocq-native/native-compose.t/foo/dune new file mode 100644 index 00000000000..b7e33d8b6c1 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/native-compose.t/foo/dune @@ -0,0 +1,7 @@ +(rocq.theory + (name foo) + (package base) + (modules :standard) + (synopsis "Test Coq library")) + +(include_subdirs qualified) diff --git a/test/blackbox-tests/test-cases/rocq-native/native-compose.t/foo/foo.v b/test/blackbox-tests/test-cases/rocq-native/native-compose.t/foo/foo.v new file mode 100644 index 00000000000..53e0ce1b152 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/native-compose.t/foo/foo.v @@ -0,0 +1 @@ +Definition mynat := nat. diff --git a/test/blackbox-tests/test-cases/rocq-native/native-compose.t/run.t b/test/blackbox-tests/test-cases/rocq-native/native-compose.t/run.t new file mode 100644 index 00000000000..5342b1ce075 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/native-compose.t/run.t @@ -0,0 +1,30 @@ + $ dune build --profile=release --display short --debug-dependency-path @all + rocq bar/.bar.theory.d + rocq foo/.foo.theory.d + rocq foo/Nfoo_foo.{cmi,cmxs},foo/foo.{glob,vo} + rocq foo/a/Nfoo_a_a.{cmi,cmxs},foo/a/a.{glob,vo} + rocq bar/Nbar_baz_bar.{cmi,cmxs},bar/bar.{glob,vo} + + $ dune build --profile=release --debug-dependency-path @default + lib: [ + "_build/install/default/lib/base/META" + "_build/install/default/lib/base/dune-package" + "_build/install/default/lib/base/opam" + ] + lib_root: [ + "_build/install/default/lib/coq/user-contrib/bar/baz/.coq-native/Nbar_baz_bar.cmi" {"coq/user-contrib/bar/baz/.coq-native/Nbar_baz_bar.cmi"} + "_build/install/default/lib/coq/user-contrib/bar/baz/.coq-native/Nbar_baz_bar.cmxs" {"coq/user-contrib/bar/baz/.coq-native/Nbar_baz_bar.cmxs"} + "_build/install/default/lib/coq/user-contrib/bar/baz/bar.glob" {"coq/user-contrib/bar/baz/bar.glob"} + "_build/install/default/lib/coq/user-contrib/bar/baz/bar.v" {"coq/user-contrib/bar/baz/bar.v"} + "_build/install/default/lib/coq/user-contrib/bar/baz/bar.vo" {"coq/user-contrib/bar/baz/bar.vo"} + "_build/install/default/lib/coq/user-contrib/foo/.coq-native/Nfoo_foo.cmi" {"coq/user-contrib/foo/.coq-native/Nfoo_foo.cmi"} + "_build/install/default/lib/coq/user-contrib/foo/.coq-native/Nfoo_foo.cmxs" {"coq/user-contrib/foo/.coq-native/Nfoo_foo.cmxs"} + "_build/install/default/lib/coq/user-contrib/foo/a/.coq-native/Nfoo_a_a.cmi" {"coq/user-contrib/foo/a/.coq-native/Nfoo_a_a.cmi"} + "_build/install/default/lib/coq/user-contrib/foo/a/.coq-native/Nfoo_a_a.cmxs" {"coq/user-contrib/foo/a/.coq-native/Nfoo_a_a.cmxs"} + "_build/install/default/lib/coq/user-contrib/foo/a/a.glob" {"coq/user-contrib/foo/a/a.glob"} + "_build/install/default/lib/coq/user-contrib/foo/a/a.v" {"coq/user-contrib/foo/a/a.v"} + "_build/install/default/lib/coq/user-contrib/foo/a/a.vo" {"coq/user-contrib/foo/a/a.vo"} + "_build/install/default/lib/coq/user-contrib/foo/foo.glob" {"coq/user-contrib/foo/foo.glob"} + "_build/install/default/lib/coq/user-contrib/foo/foo.v" {"coq/user-contrib/foo/foo.v"} + "_build/install/default/lib/coq/user-contrib/foo/foo.vo" {"coq/user-contrib/foo/foo.vo"} + ] diff --git a/test/blackbox-tests/test-cases/rocq-native/native-single.t/bar.v b/test/blackbox-tests/test-cases/rocq-native/native-single.t/bar.v new file mode 100644 index 00000000000..4627b76131c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/native-single.t/bar.v @@ -0,0 +1,3 @@ +From basic Require Import foo. + +Definition mynum (i : mynat) := 3. diff --git a/test/blackbox-tests/test-cases/rocq-native/native-single.t/base.opam b/test/blackbox-tests/test-cases/rocq-native/native-single.t/base.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq-native/native-single.t/dune b/test/blackbox-tests/test-cases/rocq-native/native-single.t/dune new file mode 100644 index 00000000000..f11be27b12d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/native-single.t/dune @@ -0,0 +1,9 @@ +(rocq.theory + (name basic) + (package base) + (modules :standard) + (synopsis "Test Coq library")) + +(rule + (alias default) + (action (echo "%{read:base.install}"))) diff --git a/test/blackbox-tests/test-cases/rocq-native/native-single.t/dune-project b/test/blackbox-tests/test-cases/rocq-native/native-single.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/native-single.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/native-single.t/foo.v b/test/blackbox-tests/test-cases/rocq-native/native-single.t/foo.v new file mode 100644 index 00000000000..53e0ce1b152 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/native-single.t/foo.v @@ -0,0 +1 @@ +Definition mynat := nat. diff --git a/test/blackbox-tests/test-cases/rocq-native/native-single.t/run.t b/test/blackbox-tests/test-cases/rocq-native/native-single.t/run.t new file mode 100644 index 00000000000..07481b8fba5 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/native-single.t/run.t @@ -0,0 +1,23 @@ + $ dune build --profile=release --display short --debug-dependency-path @all + rocq .basic.theory.d + rocq Nbasic_foo.{cmi,cmxs},foo.{glob,vo} + rocq Nbasic_bar.{cmi,cmxs},bar.{glob,vo} + + $ dune build --profile=release --debug-dependency-path @default + lib: [ + "_build/install/default/lib/base/META" + "_build/install/default/lib/base/dune-package" + "_build/install/default/lib/base/opam" + ] + lib_root: [ + "_build/install/default/lib/coq/user-contrib/basic/.coq-native/Nbasic_bar.cmi" {"coq/user-contrib/basic/.coq-native/Nbasic_bar.cmi"} + "_build/install/default/lib/coq/user-contrib/basic/.coq-native/Nbasic_bar.cmxs" {"coq/user-contrib/basic/.coq-native/Nbasic_bar.cmxs"} + "_build/install/default/lib/coq/user-contrib/basic/.coq-native/Nbasic_foo.cmi" {"coq/user-contrib/basic/.coq-native/Nbasic_foo.cmi"} + "_build/install/default/lib/coq/user-contrib/basic/.coq-native/Nbasic_foo.cmxs" {"coq/user-contrib/basic/.coq-native/Nbasic_foo.cmxs"} + "_build/install/default/lib/coq/user-contrib/basic/bar.glob" {"coq/user-contrib/basic/bar.glob"} + "_build/install/default/lib/coq/user-contrib/basic/bar.v" {"coq/user-contrib/basic/bar.v"} + "_build/install/default/lib/coq/user-contrib/basic/bar.vo" {"coq/user-contrib/basic/bar.vo"} + "_build/install/default/lib/coq/user-contrib/basic/foo.glob" {"coq/user-contrib/basic/foo.glob"} + "_build/install/default/lib/coq/user-contrib/basic/foo.v" {"coq/user-contrib/basic/foo.v"} + "_build/install/default/lib/coq/user-contrib/basic/foo.vo" {"coq/user-contrib/basic/foo.vo"} + ] diff --git a/test/blackbox-tests/test-cases/rocq-native/no-stdlib.t/bar.v b/test/blackbox-tests/test-cases/rocq-native/no-stdlib.t/bar.v new file mode 100644 index 00000000000..53e0ce1b152 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/no-stdlib.t/bar.v @@ -0,0 +1 @@ +Definition mynat := nat. diff --git a/test/blackbox-tests/test-cases/rocq-native/no-stdlib.t/dune b/test/blackbox-tests/test-cases/rocq-native/no-stdlib.t/dune new file mode 100644 index 00000000000..866382968f0 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/no-stdlib.t/dune @@ -0,0 +1,5 @@ +(rocq.theory + (name basic) + (package no-stdlib) + (stdlib no) + (synopsis "Test Coq library")) diff --git a/test/blackbox-tests/test-cases/rocq-native/no-stdlib.t/dune-project b/test/blackbox-tests/test-cases/rocq-native/no-stdlib.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/no-stdlib.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/no-stdlib.t/foo.v b/test/blackbox-tests/test-cases/rocq-native/no-stdlib.t/foo.v new file mode 100644 index 00000000000..67f3fb42097 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/no-stdlib.t/foo.v @@ -0,0 +1 @@ +From Corelib Require Import Prelude. diff --git a/test/blackbox-tests/test-cases/rocq-native/no-stdlib.t/no-stdlib.opam b/test/blackbox-tests/test-cases/rocq-native/no-stdlib.t/no-stdlib.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq-native/no-stdlib.t/run.t b/test/blackbox-tests/test-cases/rocq-native/no-stdlib.t/run.t new file mode 100644 index 00000000000..920ca4a48f1 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/no-stdlib.t/run.t @@ -0,0 +1,21 @@ +Test that when `(stdlib no)` is provided, the standard library is not bound to `Coq` +and the prelude is not imported; we expect the below two tests to fail. + + $ dune build --display=short foo.vo + rocq .basic.theory.d + Warning: in file foo.v, library Prelude is required + from root Corelib and has not been found in the loadpath! + [module-not-found,filesystem,default] + rocq Nbasic_foo.{cmi,cmxs},foo.{glob,vo} (exit 1) + File "./foo.v", line 1, characters 28-35: + Error: Cannot find a physical path bound to logical path + Prelude with prefix Corelib. + + [1] + + $ dune build --display=short bar.vo + rocq Nbasic_bar.{cmi,cmxs},bar.{glob,vo} (exit 1) + File "./bar.v", line 1, characters 20-23: + Error: The reference nat was not found in the current environment. + + [1] diff --git a/test/blackbox-tests/test-cases/rocq-native/per_file_flags.t/bar.v b/test/blackbox-tests/test-cases/rocq-native/per_file_flags.t/bar.v new file mode 100644 index 00000000000..1845f3b657f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/per_file_flags.t/bar.v @@ -0,0 +1,6 @@ +From basic Require Import foo. + +Definition mynum (i : mynat) := 3. + +(* This should not emit a warning *) +Variable (A : nat). diff --git a/test/blackbox-tests/test-cases/rocq-native/per_file_flags.t/base.opam b/test/blackbox-tests/test-cases/rocq-native/per_file_flags.t/base.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq-native/per_file_flags.t/dune b/test/blackbox-tests/test-cases/rocq-native/per_file_flags.t/dune new file mode 100644 index 00000000000..7eb30a9b19a --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/per_file_flags.t/dune @@ -0,0 +1,14 @@ +(rocq.theory + (name basic) + (package base) + (modules :standard) + (flags :standard -w declaration-outside-section) + (modules_flags + (bar :standard -w -declaration-outside-section)) + (synopsis "Test Coq library")) + +; foo (:standard -w -declaration-outside-section -w declaration-outside-section))) + +(rule + (alias default) + (action (echo "%{read:base.install}"))) diff --git a/test/blackbox-tests/test-cases/rocq-native/per_file_flags.t/dune-project b/test/blackbox-tests/test-cases/rocq-native/per_file_flags.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/per_file_flags.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/per_file_flags.t/foo.v b/test/blackbox-tests/test-cases/rocq-native/per_file_flags.t/foo.v new file mode 100644 index 00000000000..fb5eea8e22c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/per_file_flags.t/foo.v @@ -0,0 +1,4 @@ +Definition mynat := nat. + +(* This should emit a warning *) +Variable (A : nat). diff --git a/test/blackbox-tests/test-cases/rocq-native/per_file_flags.t/run.t b/test/blackbox-tests/test-cases/rocq-native/per_file_flags.t/run.t new file mode 100644 index 00000000000..e59e72a9c3d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/per_file_flags.t/run.t @@ -0,0 +1,27 @@ + $ dune build --display short @all + rocq .basic.theory.d + rocq Nbasic_foo.{cmi,cmxs},foo.{glob,vo} + File "./foo.v", line 4, characters 0-19: + Warning: Use of "Variable" or "Hypothesis" outside sections behaves as + "#[local] Parameter" or "#[local] Axiom". + [declaration-outside-section,vernacular,default] + rocq Nbasic_bar.{cmi,cmxs},bar.{glob,vo} + + $ dune build --debug-dependency-path @default + lib: [ + "_build/install/default/lib/base/META" + "_build/install/default/lib/base/dune-package" + "_build/install/default/lib/base/opam" + ] + lib_root: [ + "_build/install/default/lib/coq/user-contrib/basic/.coq-native/Nbasic_bar.cmi" {"coq/user-contrib/basic/.coq-native/Nbasic_bar.cmi"} + "_build/install/default/lib/coq/user-contrib/basic/.coq-native/Nbasic_bar.cmxs" {"coq/user-contrib/basic/.coq-native/Nbasic_bar.cmxs"} + "_build/install/default/lib/coq/user-contrib/basic/.coq-native/Nbasic_foo.cmi" {"coq/user-contrib/basic/.coq-native/Nbasic_foo.cmi"} + "_build/install/default/lib/coq/user-contrib/basic/.coq-native/Nbasic_foo.cmxs" {"coq/user-contrib/basic/.coq-native/Nbasic_foo.cmxs"} + "_build/install/default/lib/coq/user-contrib/basic/bar.glob" {"coq/user-contrib/basic/bar.glob"} + "_build/install/default/lib/coq/user-contrib/basic/bar.v" {"coq/user-contrib/basic/bar.v"} + "_build/install/default/lib/coq/user-contrib/basic/bar.vo" {"coq/user-contrib/basic/bar.vo"} + "_build/install/default/lib/coq/user-contrib/basic/foo.glob" {"coq/user-contrib/basic/foo.glob"} + "_build/install/default/lib/coq/user-contrib/basic/foo.v" {"coq/user-contrib/basic/foo.v"} + "_build/install/default/lib/coq/user-contrib/basic/foo.vo" {"coq/user-contrib/basic/foo.vo"} + ] diff --git a/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/dune b/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/dune new file mode 100644 index 00000000000..7c5eb6af132 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/dune @@ -0,0 +1,3 @@ +(rule + (alias default) + (action (echo "%{read:public.install}"))) diff --git a/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/dune-project b/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/private/a.v b/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/private/a.v new file mode 100644 index 00000000000..d4389c6d37d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/private/a.v @@ -0,0 +1 @@ +Definition foo := 3. diff --git a/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/private/dune b/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/private/dune new file mode 100644 index 00000000000..7c4ffcaf0db --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/private/dune @@ -0,0 +1,2 @@ +(rocq.theory + (name private)) diff --git a/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/public.opam b/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/public.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/public/b.v b/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/public/b.v new file mode 100644 index 00000000000..5f955f638da --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/public/b.v @@ -0,0 +1,3 @@ +From private Require a. + +Definition bar := a.foo. diff --git a/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/public/dune b/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/public/dune new file mode 100644 index 00000000000..3df65c46edb --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/public/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name public) + (package public) + (theories private)) diff --git a/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/run.t b/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/run.t new file mode 100644 index 00000000000..5b51afbd263 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/public-dep-on-private.t/run.t @@ -0,0 +1,15 @@ + $ dune build --display short --debug-dependency-path + File "public/dune", line 4, characters 11-18: + 4 | (theories private)) + ^^^^^^^ + Theory "private" is private, it cannot be a dependency of a public theory. + You need to associate "private" to a package. + -> required by theory public in public/dune:2 + -> required by _build/default/public/.public.theory.d + -> required by _build/default/public/Npublic_b.cmi + -> required by + _build/install/default/lib/coq/user-contrib/public/.coq-native/Npublic_b.cmi + -> required by _build/default/public.install + -> required by %{read:public.install} at dune:3 + -> required by alias default in dune:1 + [1] diff --git a/test/blackbox-tests/test-cases/rocq-native/rec-module.t/a/bar.v b/test/blackbox-tests/test-cases/rocq-native/rec-module.t/a/bar.v new file mode 100644 index 00000000000..b1e4f474ced --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/rec-module.t/a/bar.v @@ -0,0 +1,5 @@ +From rec_module Require Import b.foo. +From rec_module Require Import c.ooo. +From rec_module Require c.d.bar. + +Definition mynum (i : mynat) := 3 + ooo_nat + c.d.bar.bar_nat. diff --git a/test/blackbox-tests/test-cases/rocq-native/rec-module.t/b/foo.v b/test/blackbox-tests/test-cases/rocq-native/rec-module.t/b/foo.v new file mode 100644 index 00000000000..53e0ce1b152 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/rec-module.t/b/foo.v @@ -0,0 +1 @@ +Definition mynat := nat. diff --git a/test/blackbox-tests/test-cases/rocq-native/rec-module.t/c/d/bar.v b/test/blackbox-tests/test-cases/rocq-native/rec-module.t/c/d/bar.v new file mode 100644 index 00000000000..b68bd7244fb --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/rec-module.t/c/d/bar.v @@ -0,0 +1 @@ +Definition bar_nat : nat := 4. diff --git a/test/blackbox-tests/test-cases/rocq-native/rec-module.t/c/ooo.v b/test/blackbox-tests/test-cases/rocq-native/rec-module.t/c/ooo.v new file mode 100644 index 00000000000..07d40e56798 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/rec-module.t/c/ooo.v @@ -0,0 +1 @@ +Definition ooo_nat : nat := 10. diff --git a/test/blackbox-tests/test-cases/rocq-native/rec-module.t/dune b/test/blackbox-tests/test-cases/rocq-native/rec-module.t/dune new file mode 100644 index 00000000000..730430b3461 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/rec-module.t/dune @@ -0,0 +1,11 @@ +(rocq.theory + (name rec_module) + (package rec) + (modules :standard) + (synopsis "Test Coq library")) + +(include_subdirs qualified) + +(rule + (alias default) + (action (echo "%{read:rec.install}"))) diff --git a/test/blackbox-tests/test-cases/rocq-native/rec-module.t/dune-project b/test/blackbox-tests/test-cases/rocq-native/rec-module.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/rec-module.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq-native/rec-module.t/rec.opam b/test/blackbox-tests/test-cases/rocq-native/rec-module.t/rec.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq-native/rec-module.t/run.t b/test/blackbox-tests/test-cases/rocq-native/rec-module.t/run.t new file mode 100644 index 00000000000..2860b74c0a9 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/rec-module.t/run.t @@ -0,0 +1,35 @@ + $ dune build --display short --debug-dependency-path @all + rocq .rec_module.theory.d + rocq b/Nrec_module_b_foo.{cmi,cmxs},b/foo.{glob,vo} + rocq c/Nrec_module_c_ooo.{cmi,cmxs},c/ooo.{glob,vo} + rocq c/d/Nrec_module_c_d_bar.{cmi,cmxs},c/d/bar.{glob,vo} + rocq a/Nrec_module_a_bar.{cmi,cmxs},a/bar.{glob,vo} + + $ dune build --debug-dependency-path @default + lib: [ + "_build/install/default/lib/rec/META" + "_build/install/default/lib/rec/dune-package" + "_build/install/default/lib/rec/opam" + ] + lib_root: [ + "_build/install/default/lib/coq/user-contrib/rec_module/a/.coq-native/Nrec_module_a_bar.cmi" {"coq/user-contrib/rec_module/a/.coq-native/Nrec_module_a_bar.cmi"} + "_build/install/default/lib/coq/user-contrib/rec_module/a/.coq-native/Nrec_module_a_bar.cmxs" {"coq/user-contrib/rec_module/a/.coq-native/Nrec_module_a_bar.cmxs"} + "_build/install/default/lib/coq/user-contrib/rec_module/a/bar.glob" {"coq/user-contrib/rec_module/a/bar.glob"} + "_build/install/default/lib/coq/user-contrib/rec_module/a/bar.v" {"coq/user-contrib/rec_module/a/bar.v"} + "_build/install/default/lib/coq/user-contrib/rec_module/a/bar.vo" {"coq/user-contrib/rec_module/a/bar.vo"} + "_build/install/default/lib/coq/user-contrib/rec_module/b/.coq-native/Nrec_module_b_foo.cmi" {"coq/user-contrib/rec_module/b/.coq-native/Nrec_module_b_foo.cmi"} + "_build/install/default/lib/coq/user-contrib/rec_module/b/.coq-native/Nrec_module_b_foo.cmxs" {"coq/user-contrib/rec_module/b/.coq-native/Nrec_module_b_foo.cmxs"} + "_build/install/default/lib/coq/user-contrib/rec_module/b/foo.glob" {"coq/user-contrib/rec_module/b/foo.glob"} + "_build/install/default/lib/coq/user-contrib/rec_module/b/foo.v" {"coq/user-contrib/rec_module/b/foo.v"} + "_build/install/default/lib/coq/user-contrib/rec_module/b/foo.vo" {"coq/user-contrib/rec_module/b/foo.vo"} + "_build/install/default/lib/coq/user-contrib/rec_module/c/.coq-native/Nrec_module_c_ooo.cmi" {"coq/user-contrib/rec_module/c/.coq-native/Nrec_module_c_ooo.cmi"} + "_build/install/default/lib/coq/user-contrib/rec_module/c/.coq-native/Nrec_module_c_ooo.cmxs" {"coq/user-contrib/rec_module/c/.coq-native/Nrec_module_c_ooo.cmxs"} + "_build/install/default/lib/coq/user-contrib/rec_module/c/d/.coq-native/Nrec_module_c_d_bar.cmi" {"coq/user-contrib/rec_module/c/d/.coq-native/Nrec_module_c_d_bar.cmi"} + "_build/install/default/lib/coq/user-contrib/rec_module/c/d/.coq-native/Nrec_module_c_d_bar.cmxs" {"coq/user-contrib/rec_module/c/d/.coq-native/Nrec_module_c_d_bar.cmxs"} + "_build/install/default/lib/coq/user-contrib/rec_module/c/d/bar.glob" {"coq/user-contrib/rec_module/c/d/bar.glob"} + "_build/install/default/lib/coq/user-contrib/rec_module/c/d/bar.v" {"coq/user-contrib/rec_module/c/d/bar.v"} + "_build/install/default/lib/coq/user-contrib/rec_module/c/d/bar.vo" {"coq/user-contrib/rec_module/c/d/bar.vo"} + "_build/install/default/lib/coq/user-contrib/rec_module/c/ooo.glob" {"coq/user-contrib/rec_module/c/ooo.glob"} + "_build/install/default/lib/coq/user-contrib/rec_module/c/ooo.v" {"coq/user-contrib/rec_module/c/ooo.v"} + "_build/install/default/lib/coq/user-contrib/rec_module/c/ooo.vo" {"coq/user-contrib/rec_module/c/ooo.vo"} + ] diff --git a/test/blackbox-tests/test-cases/rocq-native/scrub_coq_args.sh b/test/blackbox-tests/test-cases/rocq-native/scrub_coq_args.sh new file mode 100755 index 00000000000..8f4876d0ae0 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq-native/scrub_coq_args.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +# This script is used for scrubbing the output of Dune actions calling Coq +# binaries. It contains some common patterns which are scurbbed for any +# non-reproducible paths and the arguments are displayed line by line. + +# \f (form feed) is used as a delayed new line for sed + +sed 's/$ (cd .*coqc/coqc/' $1 | # cleanup coqc +sed 's/$ (cd .*coqdep/coqdep/' | # cleanup coqdep +sed 's/$ (cd .*coqdoc/coqdoc/' | # cleanup coqdoc +sed 's/$ (cd .*rocq compile/rocq compile/' $1 | # cleanup coqc +sed 's/$ (cd .*rocq dep/rocq dep/' $1 | # cleanup coqc +sed 's/)//' | # remove trailing ) +sed 's/ -I/\f-I/g' | # new line for each -I +sed 's/ -nI/\f-nI/g' | # new line for each -nI +sed 's/ -R/\f-R/g' | # new line for each -R +sed 's/ -Q/\f-Q/g' | # new line for each -Q +sed 's/ -w/\f-w/g' | # new line for each -w +sed 's/ -boot/\f-boot/g' | # new line for each -boot +sed 's/ -native-compiler /\f-native-compiler /g' | # new line for each -native-compiler +sed 's/-R [^[:space:]]*coq /-R coq /g' | # scrub -R with coq +sed 's#-R [^[:space:]]*coq/theories #-R coq/theories #g' | # scrub -R with coq/theories +sed 's/-I [-A-Za-z0-9\/_\.]*lib\//-I lib\//g' | # scrub -I with lib/ +sed 's/-nI [-A-Za-z0-9\/_\.]*lib\//-nI lib\//g' | # scrub -nI with lib/ +sed 's/\(-R [^\f]* [^\f]*\) \(.*\)/\1\f\2/g' | # new line after each -R +sed 's/\(-I lib\/findlib\)\f\(.*\)/\2\f\1/g' | # move lib/findlib to the end +sed 's/\(-I lib\/zarith\)\f\(.*\)/\2\f\1/g' | # move lib/zarith to the end +tr '\f' '\n' # replace form feed with new line diff --git a/test/blackbox-tests/test-cases/rocq/base-unsound.t/bar.v b/test/blackbox-tests/test-cases/rocq/base-unsound.t/bar.v new file mode 100644 index 00000000000..aaaf57b5190 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/base-unsound.t/bar.v @@ -0,0 +1,3 @@ +From basic Require Import foo. + +Definition false : t := t. diff --git a/test/blackbox-tests/test-cases/rocq/base-unsound.t/base.opam b/test/blackbox-tests/test-cases/rocq/base-unsound.t/base.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/base-unsound.t/dune b/test/blackbox-tests/test-cases/rocq/base-unsound.t/dune new file mode 100644 index 00000000000..f11be27b12d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/base-unsound.t/dune @@ -0,0 +1,9 @@ +(rocq.theory + (name basic) + (package base) + (modules :standard) + (synopsis "Test Coq library")) + +(rule + (alias default) + (action (echo "%{read:base.install}"))) diff --git a/test/blackbox-tests/test-cases/rocq/base-unsound.t/dune-project b/test/blackbox-tests/test-cases/rocq/base-unsound.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/base-unsound.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/base-unsound.t/dune-workspace b/test/blackbox-tests/test-cases/rocq/base-unsound.t/dune-workspace new file mode 100644 index 00000000000..98a41b3f6f9 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/base-unsound.t/dune-workspace @@ -0,0 +1,2 @@ +(lang dune 3.21) +(env (unsound (rocq (flags -type-in-type)))) diff --git a/test/blackbox-tests/test-cases/rocq/base-unsound.t/foo.v b/test/blackbox-tests/test-cases/rocq/base-unsound.t/foo.v new file mode 100644 index 00000000000..fea01705199 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/base-unsound.t/foo.v @@ -0,0 +1 @@ +Definition t := Type. \ No newline at end of file diff --git a/test/blackbox-tests/test-cases/rocq/base-unsound.t/run.t b/test/blackbox-tests/test-cases/rocq/base-unsound.t/run.t new file mode 100644 index 00000000000..6c320c0d05c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/base-unsound.t/run.t @@ -0,0 +1,4 @@ + $ dune build --display short --profile unsound --debug-dependency-path @all + rocq .basic.theory.d + rocq foo.{glob,vo} + rocq bar.{glob,vo} diff --git a/test/blackbox-tests/test-cases/rocq/base.t/bar.v b/test/blackbox-tests/test-cases/rocq/base.t/bar.v new file mode 100644 index 00000000000..4627b76131c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/base.t/bar.v @@ -0,0 +1,3 @@ +From basic Require Import foo. + +Definition mynum (i : mynat) := 3. diff --git a/test/blackbox-tests/test-cases/rocq/base.t/base.opam b/test/blackbox-tests/test-cases/rocq/base.t/base.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/base.t/dune b/test/blackbox-tests/test-cases/rocq/base.t/dune new file mode 100644 index 00000000000..f11be27b12d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/base.t/dune @@ -0,0 +1,9 @@ +(rocq.theory + (name basic) + (package base) + (modules :standard) + (synopsis "Test Coq library")) + +(rule + (alias default) + (action (echo "%{read:base.install}"))) diff --git a/test/blackbox-tests/test-cases/rocq/base.t/dune-project b/test/blackbox-tests/test-cases/rocq/base.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/base.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/base.t/foo.v b/test/blackbox-tests/test-cases/rocq/base.t/foo.v new file mode 100644 index 00000000000..53e0ce1b152 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/base.t/foo.v @@ -0,0 +1 @@ +Definition mynat := nat. diff --git a/test/blackbox-tests/test-cases/rocq/base.t/run.t b/test/blackbox-tests/test-cases/rocq/base.t/run.t new file mode 100644 index 00000000000..58c522f19a4 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/base.t/run.t @@ -0,0 +1,19 @@ + $ dune build --display short --debug-dependency-path @all --always-show-command-line + rocq .basic.theory.d + rocq foo.{glob,vo} + rocq bar.{glob,vo} + + $ dune build --debug-dependency-path @default + lib: [ + "_build/install/default/lib/base/META" + "_build/install/default/lib/base/dune-package" + "_build/install/default/lib/base/opam" + ] + lib_root: [ + "_build/install/default/lib/coq/user-contrib/basic/bar.glob" {"coq/user-contrib/basic/bar.glob"} + "_build/install/default/lib/coq/user-contrib/basic/bar.v" {"coq/user-contrib/basic/bar.v"} + "_build/install/default/lib/coq/user-contrib/basic/bar.vo" {"coq/user-contrib/basic/bar.vo"} + "_build/install/default/lib/coq/user-contrib/basic/foo.glob" {"coq/user-contrib/basic/foo.glob"} + "_build/install/default/lib/coq/user-contrib/basic/foo.v" {"coq/user-contrib/basic/foo.v"} + "_build/install/default/lib/coq/user-contrib/basic/foo.vo" {"coq/user-contrib/basic/foo.vo"} + ] diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/A/A.opam b/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/A/A.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/A/a.v b/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/A/a.v new file mode 100644 index 00000000000..20a65183f49 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/A/a.v @@ -0,0 +1 @@ +Inductive AnotherBeginning := Of | The | Universe. diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/A/dune b/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/A/dune new file mode 100644 index 00000000000..3c8d2133c9d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/A/dune @@ -0,0 +1,5 @@ +(rocq.theory + (name A) + (package A) + (theories B) + (boot)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/A/dune-project b/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/A/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/A/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/B/B.opam b/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/B/B.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/B/b.v b/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/B/b.v new file mode 100644 index 00000000000..4c127dbd6d4 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/B/b.v @@ -0,0 +1 @@ +Inductive Beginning := Of | The | Universe. diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/B/dune b/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/B/dune new file mode 100644 index 00000000000..d6bb1227ed8 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/B/dune @@ -0,0 +1,5 @@ +(rocq.theory + (name B) + (package B)) + + diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/B/dune-project b/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/B/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/B/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/dune-workspace b/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/dune-workspace new file mode 100644 index 00000000000..e1b8e598780 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/dune-workspace @@ -0,0 +1 @@ +(lang dune 3.21) diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/run.t new file mode 100644 index 00000000000..7418f4cec85 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nodeps.t/run.t @@ -0,0 +1,8 @@ +Testing composition with two boot libraries + + $ dune build + File "A/dune", line 4, characters 11-12: + 4 | (theories B) + ^ + Error: (boot) libraries cannot have dependencies + [1] diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/A/A.opam b/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/A/A.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/A/a.v b/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/A/a.v new file mode 100644 index 00000000000..20a65183f49 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/A/a.v @@ -0,0 +1 @@ +Inductive AnotherBeginning := Of | The | Universe. diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/A/dune b/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/A/dune new file mode 100644 index 00000000000..3e9e7f6dc00 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/A/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name A) + (package A) + (boot)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/A/dune-project b/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/A/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/A/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/B/B.opam b/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/B/B.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/B/b.v b/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/B/b.v new file mode 100644 index 00000000000..4c127dbd6d4 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/B/b.v @@ -0,0 +1 @@ +Inductive Beginning := Of | The | Universe. diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/B/dune b/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/B/dune new file mode 100644 index 00000000000..6dbd0135d0c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/B/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name B) + (package B) + (boot)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/B/dune-project b/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/B/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/B/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/dune-workspace b/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/dune-workspace new file mode 100644 index 00000000000..e1b8e598780 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/dune-workspace @@ -0,0 +1 @@ +(lang dune 3.21) diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/run.t new file mode 100644 index 00000000000..f7e643f09b3 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nodups.t/run.t @@ -0,0 +1,8 @@ +Testing composition with two boot libraries + + $ dune build + Error: Cannot have more than one boot theory in scope: + - A at A/dune:1 + - B at B/dune:1 + -> required by alias default + [1] diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/A/a.v b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/A/a.v new file mode 100644 index 00000000000..13ee8a5b8f4 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/A/a.v @@ -0,0 +1,5 @@ +Fail Print Prelude. +From Corelib Require Import Prelude. +Print Prelude. +Require Import mytheory. +Check Hello. diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/A/dune b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/A/dune new file mode 100644 index 00000000000..d872b235fa9 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/A/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name A) + (stdlib no) + (theories Corelib)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/A/dune-project b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/A/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/A/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/B/b.v b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/B/b.v new file mode 100644 index 00000000000..b0165e09243 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/B/b.v @@ -0,0 +1,3 @@ +Print Prelude. +Require Import mytheory. +Check Hello. diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/B/dune b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/B/dune new file mode 100644 index 00000000000..74121db1340 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/B/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name B) + (stdlib yes) + (theories Corelib)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/B/dune-project b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/B/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/B/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/Coq/Coq.opam b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/Coq/Coq.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/Coq/Init/Prelude.v b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/Coq/Init/Prelude.v new file mode 100644 index 00000000000..9de480a5ab8 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/Coq/Init/Prelude.v @@ -0,0 +1,2 @@ +Unset Elimination Schemes. +Inductive BootType := boot | type. diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/Coq/dune b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/Coq/dune new file mode 100644 index 00000000000..e6c2c8a6daf --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/Coq/dune @@ -0,0 +1,6 @@ +(rocq.theory + (name Corelib) + (package Coq) + (boot)) + +(include_subdirs qualified) diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/Coq/dune-project b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/Coq/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/Coq/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/Coq/mytheory.v b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/Coq/mytheory.v new file mode 100644 index 00000000000..831752c569d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/Coq/mytheory.v @@ -0,0 +1,2 @@ + +Inductive Hello := World | Bye. diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/dune-workspace b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/dune-workspace new file mode 100644 index 00000000000..e1b8e598780 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/dune-workspace @@ -0,0 +1 @@ +(lang dune 3.21) diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/run.t new file mode 100644 index 00000000000..c1ec6b509dd --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-nostdlib.t/run.t @@ -0,0 +1,20 @@ +Testing composition of theories across a Dune workspace with a boot library and +importing ``corelib`` enabled or disabled. + +Composing library A depending on Coq but having `(stdlib no)`: + + $ dune build A + Module + Prelude + := Struct Inductive BootType : Set := boot : BootType | type : BootType. End + Hello + : Set + +Composing library B depending on Coq but having `(stdlib yes)`: + + $ dune build B + Module + Prelude + := Struct Inductive BootType : Set := boot : BootType | type : BootType. End + Hello + : Set diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/Coq/coq-boot.opam b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/Coq/coq-boot.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/Coq/dune-project b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/Coq/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/Coq/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/Coq/plugins/boot_plugin.mlpack b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/Coq/plugins/boot_plugin.mlpack new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/Coq/plugins/dune b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/Coq/plugins/dune new file mode 100644 index 00000000000..c9a2d0618ba --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/Coq/plugins/dune @@ -0,0 +1,4 @@ +(library + (name boot_plugin) + (public_name coq-boot.boot_plugin)) + diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/Coq/plugins/main.ml b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/Coq/plugins/main.ml new file mode 100644 index 00000000000..752bae9ceed --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/Coq/plugins/main.ml @@ -0,0 +1 @@ +let () = Format.eprintf "plugin loaded@\n%!" diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/Coq/theories/Init/Prelude.v b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/Coq/theories/Init/Prelude.v new file mode 100644 index 00000000000..0ac0180df80 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/Coq/theories/Init/Prelude.v @@ -0,0 +1,2 @@ +Declare ML Module "coq-boot.boot_plugin". +Inductive AnotherBeginning := Of | The | Universe. diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/Coq/theories/dune b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/Coq/theories/dune new file mode 100644 index 00000000000..7c58337a68a --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/Coq/theories/dune @@ -0,0 +1,7 @@ +(rocq.theory + (name Coq) + (boot) + (package coq-boot) + (plugins coq-boot.boot_plugin)) + +(include_subdirs qualified) diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/User/coq-user.opam b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/User/coq-user.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/User/dune b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/User/dune new file mode 100644 index 00000000000..417d6e9428f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/User/dune @@ -0,0 +1,5 @@ +(rocq.theory + (name User) + (package coq-user)) + + diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/User/dune-project b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/User/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/User/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/User/user.v b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/User/user.v new file mode 100644 index 00000000000..7ae6d680982 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/User/user.v @@ -0,0 +1 @@ +Definition from_boot : AnotherBeginning := Universe. diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/dune-workspace b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/dune-workspace new file mode 100644 index 00000000000..e1b8e598780 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/dune-workspace @@ -0,0 +1 @@ +(lang dune 3.21) diff --git a/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/run.t new file mode 100644 index 00000000000..3d8759752c3 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-boot-plugins.t/run.t @@ -0,0 +1,5 @@ +Testing composition with a boot library with plugins + + $ dune build + plugin loaded + plugin loaded diff --git a/test/blackbox-tests/test-cases/rocq/compose-cycle.t/A/a.v b/test/blackbox-tests/test-cases/rocq/compose-cycle.t/A/a.v new file mode 100644 index 00000000000..d4389c6d37d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-cycle.t/A/a.v @@ -0,0 +1 @@ +Definition foo := 3. diff --git a/test/blackbox-tests/test-cases/rocq/compose-cycle.t/A/dune b/test/blackbox-tests/test-cases/rocq/compose-cycle.t/A/dune new file mode 100644 index 00000000000..ca33704ba50 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-cycle.t/A/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name A) + (theories B)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-cycle.t/B/b.v b/test/blackbox-tests/test-cases/rocq/compose-cycle.t/B/b.v new file mode 100644 index 00000000000..e184683b4d4 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-cycle.t/B/b.v @@ -0,0 +1,3 @@ +From a Require Import a. + +Definition bar := a.foo. diff --git a/test/blackbox-tests/test-cases/rocq/compose-cycle.t/B/dune b/test/blackbox-tests/test-cases/rocq/compose-cycle.t/B/dune new file mode 100644 index 00000000000..54c3c6cc96f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-cycle.t/B/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name B) + (theories A)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-cycle.t/dune-project b/test/blackbox-tests/test-cases/rocq/compose-cycle.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-cycle.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-cycle.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-cycle.t/run.t new file mode 100644 index 00000000000..c84bcb5e2ea --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-cycle.t/run.t @@ -0,0 +1,10 @@ +We check cycles are detected + $ dune build + Error: Dependency cycle between: + theory A in A/dune:2 + -> theory B in B/dune:2 + -> theory A in A/dune:2 + -> required by _build/default/A/.A.theory.d + -> required by alias A/all + -> required by alias default + [1] diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-compat.t/A/a.v b/test/blackbox-tests/test-cases/rocq/compose-installed-compat.t/A/a.v new file mode 100644 index 00000000000..ebcb8bf8f39 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-compat.t/A/a.v @@ -0,0 +1,2 @@ +From B Require Import b. +Print hello. diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-compat.t/A/dune b/test/blackbox-tests/test-cases/rocq/compose-installed-compat.t/A/dune new file mode 100644 index 00000000000..52a9f05b182 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-compat.t/A/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name A) + (theories Corelib B)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-compat.t/A/dune-project b/test/blackbox-tests/test-cases/rocq/compose-installed-compat.t/A/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-compat.t/A/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-compat.t/B/b.v b/test/blackbox-tests/test-cases/rocq/compose-installed-compat.t/B/b.v new file mode 100644 index 00000000000..858e4927197 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-compat.t/B/b.v @@ -0,0 +1 @@ +Inductive hello := I | am | an | install | loc. \ No newline at end of file diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-compat.t/B/dune b/test/blackbox-tests/test-cases/rocq/compose-installed-compat.t/B/dune new file mode 100644 index 00000000000..904c3119b45 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-compat.t/B/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name B) + (package B) + (theories Corelib)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-compat.t/B/dune-project b/test/blackbox-tests/test-cases/rocq/compose-installed-compat.t/B/dune-project new file mode 100644 index 00000000000..1145d420f9a --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-compat.t/B/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) +(using rocq 0.11) +(package (name "B")) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-compat.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-installed-compat.t/run.t new file mode 100644 index 00000000000..d4242d95656 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-compat.t/run.t @@ -0,0 +1,66 @@ +We make sure that Coq lang versions < 0.8 can still somewhat compose with +installed theories. The way this was done before was due to `-boot` not being +passed to Coq. This meant that we essentially have `-Q "" user-contrib` being +passed. In order to restore this behaviour for Coq lang < 0.8 we explicitly add +that flag. This PR makes sure that this is indeed the case. + +We configure ROCQLIB to be lib/coq. Coq will search for user-contrib from here. +We also need to set up a fake Coq install. + + $ mkdir -p lib/coq + $ export ROCQLIB=$PWD/lib/coq + $ echo $ROCQLIB + $TESTCASE_ROOT/lib/coq + + $ mkdir -p lib/coq/theories/Init/ + $ cat > lib/coq/theories/Init/Prelude.v << EOF + > Inductive PreludeLoaded := Yes. + > EOF + +We need to manually compile the prelude. + + $ rocq compile -boot -noinit -w -deprecated-native-compiler-option -w -native-compiler-disabled -native-compiler no -R lib/coq/theories/ Corelib lib/coq/theories/Init/Prelude.v + +We also setup some plugins + + $ mkdir -p lib/rocq-runtime/plugins + +We setup an installed theory. Note that lib/coq/user-contrib doesn't exist yet, +so this also tests that it won't be a problem. + + $ dune build --root B @install + Entering directory 'B' + Leaving directory 'B' + $ dune install --root B --prefix=$PWD --display=short + Installing $TESTCASE_ROOT/lib/B/META + Installing $TESTCASE_ROOT/lib/B/dune-package + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.glob + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.v + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.vo + + +Next we go into our Dune project and build it. + $ dune build --root A + Entering directory 'A' + Inductive hello : Set := + I : hello | am : hello | an : hello | install : hello | loc : hello. + Leaving directory 'A' + +Now we check the flags that were passed to coqdep and coqc: + + $ tail -4 A/_build/log | head -2 | ../scrub_coq_args.sh + rocq dep + -boot + -R coq/theories Corelib + -Q $TESTCASE_ROOT/lib/coq/user-contrib/B B + -R . A -dyndep opt -vos a.v > + _build/default/.A.theory.d + rocq compile -q + -w -deprecated-native-compiler-option + -w -native-compiler-disabled + -native-compiler ondemand + -boot + -R coq/theories Corelib + -Q $TESTCASE_ROOT/lib/coq/user-contrib/B B + -R . A + a.v diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/run.t new file mode 100644 index 00000000000..e191ff85f8e --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/run.t @@ -0,0 +1,16 @@ +Test for https://github.com/ocaml/dune/issues/7893 +When using an installed theory with plugins, things should work fine. + + $ dune build --root to_install @all + Entering directory 'to_install' + Hello + Leaving directory 'to_install' + $ dune install --root to_install --prefix=$PWD + +We now build the normal theory, and should work + + $ OCAMLPATH=$PWD/lib/:$OCAMLPATH + $ ROCQPATH=$PWD/lib/coq/user-contrib dune build --root user @all + Entering directory 'user' + Hello + Leaving directory 'user' diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/to_install/dune-project b/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/to_install/dune-project new file mode 100644 index 00000000000..299d0a78b50 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/to_install/dune-project @@ -0,0 +1,4 @@ +(lang dune 3.21) +(using rocq 0.11) + +(package (name global)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/to_install/plugin/dune b/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/to_install/plugin/dune new file mode 100644 index 00000000000..b4f00a05cac --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/to_install/plugin/dune @@ -0,0 +1,3 @@ +(library + (name plugin) + (public_name global.plugin)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/to_install/plugin/p.ml b/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/to_install/plugin/p.ml new file mode 100644 index 00000000000..59969919305 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/to_install/plugin/p.ml @@ -0,0 +1 @@ +let () = Format.eprintf "Hello@\n%!" diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/to_install/plugin/plugin.mlpack b/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/to_install/plugin/plugin.mlpack new file mode 100644 index 00000000000..8d1c8b69c3f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/to_install/plugin/plugin.mlpack @@ -0,0 +1 @@ + diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/to_install/theory/bar.v b/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/to_install/theory/bar.v new file mode 100644 index 00000000000..9cfccc150ad --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/to_install/theory/bar.v @@ -0,0 +1 @@ +Declare ML Module "global.plugin". diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/to_install/theory/dune b/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/to_install/theory/dune new file mode 100644 index 00000000000..56112559506 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/to_install/theory/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name Bar) + (package global) + (plugins global.plugin)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/user/bar.v b/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/user/bar.v new file mode 100644 index 00000000000..eb3f6b7e435 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/user/bar.v @@ -0,0 +1 @@ +From Bar Require Import bar. diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/user/dune b/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/user/dune new file mode 100644 index 00000000000..e3459eaddcf --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/user/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name Foo) + (package local) + (theories Bar)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/user/dune-project b/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/user/dune-project new file mode 100644 index 00000000000..12e7aaa0287 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-plugin.t/user/dune-project @@ -0,0 +1,4 @@ +(lang dune 3.21) +(using rocq 0.11) + +(package (name local)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-prefix-dupe.t/B/a.v b/test/blackbox-tests/test-cases/rocq/compose-installed-prefix-dupe.t/B/a.v new file mode 100644 index 00000000000..07bf8ad935c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-prefix-dupe.t/B/a.v @@ -0,0 +1 @@ +Inductive b := . \ No newline at end of file diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-prefix-dupe.t/B/dune b/test/blackbox-tests/test-cases/rocq/compose-installed-prefix-dupe.t/B/dune new file mode 100644 index 00000000000..3e4eb6dadb8 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-prefix-dupe.t/B/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name A.B) + (package Theory1)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-prefix-dupe.t/B/dune-project b/test/blackbox-tests/test-cases/rocq/compose-installed-prefix-dupe.t/B/dune-project new file mode 100644 index 00000000000..60e993c14e4 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-prefix-dupe.t/B/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) +(using rocq 0.11) +(package (name Theory1)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-prefix-dupe.t/C/a.v b/test/blackbox-tests/test-cases/rocq/compose-installed-prefix-dupe.t/C/a.v new file mode 100644 index 00000000000..761e6637d52 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-prefix-dupe.t/C/a.v @@ -0,0 +1 @@ +Inductive c := . \ No newline at end of file diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-prefix-dupe.t/C/dune b/test/blackbox-tests/test-cases/rocq/compose-installed-prefix-dupe.t/C/dune new file mode 100644 index 00000000000..b674b7bee50 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-prefix-dupe.t/C/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name A.C) + (package Theory2)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-prefix-dupe.t/C/dune-project b/test/blackbox-tests/test-cases/rocq/compose-installed-prefix-dupe.t/C/dune-project new file mode 100644 index 00000000000..5b8d04f44dc --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-prefix-dupe.t/C/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) +(using rocq 0.11) +(package (name Theory2)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-prefix-dupe.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-installed-prefix-dupe.t/run.t new file mode 100644 index 00000000000..7e7ff12d658 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-prefix-dupe.t/run.t @@ -0,0 +1,36 @@ +If we have installed theories A.B and A.C then Dune should not complain that A +is a duplicate theory. + +First we install our two theories with the conflicting name prefix. + + $ (cd B && dune build @install && dune install --prefix .) + $ (cd C && dune build @install && dune install --prefix .) + +We add these to ROCQPATH + + $ export ROCQPATH=../B/lib/coq/user-contrib:../C/lib/coq/user-contrib:$ROCQPATH + +Now we create a theory that depends on both + + $ mkdir mytheory && cd mytheory + + $ cat > dune-project << EOF + > (lang dune 3.21) + > (using rocq 0.11) + > EOF + + $ cat > dune << EOF + > (rocq.theory + > (name mytheory) + > (theories A.B A.C)) + > EOF + + $ cat > a.v << EOF + > From A.B Require Import a. + > From A.C Require Import a. + > Print b. + > EOF + + $ dune build a.vo + Inductive b : Prop := . + diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-rebuild.t/A/a.v b/test/blackbox-tests/test-cases/rocq/compose-installed-rebuild.t/A/a.v new file mode 100644 index 00000000000..ebcb8bf8f39 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-rebuild.t/A/a.v @@ -0,0 +1,2 @@ +From B Require Import b. +Print hello. diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-rebuild.t/A/dune b/test/blackbox-tests/test-cases/rocq/compose-installed-rebuild.t/A/dune new file mode 100644 index 00000000000..52a9f05b182 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-rebuild.t/A/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name A) + (theories Corelib B)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-rebuild.t/A/dune-project b/test/blackbox-tests/test-cases/rocq/compose-installed-rebuild.t/A/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-rebuild.t/A/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-rebuild.t/B/dune b/test/blackbox-tests/test-cases/rocq/compose-installed-rebuild.t/B/dune new file mode 100644 index 00000000000..904c3119b45 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-rebuild.t/B/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name B) + (package B) + (theories Corelib)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-rebuild.t/B/dune-project b/test/blackbox-tests/test-cases/rocq/compose-installed-rebuild.t/B/dune-project new file mode 100644 index 00000000000..1145d420f9a --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-rebuild.t/B/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) +(using rocq 0.11) +(package (name "B")) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-rebuild.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-installed-rebuild.t/run.t new file mode 100644 index 00000000000..8b78744b7fe --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-rebuild.t/run.t @@ -0,0 +1,109 @@ +We test that installed Coq theories, when updated, prompt Dune to rebuild + + $ mkdir -p lib/coq + $ export ROCQLIB=$PWD/lib/coq + $ echo $ROCQLIB + $TESTCASE_ROOT/lib/coq + + $ mkdir -p lib/coq/theories/Init/ + $ cat > lib/coq/theories/Init/Prelude.v << EOF + > Inductive PreludeLoaded := Yes. + > EOF + +We need to manually compile the prelude. + + $ rocq compile -boot -noinit -w -deprecated-native-compiler-option -w -native-compiler-disabled -native-compiler no -R lib/coq/theories/ Corelib lib/coq/theories/Init/Prelude.v + +We also setup some plugins + + $ mkdir -p lib/rocq-runtime/plugins + +We setup an installed theory. Note that lib/coq/user-contrib doesn't exist yet, +so this also tests that it won't be a problem. + + $ cat > B/b.v << EOF + > Inductive hello := I | am | an | install | loc. + > EOF + + $ dune build --root B @install + Entering directory 'B' + Leaving directory 'B' + $ dune install --root B --prefix=$PWD --display=short + Installing $TESTCASE_ROOT/lib/B/META + Installing $TESTCASE_ROOT/lib/B/dune-package + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.glob + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.v + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.vo + + +Next we go into our Dune project and build it. + $ dune build --root A + Entering directory 'A' + Inductive hello : Set := + I : hello | am : hello | an : hello | install : hello | loc : hello. + Leaving directory 'A' + +Next we update B and install it again. + + $ cat > B/b.v << EOF + > Inductive hello := I | am | an | install | loc | but | updated. + > EOF + + $ dune build --root B @install + Entering directory 'B' + Leaving directory 'B' + $ dune install --root B --prefix=$PWD --display=short + Deleting $TESTCASE_ROOT/lib/B/META + Installing $TESTCASE_ROOT/lib/B/META + Deleting $TESTCASE_ROOT/lib/B/dune-package + Installing $TESTCASE_ROOT/lib/B/dune-package + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/b.glob + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.glob + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/b.v + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.v + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/b.vo + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.vo + +Now we should see that A is rebuilt + + $ dune build --root A + Entering directory 'A' + Inductive hello : Set := + I : hello + | am : hello + | an : hello + | install : hello + | loc : hello + | but : hello + | updated : hello. + Leaving directory 'A' + +Next we add a new file to B that should cause a call to coqdep, but no rebuild. + + $ cat > B/c.v << EOF + > Inductive bye := I | am | a | new | install | loc. + > EOF + + $ dune build --root B @install + Entering directory 'B' + Leaving directory 'B' + $ dune install --root B --prefix=$PWD --display=short + Deleting $TESTCASE_ROOT/lib/B/META + Installing $TESTCASE_ROOT/lib/B/META + Deleting $TESTCASE_ROOT/lib/B/dune-package + Installing $TESTCASE_ROOT/lib/B/dune-package + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/b.glob + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.glob + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/b.v + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.v + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/b.vo + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.vo + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/c.glob + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/c.v + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/c.vo + +Now we should see that A is not rebuilt, however coqdep is called, this seems to fail + + $ dune build --root A --display=short + Entering directory 'A' + Leaving directory 'A' diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-stdlib.t/dune-project b/test/blackbox-tests/test-cases/rocq/compose-installed-stdlib.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-stdlib.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-stdlib.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-installed-stdlib.t/run.t new file mode 100644 index 00000000000..53093316cbf --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-stdlib.t/run.t @@ -0,0 +1,11 @@ +Testing the composition of the installed stdlib + + $ cat > dune << EOF + > (rocq.theory + > (name test) + > (theories Corelib)) + > EOF + + $ dune build test.vo --display=short --always-show-command-line + rocq .test.theory.d + rocq test.{glob,vo} diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-stdlib.t/test.v b/test/blackbox-tests/test-cases/rocq/compose-installed-stdlib.t/test.v new file mode 100644 index 00000000000..a8d287ba538 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-stdlib.t/test.v @@ -0,0 +1 @@ +From Corelib Require Import Classes.Init. diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/global/algebra/b_alg.v b/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/global/algebra/b_alg.v new file mode 100644 index 00000000000..ca9bc124d7d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/global/algebra/b_alg.v @@ -0,0 +1 @@ +Inductive hello_alg := I | am | an | install | loc | at_alg. diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/global/algebra/dune b/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/global/algebra/dune new file mode 100644 index 00000000000..65e6a102e73 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/global/algebra/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name global.algebra) + (package global)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/global/dune-project b/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/global/dune-project new file mode 100644 index 00000000000..1693895f8bb --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/global/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) +(using rocq 0.11) +(package (name "global")) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/global/field/b_field.v b/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/global/field/b_field.v new file mode 100644 index 00000000000..2e219771088 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/global/field/b_field.v @@ -0,0 +1 @@ +Inductive hello_field := I | am | an | install | loc | at_field. diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/global/field/dune b/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/global/field/dune new file mode 100644 index 00000000000..e4d81b8048c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/global/field/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name global.field) + (package global)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/run.t new file mode 100644 index 00000000000..066b4f1a4e4 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/run.t @@ -0,0 +1,197 @@ +We test composing a project with an installed Coq theory. The installed theory +does *not* have to be a dune project. But for the purpose of this test, we use +the installation of a Dune project. + +We configure ROCQLIB to be lib/coq. Coq will search for user-contrib from here. +We also need to set up a fake Coq install. + + $ mkdir -p lib/coq + $ export ROCQLIB=$PWD/lib/coq + $ echo $ROCQLIB + $TESTCASE_ROOT/lib/coq + + $ mkdir -p lib/coq/theories/Init/ + $ cat > lib/coq/theories/Init/Prelude.v << EOF + > Inductive PreludeLoaded := Yes. + > EOF + +We need to manually compile the prelude. + + $ rocq compile -boot -noinit -w -deprecated-native-compiler-option -w -native-compiler-disabled -native-compiler no -R lib/coq/theories/ Corelib lib/coq/theories/Init/Prelude.v + +We also setup some plugins + + $ mkdir -p lib/rocq-runtime/plugins + +Setting up a subdirectory theory: + + $ cat > user/dune << EOF + > (rocq.theory + > (name user) + > (theories global.field global.algebra)) + > EOF + +We setup an installed theory. Note that lib/coq/user-contrib doesn't exist yet, +so this also tests that it won't be a problem. + + $ dune build --root global @install + Entering directory 'global' + Leaving directory 'global' + $ dune install --root global --prefix=$PWD --display=short + Installing $TESTCASE_ROOT/lib/global/META + Installing $TESTCASE_ROOT/lib/global/dune-package + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/b_alg.glob + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/b_alg.v + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/b_alg.vo + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/field/b_field.glob + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/field/b_field.v + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/field/b_field.vo + + +Next we go into our Dune project and build it. + $ dune build --root user + Entering directory 'user' + Inductive hello_alg : Set := + I : hello_alg + | am : hello_alg + | an : hello_alg + | install : hello_alg + | loc : hello_alg + | at_alg : hello_alg. + Inductive hello_field : Set := + I : hello_field + | am : hello_field + | an : hello_field + | install : hello_field + | loc : hello_field + | at_field : hello_field. + Leaving directory 'user' + +Next we uninstall B from the standard location, user-contrib, and install it +somewhere else. + $ dune uninstall --root global --prefix=$PWD --display=short + Deleting $TESTCASE_ROOT/lib/global/META + Deleting $TESTCASE_ROOT/lib/global/dune-package + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/b_alg.glob + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/b_alg.v + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/b_alg.vo + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/global/field/b_field.glob + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/global/field/b_field.v + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/global/field/b_field.vo + Deleting empty directory $TESTCASE_ROOT/lib/global + Deleting empty directory $TESTCASE_ROOT/lib/coq/user-contrib/global/field + Deleting empty directory $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra + + $ dune install --root global --prefix=$PWD/another-place --display=short + Installing $TESTCASE_ROOT/another-place/lib/global/META + Installing $TESTCASE_ROOT/another-place/lib/global/dune-package + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/global/algebra/b_alg.glob + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/global/algebra/b_alg.v + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/global/algebra/b_alg.vo + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/global/field/b_field.glob + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/global/field/b_field.v + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/global/field/b_field.vo + $ rmdir lib/coq/user-contrib/global + +As expected, Dune can no longer build A: + + $ dune build --root user + Entering directory 'user' + File "dune", line 3, characters 11-23: + 3 | (theories global.field global.algebra)) + ^^^^^^^^^^^^ + Theory "global.field" has not been found. + -> required by theory user in dune:2 + -> required by _build/default/.user.theory.d + -> required by alias all + -> required by alias default + Leaving directory 'user' + [1] + +We therefore set a variable called COQPATH which allows for library install +locations alternative to user-contrib. + + $ export ROCQPATH=$PWD/another-place/lib/coq/user-contrib + +Now Dune should be able to build `user` again, since we scan both user-contrib and +all the directories found in ROCQPATH. + + $ dune build --root user + Entering directory 'user' + Inductive hello_alg : Set := + I : hello_alg + | am : hello_alg + | an : hello_alg + | install : hello_alg + | loc : hello_alg + | at_alg : hello_alg. + Inductive hello_field : Set := + I : hello_field + | am : hello_field + | an : hello_field + | install : hello_field + | loc : hello_field + | at_field : hello_field. + Leaving directory 'user' + +We test if having global in the workspace and in user-contrib will cause Dune +any problems. It shouldn't do, as the workspace should take precedence. + + $ dune build user + Inductive hello_alg : Set := + I : hello_alg + | am : hello_alg + | an : hello_alg + | install : hello_alg + | loc : hello_alg + | at_alg : hello_alg. + Inductive hello_field : Set := + I : hello_field + | am : hello_field + | an : hello_field + | install : hello_field + | loc : hello_field + | at_field : hello_field. + +We test updating the dune file for user to use the super-theory works: + + $ cat > user/dune << EOF + > (rocq.theory + > (name user) + > (theories global)) + > EOF + $ dune build --root user + Entering directory 'user' + Inductive hello_alg : Set := + I : hello_alg + | am : hello_alg + | an : hello_alg + | install : hello_alg + | loc : hello_alg + | at_alg : hello_alg. + Inductive hello_field : Set := + I : hello_field + | am : hello_field + | an : hello_field + | install : hello_field + | loc : hello_field + | at_field : hello_field. + Leaving directory 'user' + +We test whether installing `global` again in user-contrib will cause Dune to reject the +build. Currently this is not the case and the first theory is preferred inline +with the loadpath semantics of Coq. + + $ dune install --root global --prefix=$PWD --display=short + Installing $TESTCASE_ROOT/lib/global/META + Installing $TESTCASE_ROOT/lib/global/dune-package + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/b_alg.glob + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/b_alg.v + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/algebra/b_alg.vo + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/field/b_field.glob + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/field/b_field.v + Installing $TESTCASE_ROOT/lib/coq/user-contrib/global/field/b_field.vo + + $ dune build --root user + Entering directory 'user' + Leaving directory 'user' diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/user/a.v b/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/user/a.v new file mode 100644 index 00000000000..50d248ca6d3 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/user/a.v @@ -0,0 +1,3 @@ +From global Require Import b_alg b_field. +Print hello_alg. +Print hello_field. diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/user/dune-project b/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/user/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed-sub.t/user/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed.t/A/a.v b/test/blackbox-tests/test-cases/rocq/compose-installed.t/A/a.v new file mode 100644 index 00000000000..ebcb8bf8f39 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed.t/A/a.v @@ -0,0 +1,2 @@ +From B Require Import b. +Print hello. diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed.t/A/dune b/test/blackbox-tests/test-cases/rocq/compose-installed.t/A/dune new file mode 100644 index 00000000000..52a9f05b182 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed.t/A/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name A) + (theories Corelib B)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed.t/A/dune-project b/test/blackbox-tests/test-cases/rocq/compose-installed.t/A/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed.t/A/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed.t/B/b.v b/test/blackbox-tests/test-cases/rocq/compose-installed.t/B/b.v new file mode 100644 index 00000000000..858e4927197 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed.t/B/b.v @@ -0,0 +1 @@ +Inductive hello := I | am | an | install | loc. \ No newline at end of file diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed.t/B/dune b/test/blackbox-tests/test-cases/rocq/compose-installed.t/B/dune new file mode 100644 index 00000000000..904c3119b45 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed.t/B/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name B) + (package B) + (theories Corelib)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed.t/B/dune-project b/test/blackbox-tests/test-cases/rocq/compose-installed.t/B/dune-project new file mode 100644 index 00000000000..1145d420f9a --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed.t/B/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) +(using rocq 0.11) +(package (name "B")) diff --git a/test/blackbox-tests/test-cases/rocq/compose-installed.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-installed.t/run.t new file mode 100644 index 00000000000..7aa1cb23640 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-installed.t/run.t @@ -0,0 +1,114 @@ +We test composing a project with an installed Coq theory. The installed theory +does *not* have to be a dune project. But for the purpose of this test, we use +the installation of a Dune project. + +We configure ROCQLIB to be lib/coq. Coq will search for user-contrib from here. +We also need to set up a fake Coq install. + + $ mkdir -p lib/coq + $ export ROCQLIB=$PWD/lib/coq + $ echo $ROCQLIB + $TESTCASE_ROOT/lib/coq + + $ mkdir -p lib/coq/theories/Init/ + $ cat > lib/coq/theories/Init/Prelude.v << EOF + > Inductive PreludeLoaded := Yes. + > EOF + +We need to manually compile the prelude. + + $ rocq compile -boot -noinit -w -deprecated-native-compiler-option -w -native-compiler-disabled -native-compiler no -R lib/coq/theories/ Corelib lib/coq/theories/Init/Prelude.v + +We also setup some plugins + + $ mkdir -p lib/rocq-runtime/plugins + +We setup an installed theory. Note that lib/coq/user-contrib doesn't exist yet, +so this also tests that it won't be a problem. + + $ dune build --root B @install + Entering directory 'B' + Leaving directory 'B' + $ dune install --root B --prefix=$PWD --display=short + Installing $TESTCASE_ROOT/lib/B/META + Installing $TESTCASE_ROOT/lib/B/dune-package + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.glob + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.v + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.vo + + +Next we go into our Dune project and build it. + $ dune build --root A + Entering directory 'A' + Inductive hello : Set := + I : hello | am : hello | an : hello | install : hello | loc : hello. + Leaving directory 'A' + +Next we uninstall B from the standard location, user-contrib, and install it +somewhere else. + $ dune uninstall --root B --prefix=$PWD --display=short + Deleting $TESTCASE_ROOT/lib/B/META + Deleting $TESTCASE_ROOT/lib/B/dune-package + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/b.glob + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/b.v + Deleting $TESTCASE_ROOT/lib/coq/user-contrib/B/b.vo + Deleting empty directory $TESTCASE_ROOT/lib/coq/user-contrib/B + Deleting empty directory $TESTCASE_ROOT/lib/B + + $ dune install --root B --prefix=$PWD/another-place --display=short + Installing $TESTCASE_ROOT/another-place/lib/B/META + Installing $TESTCASE_ROOT/another-place/lib/B/dune-package + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/B/b.glob + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/B/b.v + Installing $TESTCASE_ROOT/another-place/lib/coq/user-contrib/B/b.vo + +As expected, Dune can no longer build A: + + $ dune build --root A + Entering directory 'A' + File "dune", line 3, characters 19-20: + 3 | (theories Corelib B)) + ^ + Theory "B" has not been found. + -> required by theory A in dune:2 + -> required by _build/default/.A.theory.d + -> required by alias all + -> required by alias default + Leaving directory 'A' + [1] + +We therefore set a variable called ROCQPATH which allows for library install +locations alternative to user-contrib. + + $ export ROCQPATH=$PWD/another-place/lib/coq/user-contrib + +Now Dune should be able to build A again, since we scan both user-contrib and +all the directories found in ROCQPATH. + + $ dune build --root A + Entering directory 'A' + Inductive hello : Set := + I : hello | am : hello | an : hello | install : hello | loc : hello. + Leaving directory 'A' + +We test if having B in the workspace and in user-contrib will cause Dune +any problems. It shouldn't do, as the workspace should take precedence. + + $ dune build A + Inductive hello : Set := + I : hello | am : hello | an : hello | install : hello | loc : hello. + +We test whether installing B again in user-contrib will cause Dune to reject the +build. Currently this is not the case and the first theory is preferred inline +with the loadpath semantics of Coq. + + $ dune install --root B --prefix=$PWD --display=short + Installing $TESTCASE_ROOT/lib/B/META + Installing $TESTCASE_ROOT/lib/B/dune-package + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.glob + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.v + Installing $TESTCASE_ROOT/lib/coq/user-contrib/B/b.vo + + $ dune build --root A + Entering directory 'A' + Leaving directory 'A' diff --git a/test/blackbox-tests/test-cases/rocq/compose-plugin.t/cplugin.opam b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/cplugin.opam new file mode 100644 index 00000000000..8d1c8b69c3f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/cplugin.opam @@ -0,0 +1 @@ + diff --git a/test/blackbox-tests/test-cases/rocq/compose-plugin.t/dune b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/dune new file mode 100644 index 00000000000..d6032cc01e2 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/dune @@ -0,0 +1,3 @@ +(rule + (alias default) + (action (echo "%{read:cplugin.install}"))) diff --git a/test/blackbox-tests/test-cases/rocq/compose-plugin.t/dune-project b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-plugin.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/run.t new file mode 100644 index 00000000000..cda5721cf90 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/run.t @@ -0,0 +1 @@ + $ dune build @all diff --git a/test/blackbox-tests/test-cases/rocq/compose-plugin.t/src_a/dune b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/src_a/dune new file mode 100644 index 00000000000..e31be8f4210 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/src_a/dune @@ -0,0 +1,7 @@ +(library + (public_name cplugin.ml_plugin_a) + (name ml_plugin_a) + (flags :standard -rectypes) + (libraries rocq-runtime.plugins.ltac)) + +(rocq.pp (modules gram)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-plugin.t/src_a/gram.mlg b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/src_a/gram.mlg new file mode 100644 index 00000000000..f54a2e951fc --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/src_a/gram.mlg @@ -0,0 +1,9 @@ +DECLARE PLUGIN "cplugin.ml_plugin_a" + +{ + +(* We don't use any coqpp specific macros as to make the test more + resilient on different Coq versions *) +let foo = 3 + +} diff --git a/test/blackbox-tests/test-cases/rocq/compose-plugin.t/src_a/gram.mli b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/src_a/gram.mli new file mode 100644 index 00000000000..bcc533d2e62 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/src_a/gram.mli @@ -0,0 +1 @@ +val foo : int diff --git a/test/blackbox-tests/test-cases/rocq/compose-plugin.t/src_a/ml_plugin_a.mlpack b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/src_a/ml_plugin_a.mlpack new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-plugin.t/src_a/simple.ml b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/src_a/simple.ml new file mode 100644 index 00000000000..555166169c9 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/src_a/simple.ml @@ -0,0 +1,2 @@ +let a = 3 +let _ = a diff --git a/test/blackbox-tests/test-cases/rocq/compose-plugin.t/src_b/dune b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/src_b/dune new file mode 100644 index 00000000000..a636d09f518 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/src_b/dune @@ -0,0 +1,5 @@ +(library + (public_name cplugin.ml_plugin_b) + (name ml_plugin_b) + (flags :standard -rectypes) + (libraries ml_plugin_a)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-plugin.t/src_b/ml_plugin_b.mlpack b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/src_b/ml_plugin_b.mlpack new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-plugin.t/src_b/simple_b.ml b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/src_b/simple_b.ml new file mode 100644 index 00000000000..04ea5df11e8 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/src_b/simple_b.ml @@ -0,0 +1 @@ +let _ = Ml_plugin_a.Simple.a diff --git a/test/blackbox-tests/test-cases/rocq/compose-plugin.t/thy1/a.v b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/thy1/a.v new file mode 100644 index 00000000000..e3fcd50627c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/thy1/a.v @@ -0,0 +1,3 @@ +Declare ML Module "cplugin.ml_plugin_a". +Declare ML Module "cplugin.ml_plugin_b". + diff --git a/test/blackbox-tests/test-cases/rocq/compose-plugin.t/thy1/dune b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/thy1/dune new file mode 100644 index 00000000000..b6a90350fe9 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/thy1/dune @@ -0,0 +1,6 @@ +(rocq.theory + (name thy1) + (package cplugin) + (synopsis "Test Plugin") + (plugins cplugin.ml_plugin_b) + (modules :standard)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-plugin.t/thy2/a.v b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/thy2/a.v new file mode 100644 index 00000000000..e3fcd50627c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/thy2/a.v @@ -0,0 +1,3 @@ +Declare ML Module "cplugin.ml_plugin_a". +Declare ML Module "cplugin.ml_plugin_b". + diff --git a/test/blackbox-tests/test-cases/rocq/compose-plugin.t/thy2/dune b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/thy2/dune new file mode 100644 index 00000000000..3ab26c493f3 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-plugin.t/thy2/dune @@ -0,0 +1,6 @@ +(rocq.theory + (name thy2) + (package cplugin) + (synopsis "Test Plugin") + (theories thy1)) + diff --git a/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/A/A.opam b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/A/A.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/A/a.v b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/A/a.v new file mode 100644 index 00000000000..2f7268475b4 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/A/a.v @@ -0,0 +1,3 @@ +From Stdlib Require Import String. +Local Open Scope string_scope. +Definition message := "I am the the private A ". diff --git a/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/A/dune b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/A/dune new file mode 100644 index 00000000000..6cb657fb046 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/A/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name A) + (theories Stdlib)) + diff --git a/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/A_vendored/A.opam b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/A_vendored/A.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/A_vendored/a.v b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/A_vendored/a.v new file mode 100644 index 00000000000..01c353dd662 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/A_vendored/a.v @@ -0,0 +1,3 @@ +From Coq Require Import String. +Local Open Scope string_scope. +Definition message := "I am the vendored A". diff --git a/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/A_vendored/dune b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/A_vendored/dune new file mode 100644 index 00000000000..d157c021eea --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/A_vendored/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name A) + (package A)) + diff --git a/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/A_vendored/dune-project b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/A_vendored/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/A_vendored/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/B/b.v b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/B/b.v new file mode 100644 index 00000000000..7f55442a36c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/B/b.v @@ -0,0 +1,7 @@ +From Stdlib Require Import String. +From A Require Import a. + +Local Open Scope string_scope. + +Print message. + diff --git a/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/B/dune b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/B/dune new file mode 100644 index 00000000000..54c3c6cc96f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/B/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name B) + (theories A)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/C.opam b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/C.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/C/c.v b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/C/c.v new file mode 100644 index 00000000000..daa1e640ee1 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/C/c.v @@ -0,0 +1,7 @@ +From Coq Require Import String. +From A Require Import a. + +Local Open Scope string_scope. + +Print message. + diff --git a/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/C/dune b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/C/dune new file mode 100644 index 00000000000..953bb529c83 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/C/dune @@ -0,0 +1,6 @@ +(rocq.theory + (name C) + (package C) + (theories A)) + + diff --git a/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/dune-project b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/run.t new file mode 100644 index 00000000000..cc55f34adfd --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-private-ambiguous.t/run.t @@ -0,0 +1,16 @@ +We have two theories, A and A_vendored both called A. We test which one a +private plugin B and the public package C will pick up. + +B will pick up the private one: + $ dune build B + message = "I am the the private A " + : string + +C picks up the private one too: + $ dune build C + File "C/dune", line 4, characters 11-12: + 4 | (theories A)) + ^ + Theory "A" is private, it cannot be a dependency of a public theory. You need + to associate "A" to a package. + [1] diff --git a/test/blackbox-tests/test-cases/rocq/compose-private.t/A/A.opam b/test/blackbox-tests/test-cases/rocq/compose-private.t/A/A.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-private.t/A/a.v b/test/blackbox-tests/test-cases/rocq/compose-private.t/A/a.v new file mode 100644 index 00000000000..831752c569d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-private.t/A/a.v @@ -0,0 +1,2 @@ + +Inductive Hello := World | Bye. diff --git a/test/blackbox-tests/test-cases/rocq/compose-private.t/A/dune b/test/blackbox-tests/test-cases/rocq/compose-private.t/A/dune new file mode 100644 index 00000000000..1af0b2ef4c5 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-private.t/A/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name A)) + diff --git a/test/blackbox-tests/test-cases/rocq/compose-private.t/B/b.v b/test/blackbox-tests/test-cases/rocq/compose-private.t/B/b.v new file mode 100644 index 00000000000..5659f2682e6 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-private.t/B/b.v @@ -0,0 +1,4 @@ +From A Require Import a. + +Check Hello. + diff --git a/test/blackbox-tests/test-cases/rocq/compose-private.t/B/dune b/test/blackbox-tests/test-cases/rocq/compose-private.t/B/dune new file mode 100644 index 00000000000..54c3c6cc96f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-private.t/B/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name B) + (theories A)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-private.t/C.opam b/test/blackbox-tests/test-cases/rocq/compose-private.t/C.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-private.t/C/c.v b/test/blackbox-tests/test-cases/rocq/compose-private.t/C/c.v new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-private.t/C/dune b/test/blackbox-tests/test-cases/rocq/compose-private.t/C/dune new file mode 100644 index 00000000000..57073fabdfe --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-private.t/C/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name C) + (package C) + (theories B)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-private.t/dune-project b/test/blackbox-tests/test-cases/rocq/compose-private.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-private.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-private.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-private.t/run.t new file mode 100644 index 00000000000..02db95b3c18 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-private.t/run.t @@ -0,0 +1,13 @@ +Testing composition of theories with two private theories and a third public +theory. As expected, the private theories build, but the public theory fails +because a public theory cannot depend on a private theory. + + $ dune build + Hello + : Set + File "C/dune", line 4, characters 11-12: + 4 | (theories B)) + ^ + Theory "B" is private, it cannot be a dependency of a public theory. You need + to associate "B" to a package. + [1] diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/A/a.v b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/A/a.v new file mode 100644 index 00000000000..953a3b7b657 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/A/a.v @@ -0,0 +1,9 @@ + + +Print Prelude. + +Require Import mytheory. + +Check Hello. + + diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/A/dune b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/A/dune new file mode 100644 index 00000000000..0b2080e1dcb --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/A/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name A) + (theories Coq)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/A/dune-project b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/A/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/A/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/B/Coq/Init/Prelude.v b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/B/Coq/Init/Prelude.v new file mode 100644 index 00000000000..e6778dee030 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/B/Coq/Init/Prelude.v @@ -0,0 +1,2 @@ +Unset Elimination Schemes. +Inductive PrivateBootType := private_boot | private_type. diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/B/Foo.opam b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/B/Foo.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/B/Stuff/b.v b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/B/Stuff/b.v new file mode 100644 index 00000000000..8a23f1a1419 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/B/Stuff/b.v @@ -0,0 +1 @@ +Check private_boot. diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/B/Stuff/dune b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/B/Stuff/dune new file mode 100644 index 00000000000..aae43938a8b --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/B/Stuff/dune @@ -0,0 +1,3 @@ + (rocq.theory + (name B) + (modules b)) \ No newline at end of file diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/B/dune-project b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/B/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/B/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/Coq/Coq.opam b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/Coq/Coq.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/Coq/Init/Prelude.v b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/Coq/Init/Prelude.v new file mode 100644 index 00000000000..9de480a5ab8 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/Coq/Init/Prelude.v @@ -0,0 +1,2 @@ +Unset Elimination Schemes. +Inductive BootType := boot | type. diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/Coq/dune b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/Coq/dune new file mode 100644 index 00000000000..1bc6d233edc --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/Coq/dune @@ -0,0 +1,6 @@ +(rocq.theory + (name Coq) + (package Coq) + (boot)) + +(include_subdirs qualified) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/Coq/dune-project b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/Coq/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/Coq/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/Coq/mytheory.v b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/Coq/mytheory.v new file mode 100644 index 00000000000..831752c569d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/Coq/mytheory.v @@ -0,0 +1,2 @@ + +Inductive Hello := World | Bye. diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/dune-workspace b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/dune-workspace new file mode 100644 index 00000000000..e1b8e598780 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/dune-workspace @@ -0,0 +1 @@ +(lang dune 3.21) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/run.t new file mode 100644 index 00000000000..473e7edf0d8 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-boot.t/run.t @@ -0,0 +1,57 @@ +Testing composition of theories across a dune workspace with a boot library. A +boot library must have the following: + +- Under the module prefix "Coq" +- Have a file Init/Prelude.v + +When composing with a (boot) library, every library must have -boot passed to +coqdep and coqc. + + $ dune build A + Module + Prelude + := Struct Inductive BootType : Set := boot : BootType | type : BootType. End + Hello + : Set + +We can even have a secondary private boot library in another scope and only the +private boot library will be loaded implicitly. + + $ cat > B/Coq/dune << EOF + > (include_subdirs qualified) + > (rocq.theory + > (name Coq) + > (boot)) + > EOF + + $ dune build B + private_boot + : PrivateBootType + +However if this boot library is public Dune will complain + + $ cat > B/Coq/dune << EOF + > (include_subdirs qualified) + > (rocq.theory + > (name Coq) + > (package Foo) + > (boot)) + > EOF + +Due to lazy loading of installed theories, the error messages for having more +than one boot theory is a bit delayed and comes with the multiple rules error +message together. This is some extra noise for the user, but we are not sure how +to fix this currently. + + $ dune build B + Error: Cannot have more than one boot theory in scope: + - Coq at B/Coq/dune:2 + - Coq at Coq/dune:1 + Error: Multiple rules generated for + _build/install/default/lib/coq/theories/Init/Prelude.vo: + - Coq/dune:1 + - B/Coq/dune:2 + -> required by _build/default/B/Foo.install + -> required by alias B/all + -> required by alias B/default + [1] diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/A/A.opam b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/A/A.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/A/a.v b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/A/a.v new file mode 100644 index 00000000000..92d80e770f1 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/A/a.v @@ -0,0 +1,3 @@ +From C Require Import c. + +Inductive Hello := World | Bye. diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/A/dune b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/A/dune new file mode 100644 index 00000000000..48ca4b1c5ef --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/A/dune @@ -0,0 +1,5 @@ +(rocq.theory + (name A) + (package A) + (theories C)) + diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/A/dune-project b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/A/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/A/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/B/B.opam b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/B/B.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/B/b.v b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/B/b.v new file mode 100644 index 00000000000..5659f2682e6 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/B/b.v @@ -0,0 +1,4 @@ +From A Require Import a. + +Check Hello. + diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/B/dune b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/B/dune new file mode 100644 index 00000000000..133d2667222 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/B/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name B) + (package B) + (theories A)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/B/dune-project b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/B/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/B/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/C/C.opam b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/C/C.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/C/c.v b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/C/c.v new file mode 100644 index 00000000000..b68952f12fa --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/C/c.v @@ -0,0 +1 @@ +From B Require Import b. \ No newline at end of file diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/C/dune b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/C/dune new file mode 100644 index 00000000000..82acbc9813b --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/C/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name C) + (package C) + (theories B)) \ No newline at end of file diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/C/dune-project b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/C/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/C/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/dune-workspace b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/dune-workspace new file mode 100644 index 00000000000..e1b8e598780 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/dune-workspace @@ -0,0 +1 @@ +(lang dune 3.21) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/run.t new file mode 100644 index 00000000000..fb7ba84eacb --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-cycle.t/run.t @@ -0,0 +1,35 @@ +Testing composition of theories across a dune workspace with cyclic +dependencies. + + $ dune build A + Error: Dependency cycle between: + theory A in A/dune:2 + -> theory B in B/dune:2 + -> theory C in C/dune:2 + -> theory A in A/dune:2 + -> required by _build/default/A/.A.theory.d + -> required by alias A/all + -> required by alias A/default + [1] + + $ dune build B + Error: Dependency cycle between: + theory B in B/dune:2 + -> theory C in C/dune:2 + -> theory A in A/dune:2 + -> theory B in B/dune:2 + -> required by _build/default/B/.B.theory.d + -> required by alias B/all + -> required by alias B/default + [1] + + $ dune build C + Error: Dependency cycle between: + theory C in C/dune:2 + -> theory A in A/dune:2 + -> theory B in B/dune:2 + -> theory C in C/dune:2 + -> required by _build/default/C/.C.theory.d + -> required by alias C/all + -> required by alias C/default + [1] diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/A/A.opam b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/A/A.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/A/a.v b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/A/a.v new file mode 100644 index 00000000000..831752c569d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/A/a.v @@ -0,0 +1,2 @@ + +Inductive Hello := World | Bye. diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/A/dune b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/A/dune new file mode 100644 index 00000000000..1af0b2ef4c5 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/A/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name A)) + diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/A/dune-project b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/A/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/A/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/B/B.opam b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/B/B.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/B/b.v b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/B/b.v new file mode 100644 index 00000000000..5659f2682e6 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/B/b.v @@ -0,0 +1,4 @@ +From A Require Import a. + +Check Hello. + diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/B/dune b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/B/dune new file mode 100644 index 00000000000..133d2667222 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/B/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name B) + (package B) + (theories A)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/B/dune-project b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/B/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/B/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/C/C.opam b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/C/C.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/C/c.v b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/C/c.v new file mode 100644 index 00000000000..c4484984fbe --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/C/c.v @@ -0,0 +1,2 @@ + +Check bye. diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/C/dune b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/C/dune new file mode 100644 index 00000000000..82acbc9813b --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/C/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name C) + (package C) + (theories B)) \ No newline at end of file diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/C/dune-project b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/C/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/C/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/dune-workspace b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/dune-workspace new file mode 100644 index 00000000000..e1b8e598780 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/dune-workspace @@ -0,0 +1 @@ +(lang dune 3.21) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/run.t new file mode 100644 index 00000000000..dc638a5adcf --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-missing.t/run.t @@ -0,0 +1,14 @@ +Testing composition of theories across a dune workspace with a missing +dependency. + + $ dune build C + File "B/dune", line 4, characters 11-12: + 4 | (theories A)) + ^ + Theory "A" has not been found. + -> required by theory B in B/dune:2 + -> required by theory C in C/dune:2 + -> required by _build/default/C/.C.theory.d + -> required by alias C/all + -> required by alias C/default + [1] diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/A/A.opam b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/A/A.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/A/a.v b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/A/a.v new file mode 100644 index 00000000000..2f7268475b4 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/A/a.v @@ -0,0 +1,3 @@ +From Stdlib Require Import String. +Local Open Scope string_scope. +Definition message := "I am the the private A ". diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/A/dune b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/A/dune new file mode 100644 index 00000000000..cf730129a32 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/A/dune @@ -0,0 +1,5 @@ +(rocq.theory + (name A) + (package A) + (theories Stdlib)) + diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/A/dune-project b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/A/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/A/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/B/B.opam b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/B/B.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/B/b.v b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/B/b.v new file mode 100644 index 00000000000..7f55442a36c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/B/b.v @@ -0,0 +1,7 @@ +From Stdlib Require Import String. +From A Require Import a. + +Local Open Scope string_scope. + +Print message. + diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/B/dune b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/B/dune new file mode 100644 index 00000000000..60dba36a6b2 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/B/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name B) + (package B) + (theories Stdlib)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/B/dune-project b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/B/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/B/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/C/A_vendored/A.opam b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/C/A_vendored/A.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/C/A_vendored/a.v b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/C/A_vendored/a.v new file mode 100644 index 00000000000..d3e54bfe510 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/C/A_vendored/a.v @@ -0,0 +1,4 @@ +From C Require Import A. +From Stdlib Require Import String. +Local Open Scope string_scope. +Definition message := "I am the vendored A". diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/C/A_vendored/dune b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/C/A_vendored/dune new file mode 100644 index 00000000000..bde936c45ac --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/C/A_vendored/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name A) + (theories C)) + diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/C/C.opam b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/C/C.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/C/c.v b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/C/c.v new file mode 100644 index 00000000000..7f55442a36c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/C/c.v @@ -0,0 +1,7 @@ +From Stdlib Require Import String. +From A Require Import a. + +Local Open Scope string_scope. + +Print message. + diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/C/dune b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/C/dune new file mode 100644 index 00000000000..2d9c3a6b0ac --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/C/dune @@ -0,0 +1,6 @@ +(rocq.theory + (name C) + (package C) + (theories B)) + + diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/C/dune-project b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/C/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/C/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/dune-project b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/run.t new file mode 100644 index 00000000000..535b640d207 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects-private-ambiguous.t/run.t @@ -0,0 +1,59 @@ +Testing ambiguous composition of private and public theories + +1. theory `A` is public belonging to `A/dune-project` +2. theory `B` is public belong to `B/dune-project`. +2. theory `C` is public belonging to `C/dune-project` and depends on `B`. +3. theory `A` is private belonging to `C/dune-project` and depends on `C`. + +Currently Dune does not detect this issue, so passes invalid flags to coqdep +which complains. + + $ dune build B + Warning: in file b.v, library a is required + from root A and has not been found in the loadpath! + [module-not-found,filesystem,default] + File "./B/b.v", line 2, characters 22-23: + Error: Cannot find a physical path bound to logical path a with prefix A. + + [1] + + $ dune build C + Warning: in file c.v, library a is required + from root A and has not been found in the loadpath! + [module-not-found,filesystem,default] + Warning: in file a.v, library A is required + from root C and has not been found in the loadpath! + [module-not-found,filesystem,default] + File "./C/c.v", line 2, characters 22-23: + Error: Cannot find a physical path bound to logical path a with prefix A. + + File "C/A_vendored/dune", lines 1-3, characters 0-37: + 1 | (rocq.theory + 2 | (name A) + 3 | (theories C)) + Warning: + $TESTCASE_ROOT/_build/default/C/A_vendored + was previously bound to C.A_vendored; it is remapped to A + [overriding-logical-loadpath,filesystem,default] + File "./C/A_vendored/a.v", line 1, characters 22-23: + Error: Unable to locate library + A with prefix C (while searching for a .vos file). + + [1] + + $ dune build A + + $ dune build C/A_vendored + File "C/A_vendored/dune", lines 1-3, characters 0-37: + 1 | (rocq.theory + 2 | (name A) + 3 | (theories C)) + Warning: + $TESTCASE_ROOT/_build/default/C/A_vendored + was previously bound to C.A_vendored; it is remapped to A + [overriding-logical-loadpath,filesystem,default] + File "./C/A_vendored/a.v", line 1, characters 22-23: + Error: Unable to locate library + A with prefix C (while searching for a .vos file). + + [1] diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects.t/A/A.opam b/test/blackbox-tests/test-cases/rocq/compose-projects.t/A/A.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects.t/A/a.v b/test/blackbox-tests/test-cases/rocq/compose-projects.t/A/a.v new file mode 100644 index 00000000000..831752c569d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects.t/A/a.v @@ -0,0 +1,2 @@ + +Inductive Hello := World | Bye. diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects.t/A/dune b/test/blackbox-tests/test-cases/rocq/compose-projects.t/A/dune new file mode 100644 index 00000000000..d157c021eea --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects.t/A/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name A) + (package A)) + diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects.t/A/dune-project b/test/blackbox-tests/test-cases/rocq/compose-projects.t/A/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects.t/A/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects.t/B/b.v b/test/blackbox-tests/test-cases/rocq/compose-projects.t/B/b.v new file mode 100644 index 00000000000..5659f2682e6 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects.t/B/b.v @@ -0,0 +1,4 @@ +From A Require Import a. + +Check Hello. + diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects.t/B/dune b/test/blackbox-tests/test-cases/rocq/compose-projects.t/B/dune new file mode 100644 index 00000000000..54c3c6cc96f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects.t/B/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name B) + (theories A)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects.t/B/dune-project b/test/blackbox-tests/test-cases/rocq/compose-projects.t/B/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects.t/B/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects.t/dune-workspace b/test/blackbox-tests/test-cases/rocq/compose-projects.t/dune-workspace new file mode 100644 index 00000000000..e1b8e598780 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects.t/dune-workspace @@ -0,0 +1 @@ +(lang dune 3.21) diff --git a/test/blackbox-tests/test-cases/rocq/compose-projects.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-projects.t/run.t new file mode 100644 index 00000000000..0a11ec4c841 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-projects.t/run.t @@ -0,0 +1,10 @@ +Testing composition of theories across a dune workspace + $ dune build B + Hello + : Set + +Inspecting the build directory + $ ls _build/default/A/a.vo + _build/default/A/a.vo + $ ls _build/default/B/b.vo + _build/default/B/b.vo diff --git a/test/blackbox-tests/test-cases/rocq/compose-self.t/A/a.v b/test/blackbox-tests/test-cases/rocq/compose-self.t/A/a.v new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-self.t/A/dune b/test/blackbox-tests/test-cases/rocq/compose-self.t/A/dune new file mode 100644 index 00000000000..aa113db7dcb --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-self.t/A/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name A) + (theories A)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-self.t/dune-project b/test/blackbox-tests/test-cases/rocq/compose-self.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-self.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-self.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-self.t/run.t new file mode 100644 index 00000000000..184472d00eb --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-self.t/run.t @@ -0,0 +1,8 @@ +Composing a theory with itself should cause a cycle + $ dune build + Error: Dependency cycle between: + theory A in A/dune:2 + -> required by _build/default/A/.A.theory.d + -> required by alias A/all + -> required by alias default + [1] diff --git a/test/blackbox-tests/test-cases/rocq/compose-simple.t/A/a.v b/test/blackbox-tests/test-cases/rocq/compose-simple.t/A/a.v new file mode 100644 index 00000000000..d4389c6d37d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-simple.t/A/a.v @@ -0,0 +1 @@ +Definition foo := 3. diff --git a/test/blackbox-tests/test-cases/rocq/compose-simple.t/A/dune b/test/blackbox-tests/test-cases/rocq/compose-simple.t/A/dune new file mode 100644 index 00000000000..e143655924b --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-simple.t/A/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name A) + (package Simple)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-simple.t/B/b.v b/test/blackbox-tests/test-cases/rocq/compose-simple.t/B/b.v new file mode 100644 index 00000000000..951f7a4ee5e --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-simple.t/B/b.v @@ -0,0 +1,3 @@ +From A Require Import a. + +Definition bar := a.foo. diff --git a/test/blackbox-tests/test-cases/rocq/compose-simple.t/B/dune b/test/blackbox-tests/test-cases/rocq/compose-simple.t/B/dune new file mode 100644 index 00000000000..03af3c19575 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-simple.t/B/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name B) + (package Simple) + (theories A)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-simple.t/Simple.opam b/test/blackbox-tests/test-cases/rocq/compose-simple.t/Simple.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-simple.t/dune-project b/test/blackbox-tests/test-cases/rocq/compose-simple.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-simple.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-simple.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-simple.t/run.t new file mode 100644 index 00000000000..b8ceff6e639 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-simple.t/run.t @@ -0,0 +1,15 @@ +Testing a simple composition of theories. We have two theories A and B and B +depends on A. + + $ dune build + +We inspect the contents of the build directory. + + $ ls _build/install/default/lib/coq/user-contrib/A/a.vo + _build/install/default/lib/coq/user-contrib/A/a.vo + $ ls _build/default/A/a.vo + _build/default/A/a.vo + $ ls _build/install/default/lib/coq/user-contrib/B/b.vo + _build/install/default/lib/coq/user-contrib/B/b.vo + $ ls _build/default/B/b.vo + _build/default/B/b.vo diff --git a/test/blackbox-tests/test-cases/rocq/compose-sub-theory.t/A/a.v b/test/blackbox-tests/test-cases/rocq/compose-sub-theory.t/A/a.v new file mode 100644 index 00000000000..d4389c6d37d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-sub-theory.t/A/a.v @@ -0,0 +1 @@ +Definition foo := 3. diff --git a/test/blackbox-tests/test-cases/rocq/compose-sub-theory.t/A/dune b/test/blackbox-tests/test-cases/rocq/compose-sub-theory.t/A/dune new file mode 100644 index 00000000000..49791462120 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-sub-theory.t/A/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name Foo.A) + (package Subtheory)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-sub-theory.t/B/b.v b/test/blackbox-tests/test-cases/rocq/compose-sub-theory.t/B/b.v new file mode 100644 index 00000000000..1379965e9ff --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-sub-theory.t/B/b.v @@ -0,0 +1,3 @@ +From Foo Require Import a. + +Definition bar := a.foo. diff --git a/test/blackbox-tests/test-cases/rocq/compose-sub-theory.t/B/dune b/test/blackbox-tests/test-cases/rocq/compose-sub-theory.t/B/dune new file mode 100644 index 00000000000..f189f584d5b --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-sub-theory.t/B/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name B) + (package Subtheory) + (theories Foo.A)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-sub-theory.t/Subtheory.opam b/test/blackbox-tests/test-cases/rocq/compose-sub-theory.t/Subtheory.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-sub-theory.t/dune-project b/test/blackbox-tests/test-cases/rocq/compose-sub-theory.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-sub-theory.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-sub-theory.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-sub-theory.t/run.t new file mode 100644 index 00000000000..2aa94afdd27 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-sub-theory.t/run.t @@ -0,0 +1,14 @@ +Testing dependencies on subtheories. We have two theories A and B, but A is +defined as Foo.A. This changes the install layout of A. + + $ dune build + +Inspecting the build and install directory + $ ls _build/install/default/lib/coq/user-contrib/Foo/A/a.vo + _build/install/default/lib/coq/user-contrib/Foo/A/a.vo + $ ls _build/default/A/a.vo + _build/default/A/a.vo + $ ls _build/install/default/lib/coq/user-contrib/B/b.vo + _build/install/default/lib/coq/user-contrib/B/b.vo + $ ls _build/default/B/b.vo + _build/default/B/b.vo diff --git a/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/b/b.v b/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/b/b.v new file mode 100644 index 00000000000..e184683b4d4 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/b/b.v @@ -0,0 +1,3 @@ +From a Require Import a. + +Definition bar := a.foo. diff --git a/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/b/dune b/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/b/dune new file mode 100644 index 00000000000..47c7b4c0a05 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/b/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name b) + (package cvendor) + (theories a)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/cvendor.opam b/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/cvendor.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/dune b/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/dune new file mode 100644 index 00000000000..7e780eb3f8e --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/dune @@ -0,0 +1,3 @@ +(rule + (alias default) + (action (echo "%{read:cvendor.install}"))) diff --git a/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/dune-project b/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/run.t b/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/run.t new file mode 100644 index 00000000000..7e1bdeefd3b --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/run.t @@ -0,0 +1,12 @@ + + $ dune build + lib: [ + "_build/install/default/lib/cvendor/META" + "_build/install/default/lib/cvendor/dune-package" + "_build/install/default/lib/cvendor/opam" + ] + lib_root: [ + "_build/install/default/lib/coq/user-contrib/b/b.glob" {"coq/user-contrib/b/b.glob"} + "_build/install/default/lib/coq/user-contrib/b/b.v" {"coq/user-contrib/b/b.v"} + "_build/install/default/lib/coq/user-contrib/b/b.vo" {"coq/user-contrib/b/b.vo"} + ] diff --git a/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/vendor/a/a.v b/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/vendor/a/a.v new file mode 100644 index 00000000000..d4389c6d37d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/vendor/a/a.v @@ -0,0 +1 @@ +Definition foo := 3. diff --git a/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/vendor/a/dune b/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/vendor/a/dune new file mode 100644 index 00000000000..3eb00403877 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/vendor/a/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name a) + (package cvendor2)) diff --git a/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/vendor/cvendor2.opam b/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/vendor/cvendor2.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/vendor/dune-project b/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/vendor/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/compose-two-scopes.t/vendor/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/README.md b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/README.md new file mode 100644 index 00000000000..aed22f27d59 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/README.md @@ -0,0 +1,10 @@ +# Sample dune-coq project + +This is a simple dune build which has 2 projects: + +1. `example-ocaml` - simple pure OCaml library +2. `example-coq` - simple OCaml library extracted from Coq + +In addition to Coq to OCaml extraction, it also demonstrates a +workaround for long-standing Coq [issue](https://github.com/coq/coq/issues/6614) and until it is fixed +could be used as a template for dune projects using Coq extraction. diff --git a/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/Common/Foo.v b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/Common/Foo.v new file mode 100644 index 00000000000..9258a07bbce --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/Common/Foo.v @@ -0,0 +1 @@ +Definition foo (_:unit) : nat := 42. diff --git a/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/Common/dune b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/Common/dune new file mode 100644 index 00000000000..829ce592d76 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/Common/dune @@ -0,0 +1,5 @@ +(rocq.theory + (mode vo) + (name Common) + (package example-coq) + (modules Foo)) diff --git a/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/_CoqProject b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/_CoqProject new file mode 100644 index 00000000000..7911e32ea03 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/_CoqProject @@ -0,0 +1,2 @@ +-R . "" +-R Common/ Common diff --git a/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/dune b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/dune new file mode 100644 index 00000000000..a34f8e633cb --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/dune @@ -0,0 +1,20 @@ +(rule + (deps extracted/CRelationClasses.mli.patch extracted/patch.sh) + (package example-coq) + (target CRelationClasses.mli) + (action + (with-stdout-to + %{target} + (run %{dep:extracted/patch.sh} %{dep:extracted/CRelationClasses.mli})))) + +(copy_files extracted/CRelationClasses.ml) +(copy_files extracted/Datatypes.{ml,mli}) +(copy_files extracted/Foo.{ml,mli}) + +(library + (name extracted) + (public_name example-coq.coq) + (modules (:standard)) + (libraries zarith rocq-runtime.kernel) + (wrapped false) + (flags (:standard -rectypes -w -27-32-33-39-67-37-20-34))) diff --git a/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/extracted/CRelationClasses.mli.patch b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/extracted/CRelationClasses.mli.patch new file mode 100644 index 00000000000..37b58b75bc7 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/extracted/CRelationClasses.mli.patch @@ -0,0 +1,11 @@ +--- ml/extracted/CRelationClasses.mli 2018-10-08 20:41:02.000000000 -0700 ++++ CRelationClasses.mli 2018-10-08 20:41:05.000000000 -0700 +@@ -104,7 +104,7 @@ + val flip_Equivalence : + ('a1, 'a2) coq_Equivalence -> ('a1, 'a2) coq_Equivalence + +-val eq_equivalence : ('a1, __) coq_Equivalence ++val eq_equivalence : (__, __) coq_Equivalence + + val iff_equivalence : (__, __) coq_Equivalence + diff --git a/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/extracted/Extract.v b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/extracted/Extract.v new file mode 100644 index 00000000000..61d1e495ef2 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/extracted/Extract.v @@ -0,0 +1,25 @@ +Require Import Common.Foo. +Require Import Corelib.Classes.CRelationClasses. + +From Corelib Require Extraction. + +From Corelib Require ExtrOcamlBasic. +From Stdlib Require ExtrOcamlChar. +From Stdlib Require ExtrOcamlNativeString. +From Stdlib Require ExtrOCamlFloats. +From Stdlib Require ExtrOCamlInt63. + +From Stdlib Require Import ExtrOcamlNatBigInt. +From Stdlib Require Import ExtrOcamlZBigInt. + +Extraction Language OCaml. +Unset Extraction Optimize. + +Extraction Blacklist String List Char Core Monad Bool Vector Format Nat Int Option Base Numbers FMapAVL OrderedType Map. + +(* Used by Coq's Real library *) +(* Extract Constant ClassicalDedekindReals.sig_forall_dec => "fun _ -> assert false". *) +(* Extract Constant ClassicalDedekindReals.sig_not_dec => false. (\* Ugh *\) *) + +Recursive Extraction Library Foo. +Recursive Extraction Library CRelationClasses. diff --git a/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/extracted/dune b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/extracted/dune new file mode 100644 index 00000000000..aa011f037e0 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/extracted/dune @@ -0,0 +1,8 @@ +(rocq.extraction + (mode vo) + (prelude Extract) + (extracted_modules Foo CRelationClasses Datatypes) + (flags :standard -w -extraction-default-directory -w -extraction-opaque-accessed) + (theories Stdlib Common)) + + diff --git a/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/extracted/patch.sh b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/extracted/patch.sh new file mode 100755 index 00000000000..f835d7ce8ae --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/coq/extracted/patch.sh @@ -0,0 +1,3 @@ +#!/bin/sh +patch -p0 -r 0 -s --read-only=ignore --follow-symlinks -o - $1 -i extracted/CRelationClasses.mli.patch + diff --git a/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/dune b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/dune new file mode 100644 index 00000000000..ff44ed00399 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/dune @@ -0,0 +1,3 @@ +(dirs coq ml) + + diff --git a/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/dune-project b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/dune-project new file mode 100644 index 00000000000..7c2c1d35e22 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) +(name example) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/example-coq.opam b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/example-coq.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/example-ocaml.opam b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/example-ocaml.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/ml/bar.ml b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/ml/bar.ml new file mode 100644 index 00000000000..281680fe3f6 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/ml/bar.ml @@ -0,0 +1 @@ +let bar (_:unit) = 24 diff --git a/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/ml/dune b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/ml/dune new file mode 100644 index 00000000000..36df2d0f2c7 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/ml/dune @@ -0,0 +1,6 @@ +(library + (name bar) + (public_name example-ocaml.bar) + (modules bar) + (wrapped false) + (flags (:standard -rectypes -w -27-32-33-39-67-37-20-34))) diff --git a/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/run.t b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/run.t new file mode 100644 index 00000000000..c8210d42943 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/config-no-coqc.t/run.t @@ -0,0 +1,148 @@ +Testing for https://github.com/ocaml/dune/issues/9818 + +We first test the package builds as normal, when both are in scope: + + $ dune build -p example-ocaml + $ dune build -p example-coq + + $ ls -R _build/default/coq/extracted + _build/default/coq/extracted: + CRelationClasses.ml + CRelationClasses.mli + CRelationClasses.mli.patch + Datatypes.ml + Datatypes.mli + Extract.glob + Extract.v + Extract.vo + Extract.vok + Extract.vos + Foo.ml + Foo.mli + patch.sh + $ cat example-ocaml.install + lib: [ + "_build/install/default/lib/example-ocaml/META" + "_build/install/default/lib/example-ocaml/bar/bar.a" {"bar/bar.a"} + "_build/install/default/lib/example-ocaml/bar/bar.cma" {"bar/bar.cma"} + "_build/install/default/lib/example-ocaml/bar/bar.cmi" {"bar/bar.cmi"} + "_build/install/default/lib/example-ocaml/bar/bar.cmt" {"bar/bar.cmt"} + "_build/install/default/lib/example-ocaml/bar/bar.cmx" {"bar/bar.cmx"} + "_build/install/default/lib/example-ocaml/bar/bar.cmxa" {"bar/bar.cmxa"} + "_build/install/default/lib/example-ocaml/bar/bar.ml" {"bar/bar.ml"} + "_build/install/default/lib/example-ocaml/dune-package" + "_build/install/default/lib/example-ocaml/opam" + ] + libexec: [ + "_build/install/default/lib/example-ocaml/bar/bar.cmxs" {"bar/bar.cmxs"} + ] + doc: [ + "_build/install/default/doc/example-ocaml/README.md" + ] + $ cat example-coq.install + lib: [ + "_build/install/default/lib/example-coq/META" + "_build/install/default/lib/example-coq/coq/CRelationClasses.ml" {"coq/CRelationClasses.ml"} + "_build/install/default/lib/example-coq/coq/CRelationClasses.mli" {"coq/CRelationClasses.mli"} + "_build/install/default/lib/example-coq/coq/Datatypes.ml" {"coq/Datatypes.ml"} + "_build/install/default/lib/example-coq/coq/Datatypes.mli" {"coq/Datatypes.mli"} + "_build/install/default/lib/example-coq/coq/Foo.ml" {"coq/Foo.ml"} + "_build/install/default/lib/example-coq/coq/Foo.mli" {"coq/Foo.mli"} + "_build/install/default/lib/example-coq/coq/cRelationClasses.cmi" {"coq/cRelationClasses.cmi"} + "_build/install/default/lib/example-coq/coq/cRelationClasses.cmt" {"coq/cRelationClasses.cmt"} + "_build/install/default/lib/example-coq/coq/cRelationClasses.cmti" {"coq/cRelationClasses.cmti"} + "_build/install/default/lib/example-coq/coq/cRelationClasses.cmx" {"coq/cRelationClasses.cmx"} + "_build/install/default/lib/example-coq/coq/datatypes.cmi" {"coq/datatypes.cmi"} + "_build/install/default/lib/example-coq/coq/datatypes.cmt" {"coq/datatypes.cmt"} + "_build/install/default/lib/example-coq/coq/datatypes.cmti" {"coq/datatypes.cmti"} + "_build/install/default/lib/example-coq/coq/datatypes.cmx" {"coq/datatypes.cmx"} + "_build/install/default/lib/example-coq/coq/extracted.a" {"coq/extracted.a"} + "_build/install/default/lib/example-coq/coq/extracted.cma" {"coq/extracted.cma"} + "_build/install/default/lib/example-coq/coq/extracted.cmxa" {"coq/extracted.cmxa"} + "_build/install/default/lib/example-coq/coq/foo.cmi" {"coq/foo.cmi"} + "_build/install/default/lib/example-coq/coq/foo.cmt" {"coq/foo.cmt"} + "_build/install/default/lib/example-coq/coq/foo.cmti" {"coq/foo.cmti"} + "_build/install/default/lib/example-coq/coq/foo.cmx" {"coq/foo.cmx"} + "_build/install/default/lib/example-coq/dune-package" + "_build/install/default/lib/example-coq/opam" + ] + lib_root: [ + "_build/install/default/lib/coq/user-contrib/Common/Foo.glob" {"coq/user-contrib/Common/Foo.glob"} + "_build/install/default/lib/coq/user-contrib/Common/Foo.v" {"coq/user-contrib/Common/Foo.v"} + "_build/install/default/lib/coq/user-contrib/Common/Foo.vo" {"coq/user-contrib/Common/Foo.vo"} + ] + libexec: [ + "_build/install/default/lib/example-coq/coq/extracted.cmxs" {"coq/extracted.cmxs"} + ] + doc: [ + "_build/install/default/doc/example-coq/README.md" + ] + $ cp example-ocaml.install example-ocaml.install.old + $ dune clean + +We now test that the ocaml package still builds even when Coq rules can't be setup: + + $ mkdir _path + $ ln -s $(command -v dune) _path/ + $ ln -s $(command -v ocamlc) _path/ + $ ln -s $(command -v ocamldep) _path/ + + $ (unset INSIDE_DUNE; PATH=_path dune build -p example-ocaml) + $ cat example-ocaml.install + lib: [ + "_build/install/default/lib/example-ocaml/META" + "_build/install/default/lib/example-ocaml/bar/bar.cma" {"bar/bar.cma"} + "_build/install/default/lib/example-ocaml/bar/bar.cmi" {"bar/bar.cmi"} + "_build/install/default/lib/example-ocaml/bar/bar.cmt" {"bar/bar.cmt"} + "_build/install/default/lib/example-ocaml/bar/bar.ml" {"bar/bar.ml"} + "_build/install/default/lib/example-ocaml/dune-package" + "_build/install/default/lib/example-ocaml/opam" + ] + doc: [ + "_build/install/default/doc/example-ocaml/README.md" + ] + $ diff -u --label install_old example-ocaml.install.old --label install_new example-ocaml.install + --- install_old + +++ install_new + @@ -1,18 +1,12 @@ + lib: [ + "_build/install/default/lib/example-ocaml/META" + - "_build/install/default/lib/example-ocaml/bar/bar.a" {"bar/bar.a"} + "_build/install/default/lib/example-ocaml/bar/bar.cma" {"bar/bar.cma"} + "_build/install/default/lib/example-ocaml/bar/bar.cmi" {"bar/bar.cmi"} + "_build/install/default/lib/example-ocaml/bar/bar.cmt" {"bar/bar.cmt"} + - "_build/install/default/lib/example-ocaml/bar/bar.cmx" {"bar/bar.cmx"} + - "_build/install/default/lib/example-ocaml/bar/bar.cmxa" {"bar/bar.cmxa"} + "_build/install/default/lib/example-ocaml/bar/bar.ml" {"bar/bar.ml"} + "_build/install/default/lib/example-ocaml/dune-package" + "_build/install/default/lib/example-ocaml/opam" + ] + -libexec: [ + - "_build/install/default/lib/example-ocaml/bar/bar.cmxs" {"bar/bar.cmxs"} + -] + doc: [ + "_build/install/default/doc/example-ocaml/README.md" + ] + [1] + +Coq package should fail: + + $ (unset INSIDE_DUNE; PATH=_path dune build -p example-coq) + Couldn't find Rocq standard library, and theory is not using (stdlib no) + -> required by _build/default/coq/Common/Foo.glob + -> required by _build/install/default/lib/coq/user-contrib/Common/Foo.glob + -> required by _build/default/example-coq.install + -> required by alias install + File "coq/extracted/dune", line 6, characters 11-17: + 6 | (theories Stdlib Common)) + ^^^^^^ + Theory "Stdlib" has not been found. + -> required by _build/default/coq/extracted/CRelationClasses.ml + -> required by _build/default/coq/CRelationClasses.ml + -> required by _build/install/default/lib/example-coq/coq/CRelationClasses.ml + -> required by _build/default/example-coq.install + -> required by alias install + [1] + $ cat example-coq.install + cat: example-coq.install: No such file or directory + [1] diff --git a/test/blackbox-tests/test-cases/rocq/coq-config.t/dune b/test/blackbox-tests/test-cases/rocq/coq-config.t/dune new file mode 100644 index 00000000000..527e954fbc3 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coq-config.t/dune @@ -0,0 +1,29 @@ +(rule + (action + (with-outputs-to + config.output + (progn + (echo "COQLIB=%{rocq:rocqlib}\n") + (echo "COQ_NATIVE_COMPILER_DEFAULT=%{rocq:rocq_native_compiler_default}\n") + (echo "") + (echo "%{rocq:version} %{rocq:ocaml-version}\n") + (echo + "%{rocq:version.major}.%{rocq:version.minor}%{rocq:version.suffix} %{rocq:ocaml-version}\n"))))) + +(rule + (action + (with-outputs-to + config.expected + (progn + (pipe-outputs + ; We need to scrub ignored config values + (run %{bin:rocq} --config) + (run sed "/^COQCORELIB=/d") + (run sed "/^DOCDIR=/d") + (run sed "/^OCAMLFIND=/d") + (run sed "/^CAMLFLAGS=/d") + (run sed "/^WARN=/d") + (run sed "/^HASNATDYNLINK=/d") + (run sed "/^COQ_SRC_SUBDIRS=/d")) + (run %{bin:rocq} -print-version) + (run %{bin:rocq} -print-version))))) diff --git a/test/blackbox-tests/test-cases/rocq/coq-config.t/dune-project b/test/blackbox-tests/test-cases/rocq/coq-config.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coq-config.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/coq-config.t/run.t b/test/blackbox-tests/test-cases/rocq/coq-config.t/run.t new file mode 100644 index 00000000000..12246201342 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coq-config.t/run.t @@ -0,0 +1,8 @@ +Testing the Coq macro + + $ dune build + + $ cd _build/default + +Testing the output of the version and configuration values + $ diff config.output config.expected diff --git a/test/blackbox-tests/test-cases/rocq/coqdep-flags.t/dune-project b/test/blackbox-tests/test-cases/rocq/coqdep-flags.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdep-flags.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/coqdep-flags.t/dune.disabled b/test/blackbox-tests/test-cases/rocq/coqdep-flags.t/dune.disabled new file mode 100644 index 00000000000..23a0687ed4c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdep-flags.t/dune.disabled @@ -0,0 +1,4 @@ +(env + (_ + (rocq + (rocqdep_flags (:standard --global-flag1 --global-flag2))))) diff --git a/test/blackbox-tests/test-cases/rocq/coqdep-flags.t/run.t b/test/blackbox-tests/test-cases/rocq/coqdep-flags.t/run.t new file mode 100644 index 00000000000..a99b6dfd0be --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdep-flags.t/run.t @@ -0,0 +1,29 @@ +By default the coqdep flags are empty. + + $ cp theories/dune.noflags theories/dune + $ dune build theories/.basic.theory.d + +We use non-exising coqdep flags, so compilation fails. + + $ mv dune.disabled dune + $ dune build theories/.basic.theory.d + Warning: Unknown option "--global-flag1". [unknown-option,default] + Warning: Unknown option "--global-flag2". [unknown-option,default] + +We then add more flags locally to the theory. + + $ rm -f theories/dune + $ cp theories/dune.flags theories/dune + $ dune build theories/.basic.theory.d + Warning: Unknown option "--global-flag1". [unknown-option,default] + Warning: Unknown option "--global-flag2". [unknown-option,default] + Warning: Unknown option "--local-flag1". [unknown-option,default] + Warning: Unknown option "--local-flag2". [unknown-option,default] + +Finally we remove the toplevel dune file which sets some flags, but keep the +theory-local flags only. + + $ rm -f dune + $ dune build theories/.basic.theory.d + Warning: Unknown option "--local-flag1". [unknown-option,default] + Warning: Unknown option "--local-flag2". [unknown-option,default] diff --git a/test/blackbox-tests/test-cases/rocq/coqdep-flags.t/theories/bar.v b/test/blackbox-tests/test-cases/rocq/coqdep-flags.t/theories/bar.v new file mode 100644 index 00000000000..4627b76131c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdep-flags.t/theories/bar.v @@ -0,0 +1,3 @@ +From basic Require Import foo. + +Definition mynum (i : mynat) := 3. diff --git a/test/blackbox-tests/test-cases/rocq/coqdep-flags.t/theories/dune.flags b/test/blackbox-tests/test-cases/rocq/coqdep-flags.t/theories/dune.flags new file mode 100644 index 00000000000..5fc7ec0a4cf --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdep-flags.t/theories/dune.flags @@ -0,0 +1,3 @@ +(rocq.theory + (name basic) + (rocqdep_flags (:standard --local-flag1 --local-flag2))) diff --git a/test/blackbox-tests/test-cases/rocq/coqdep-flags.t/theories/dune.noflags b/test/blackbox-tests/test-cases/rocq/coqdep-flags.t/theories/dune.noflags new file mode 100644 index 00000000000..96afeb3dd01 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdep-flags.t/theories/dune.noflags @@ -0,0 +1,2 @@ +(rocq.theory + (name basic)) diff --git a/test/blackbox-tests/test-cases/rocq/coqdep-flags.t/theories/foo.v b/test/blackbox-tests/test-cases/rocq/coqdep-flags.t/theories/foo.v new file mode 100644 index 00000000000..53e0ce1b152 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdep-flags.t/theories/foo.v @@ -0,0 +1 @@ +Definition mynat := nat. diff --git a/test/blackbox-tests/test-cases/rocq/coqdep-on-rebuild.t/a/a.v b/test/blackbox-tests/test-cases/rocq/coqdep-on-rebuild.t/a/a.v new file mode 100644 index 00000000000..d4389c6d37d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdep-on-rebuild.t/a/a.v @@ -0,0 +1 @@ +Definition foo := 3. diff --git a/test/blackbox-tests/test-cases/rocq/coqdep-on-rebuild.t/a/dune b/test/blackbox-tests/test-cases/rocq/coqdep-on-rebuild.t/a/dune new file mode 100644 index 00000000000..6137494caa5 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdep-on-rebuild.t/a/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name a) + (package csimple)) diff --git a/test/blackbox-tests/test-cases/rocq/coqdep-on-rebuild.t/csimple.opam b/test/blackbox-tests/test-cases/rocq/coqdep-on-rebuild.t/csimple.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/coqdep-on-rebuild.t/dune-project b/test/blackbox-tests/test-cases/rocq/coqdep-on-rebuild.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdep-on-rebuild.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/coqdep-on-rebuild.t/run.t b/test/blackbox-tests/test-cases/rocq/coqdep-on-rebuild.t/run.t new file mode 100644 index 00000000000..2cbe10d41b7 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdep-on-rebuild.t/run.t @@ -0,0 +1,29 @@ + $ mkdir b + $ cat > b/dune < (rocq.theory + > (name b) + > (theories a) + > (package csimple)) + > EOF + $ cat > b/b.v < From a Require Import a. + > Definition bar := a.foo. + > EOF + $ cat > b/d.v < From a Require Import a. + > Definition doo := a.foo. + > EOF + $ dune build --display short --debug-dependency-path + rocq a/.a.theory.d + rocq b/.b.theory.d + rocq a/a.{glob,vo} + rocq b/b.{glob,vo} + rocq b/d.{glob,vo} + $ cat > b/b.v < From a Require Import a. + > Definition bar := a.foo. + > Definition zoo := 4. + > EOF + $ dune build --display short --debug-dependency-path + rocq b/.b.theory.d + rocq b/b.{glob,vo} diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-dir-target-clash.t/base.v b/test/blackbox-tests/test-cases/rocq/coqdoc-dir-target-clash.t/base.v new file mode 100644 index 00000000000..63af1913bd9 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc-dir-target-clash.t/base.v @@ -0,0 +1,5 @@ + +Variant Or (A B : Set) : Set := +| inl : A -> Or A B +| inr : B -> Or A B +. diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-dir-target-clash.t/dune b/test/blackbox-tests/test-cases/rocq/coqdoc-dir-target-clash.t/dune new file mode 100644 index 00000000000..57b59b8ed84 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc-dir-target-clash.t/dune @@ -0,0 +1,21 @@ +(rule + (targets + (dir base.html)) + (action + (progn + (run mkdir base.html) + (run touch base.html/base.base.html)))) + +(rule + (targets + (dir base.tex)) + (action + (progn + (run mkdir base.tex) + (run touch base.tex/base.base.tex)))) + +(rocq.theory + (name base) + (package base) + (modules base) + (synopsis "Base Coq library")) diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-dir-target-clash.t/dune-project b/test/blackbox-tests/test-cases/rocq/coqdoc-dir-target-clash.t/dune-project new file mode 100644 index 00000000000..3e5f50e6bcc --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc-dir-target-clash.t/dune-project @@ -0,0 +1,6 @@ +(lang dune 3.21) +(using directory-targets 0.1) +(using rocq 0.11) + +(package + (name base)) diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-dir-target-clash.t/run.t b/test/blackbox-tests/test-cases/rocq/coqdoc-dir-target-clash.t/run.t new file mode 100644 index 00000000000..1c2f840754f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc-dir-target-clash.t/run.t @@ -0,0 +1,16 @@ +We try to build the documentation but there will be a clash between the +directory targets. + $ dune build @check + File "dune", lines 1-7, characters 0-120: + 1 | (rule + 2 | (targets + 3 | (dir base.html)) + 4 | (action + 5 | (progn + 6 | (run mkdir base.html) + 7 | (run touch base.html/base.base.html)))) + Error: The following both define the same directory target: + _build/default/base.html + - dune:1 + - dune:17 + [1] diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-flags-header-footer-gen.t b/test/blackbox-tests/test-cases/rocq/coqdoc-flags-header-footer-gen.t new file mode 100644 index 00000000000..1c4167f6b7b --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc-flags-header-footer-gen.t @@ -0,0 +1,31 @@ +Testing the rocqdoc_header and rocqdoc_footer field of the env stanza. + + $ cat > dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + + $ cat > dune < (rule (with-stdout-to header.%{rocq:version}.html (echo "HEADER"))) + > (rule (with-stdout-to footer.html (echo "FOOTER"))) + > (env + > (_ + > (rocq + > (rocqdoc_header header.%{rocq:version}.html) + > (rocqdoc_footer footer.html)))) + > (rocq.theory + > (name a)) + > EOF + $ cat > foo.v < Definition a := 42. + > EOF + + $ dune build @doc + $ find _build/default/a.html -type f -name '*.html' | sort | xargs grep HEADER + _build/default/a.html/a.foo.html:HEADER + _build/default/a.html/index.html:HEADER + _build/default/a.html/toc.html:HEADER + $ find _build/default/a.html -type f -name '*.html' | sort | xargs grep FOOTER + _build/default/a.html/a.foo.html:FOOTER + _build/default/a.html/index.html:FOOTER + _build/default/a.html/toc.html:FOOTER diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-flags-header-footer.t b/test/blackbox-tests/test-cases/rocq/coqdoc-flags-header-footer.t new file mode 100644 index 00000000000..ebfac84be57 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc-flags-header-footer.t @@ -0,0 +1,41 @@ +Testing the rocqdoc_header and rocqdoc_footer field of the env stanza. + + $ cat > dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + + $ cat > dune < (env + > (_ + > (rocq + > (rocqdoc_header header.html) + > (rocqdoc_footer footer.html)))) + > (rocq.theory + > (name a)) + > EOF + $ cat > foo.v < Definition a := 42. + > EOF + $ cat > header.html < header + > EOF + $ cat > footer.html < footer + > EOF + + $ dune build @doc + + $ tail _build/log -n 1 | ./scrub_coq_args.sh | sed 's/.*rocq/rocq/' + rocq doc + -R coq/theories Corelib + -R . a --toc --with-header header.html --with-footer footer.html --html -d a.html + foo.v + + $ dune build @doc-latex + + $ tail _build/log -n 1 | ./scrub_coq_args.sh | sed 's/.*rocq/rocq/' + rocq doc + -R coq/theories Corelib + -R . a --toc --latex -d a.tex + foo.v diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-flags.t b/test/blackbox-tests/test-cases/rocq/coqdoc-flags.t new file mode 100644 index 00000000000..8ff29a6557e --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc-flags.t @@ -0,0 +1,26 @@ +Testing the coqdoc flags field of the env stanza. + + $ cat > dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + + $ cat > dune < (env + > (_ + > (rocq + > (rocqdoc_flags :standard -toc-depth 2)))) + > (rocq.theory + > (name a)) + > EOF + $ cat > foo.v < Definition a := 42. + > EOF + + $ dune build @doc + + $ tail _build/log -n 1 | ./scrub_coq_args.sh | sed 's/.*rocq/rocq/' + rocq doc + -R coq/theories Corelib + -R . a --toc -toc-depth 2 --html -d a.html + foo.v diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-multi-theory.t/A/AA/aa.v b/test/blackbox-tests/test-cases/rocq/coqdoc-multi-theory.t/A/AA/aa.v new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-multi-theory.t/A/AB/ab.v b/test/blackbox-tests/test-cases/rocq/coqdoc-multi-theory.t/A/AB/ab.v new file mode 100644 index 00000000000..497f743f440 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc-multi-theory.t/A/AB/ab.v @@ -0,0 +1 @@ +Require Import AA.aa. diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-multi-theory.t/A/dune b/test/blackbox-tests/test-cases/rocq/coqdoc-multi-theory.t/A/dune new file mode 100644 index 00000000000..161266e0d94 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc-multi-theory.t/A/dune @@ -0,0 +1,3 @@ +(include_subdirs qualified) +(rocq.theory + (name A)) diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-multi-theory.t/B/b.v b/test/blackbox-tests/test-cases/rocq/coqdoc-multi-theory.t/B/b.v new file mode 100644 index 00000000000..dbbe84300ce --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc-multi-theory.t/B/b.v @@ -0,0 +1 @@ +From A Require Import AB.ab. diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-multi-theory.t/B/dune b/test/blackbox-tests/test-cases/rocq/coqdoc-multi-theory.t/B/dune new file mode 100644 index 00000000000..9d5457bd3ff --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc-multi-theory.t/B/dune @@ -0,0 +1,5 @@ +(include_subdirs qualified) + +(rocq.theory + (name B) + (theories A)) diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-multi-theory.t/dune-project b/test/blackbox-tests/test-cases/rocq/coqdoc-multi-theory.t/dune-project new file mode 100644 index 00000000000..2095d13a749 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc-multi-theory.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) +(using rocq 0.11) +(name CoqTest) diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-multi-theory.t/run.t b/test/blackbox-tests/test-cases/rocq/coqdoc-multi-theory.t/run.t new file mode 100644 index 00000000000..32e083c7338 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc-multi-theory.t/run.t @@ -0,0 +1,60 @@ +HTML +---- + +First we build the doc alias for the first theory + $ dune build @A/doc +The first theory doc is built + $ ls _build/default/A/A.html + A.AA.aa.html + A.AB.ab.html + coqdoc.css + index.html + toc.html +Check that the second is not built + $ ls _build/default/ + A +Clean + $ dune clean + +Next we build the doc for the second theory + $ dune build @B/doc +Check that the first theory doc is not built + $ ls _build/default/A/ + AA + AB +Check that the second theory doc is built + $ ls _build/default/B/B.html + B.b.html + coqdoc.css + index.html + toc.html +Clean + $ dune clean + + +LaTeX +----- + +Next we test the LaTeX targets in the same manner + $ dune build @A/doc-latex +The first theory doc is built + $ ls _build/default/A/A.tex + A.AA.aa.tex + A.AB.ab.tex + coqdoc.sty +Check that the second is not built + $ ls _build/default + A +Clean + $ dune clean + +Next we build the doc for the second theory + $ dune build @B/doc-latex +Check that the first theory doc is not built + $ ls _build/default/A + AA + AB +Check that the second theory doc is built + $ ls _build/default/B/B.tex + B.b.tex + coqdoc.sty diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/A/a.v b/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/A/a.v new file mode 100644 index 00000000000..446bb1cb55d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/A/a.v @@ -0,0 +1,3 @@ +Fail Print Prelude. +From Corelib Require Import Prelude. +Require Import mytheory. diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/A/dune b/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/A/dune new file mode 100644 index 00000000000..d872b235fa9 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/A/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name A) + (stdlib no) + (theories Corelib)) diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/A/dune-project b/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/A/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/A/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/Coq/Coq.opam b/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/Coq/Coq.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/Coq/Init/Prelude.v b/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/Coq/Init/Prelude.v new file mode 100644 index 00000000000..9de480a5ab8 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/Coq/Init/Prelude.v @@ -0,0 +1,2 @@ +Unset Elimination Schemes. +Inductive BootType := boot | type. diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/Coq/dune b/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/Coq/dune new file mode 100644 index 00000000000..e6c2c8a6daf --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/Coq/dune @@ -0,0 +1,6 @@ +(rocq.theory + (name Corelib) + (package Coq) + (boot)) + +(include_subdirs qualified) diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/Coq/dune-project b/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/Coq/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/Coq/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/Coq/mytheory.v b/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/Coq/mytheory.v new file mode 100644 index 00000000000..831752c569d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/Coq/mytheory.v @@ -0,0 +1,2 @@ + +Inductive Hello := World | Bye. diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/dune-workspace b/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/dune-workspace new file mode 100644 index 00000000000..e1b8e598780 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/dune-workspace @@ -0,0 +1 @@ +(lang dune 3.21) diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/run.t b/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/run.t new file mode 100644 index 00000000000..7c657bedac5 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc-with-boot.t/run.t @@ -0,0 +1,19 @@ +Testing coqdoc when composed with a boot library + + $ dune build A/A.html + + $ ls _build/default/A + A.html + a.glob + a.v + a.vo + a.vok + a.vos + +Dune should be passing '--coqlib' to coqdoc, but it doesn't. This is a bug. + + $ cat _build/log | sed 's/$ (cd .*rocq/rocq/' | sed '/# /d' | sed '/> /d' | sort + rocq compile -q -w -deprecated-native-compiler-option -w -native-compiler-disabled -native-compiler ondemand -boot -R Coq Corelib Coq/mytheory.v) + rocq compile -q -w -deprecated-native-compiler-option -w -native-compiler-disabled -native-compiler ondemand -noinit -boot -R Coq Corelib -R A A A/a.v) + rocq compile -q -w -deprecated-native-compiler-option -w -native-compiler-disabled -native-compiler ondemand -noinit -boot -R Coq Corelib Coq/Init/Prelude.v) + rocq doc -R ../Coq Corelib -R . A --toc --html -d A.html a.v) diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc.t/bar.v b/test/blackbox-tests/test-cases/rocq/coqdoc.t/bar.v new file mode 100644 index 00000000000..4627b76131c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc.t/bar.v @@ -0,0 +1,3 @@ +From basic Require Import foo. + +Definition mynum (i : mynat) := 3. diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc.t/dune b/test/blackbox-tests/test-cases/rocq/coqdoc.t/dune new file mode 100644 index 00000000000..3c373327984 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc.t/dune @@ -0,0 +1,5 @@ +(rocq.theory + (name basic) + (package base) + (modules :standard) + (synopsis "Test Coq library")) diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc.t/dune-project b/test/blackbox-tests/test-cases/rocq/coqdoc.t/dune-project new file mode 100644 index 00000000000..3e5f50e6bcc --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc.t/dune-project @@ -0,0 +1,6 @@ +(lang dune 3.21) +(using directory-targets 0.1) +(using rocq 0.11) + +(package + (name base)) diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc.t/foo.v b/test/blackbox-tests/test-cases/rocq/coqdoc.t/foo.v new file mode 100644 index 00000000000..53e0ce1b152 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc.t/foo.v @@ -0,0 +1 @@ +Definition mynat := nat. diff --git a/test/blackbox-tests/test-cases/rocq/coqdoc.t/run.t b/test/blackbox-tests/test-cases/rocq/coqdoc.t/run.t new file mode 100644 index 00000000000..248f4407b1e --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqdoc.t/run.t @@ -0,0 +1,39 @@ +We build the coqdoc html target: + $ dune build basic.html/ + +Now we inspect it: + $ ls _build/default/basic.html + basic.bar.html + basic.foo.html + coqdoc.css + index.html + toc.html + +We build the coqdoc latex target: + $ dune build basic.tex/ + +Now we inspect it: + $ ls _build/default/basic.tex + basic.bar.tex + basic.foo.tex + coqdoc.sty + +Next from a clean build we make sure that @all does *not* build any doc targets: + $ dune clean + $ dune build @all +Note that this currently works due to a bug in @all detecting directory targets. + $ ls _build/default + META.base + bar.glob + bar.v + bar.vo + bar.vok + bar.vos + base.dune-package + base.install + foo.glob + foo.v + foo.vo + foo.vok + foo.vos + diff --git a/test/blackbox-tests/test-cases/rocq/coqpp.t/dune-project b/test/blackbox-tests/test-cases/rocq/coqpp.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqpp.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/coqpp.t/gram.mlg b/test/blackbox-tests/test-cases/rocq/coqpp.t/gram.mlg new file mode 100644 index 00000000000..f54a2e951fc --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqpp.t/gram.mlg @@ -0,0 +1,9 @@ +DECLARE PLUGIN "cplugin.ml_plugin_a" + +{ + +(* We don't use any coqpp specific macros as to make the test more + resilient on different Coq versions *) +let foo = 3 + +} diff --git a/test/blackbox-tests/test-cases/rocq/coqpp.t/marg.mlg b/test/blackbox-tests/test-cases/rocq/coqpp.t/marg.mlg new file mode 100644 index 00000000000..d3fe5d78780 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqpp.t/marg.mlg @@ -0,0 +1,4 @@ +DECLARE PLUGIN "cplugin.ml_plugin_b" +{ + let bar = Gram.foo + 4 +} diff --git a/test/blackbox-tests/test-cases/rocq/coqpp.t/run.t b/test/blackbox-tests/test-cases/rocq/coqpp.t/run.t new file mode 100644 index 00000000000..f907319eaee --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqpp.t/run.t @@ -0,0 +1,82 @@ +Testing the coqpp stanza + + $ cat > dune << EOF + > (rocq.pp + > (modules gram)) + > (library + > (name foo) + > (flags -rectypes) + > (libraries rocq-runtime.vernac)) + > EOF + + $ ls + dune + dune-project + gram.mlg + marg.mlg + + $ dune build + + $ ls _build/default/ + foo.a + foo.cma + foo.cmxa + foo.cmxs + foo.ml-gen + gram.ml + gram.mlg + +Testing the :standard field with a .mlg file depending on another .mlg file + $ cat > dune << EOF + > (rocq.pp + > (modules :standard)) + > (library + > (name foo) + > (flags -rectypes) + > (libraries rocq-runtime.vernac)) + > EOF + + $ ls + _build + dune + dune-project + gram.mlg + marg.mlg + + $ dune build + + $ ls _build/default/ + foo.a + foo.cma + foo.cmxa + foo.cmxs + foo.ml-gen + gram.ml + gram.mlg + marg.ml + marg.mlg + +Same again but with one .mlg file removed + $ cat > dune << EOF + > (rocq.pp + > (modules :standard \ gram)) + > (library + > (name foo) + > (flags -rectypes) + > (libraries rocq-runtime.vernac)) + > EOF + + $ dune build + File "marg.mlg", line 3, characters 12-20: + Error: Unbound module Gram + [1] + + $ ls _build/default/ + foo.a + foo.cma + foo.cmxa + foo.cmxs + foo.ml-gen + gram.mlg + marg.ml + marg.mlg diff --git a/test/blackbox-tests/test-cases/rocq/coqproject-multiple-theories.t b/test/blackbox-tests/test-cases/rocq/coqproject-multiple-theories.t new file mode 100644 index 00000000000..ebbd3dfa23e --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqproject-multiple-theories.t @@ -0,0 +1,26 @@ +Testing the _RocqProject generation. + + $ cat > dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + + $ cat > dune < (rocq.theory + > (name a) + > (modules foo) + > (generate_project_file)) + > + > (rocq.theory + > (name b) + > (modules bar) + > (generate_project_file)) + > EOF + + $ touch foo.v bar.v + + $ dune build + Error: Multiple rules generated for _build/default/_RocqProject: + - dune:6 + - dune:1 + [1] diff --git a/test/blackbox-tests/test-cases/rocq/coqproject-per-module-flags.t b/test/blackbox-tests/test-cases/rocq/coqproject-per-module-flags.t new file mode 100644 index 00000000000..3b61b2d93dd --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqproject-per-module-flags.t @@ -0,0 +1,22 @@ +Testing the _CoqProject generation. + + $ cat > dune-project < (lang dune 3.21) + > (using coq 0.11) + > EOF + + $ cat > dune < (coq.theory + > (name a) + > (modules_flags (foo (:standard -flag))) + > (generate_project_file)) + > EOF + + $ touch foo.v + + $ dune build + File "dune", line 4, characters 1-24: + 4 | (generate_project_file)) + ^^^^^^^^^^^^^^^^^^^^^^^ + Error: (generate_project_file) is not compatible with (modules_flags ...) + [1] diff --git a/test/blackbox-tests/test-cases/rocq/coqproject.t b/test/blackbox-tests/test-cases/rocq/coqproject.t new file mode 100644 index 00000000000..658c4175e8f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqproject.t @@ -0,0 +1,17 @@ +Testing the _RocqProject generation. + + $ cat > dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + + $ cat > dune < (rocq.theory + > (name a) + > (generate_project_file)) + > EOF + + $ touch foo.v + + $ dune build + $ [ -f _RocqProject ] diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-flags.t/Test.v b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-flags.t/Test.v new file mode 100644 index 00000000000..55d1fa98f60 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-flags.t/Test.v @@ -0,0 +1 @@ +Inductive foo := . diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-flags.t/dune b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-flags.t/dune new file mode 100644 index 00000000000..0d2922aae9f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-flags.t/dune @@ -0,0 +1,3 @@ +(rocq.theory + (name minimal) + (flags -w -notation-overridden)) diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-flags.t/dune-project b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-flags.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-flags.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-flags.t/run.t b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-flags.t/run.t new file mode 100644 index 00000000000..5abf3520cdb --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-flags.t/run.t @@ -0,0 +1,24 @@ +Testing that the correct flags are being passed to dune rocq top + +The flags passed to coqc: + $ dune build && tail -1 _build/log | ../../scrub_coq_args.sh + rocq compile + -w -notation-overridden + -w -deprecated-native-compiler-option + -w -native-compiler-disabled + -native-compiler ondemand + -boot + -R coq/theories Corelib + -R . minimal + Test.v + +The flags passed to coqtop: + $ dune rocq top --toplevel=echo Test.v | ../../scrub_coq_args.sh + -topfile $TESTCASE_ROOT/_build/default/Test.v + -w -notation-overridden + -w -deprecated-native-compiler-option + -w -native-compiler-disabled + -native-compiler ondemand + -boot + -R coq/theories Corelib + -R $TESTCASE_ROOT/_build/default minimal diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-gen-file.t b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-gen-file.t new file mode 100644 index 00000000000..3e1b217aee4 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-gen-file.t @@ -0,0 +1,22 @@ +Running the Coq Toplevel on a generated file with a dependency. + + $ cat >bar.v < From basic Require Import foo. + > Definition mynum (i : mynat) := 3. + > EOF + $ cat >foo.v < Definition mynat := nat. + > EOF + $ cat >dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + $ cat >dune < (rocq.theory + > (name basic)) + > (rule + > (target bar_gen.v) + > (deps bar.v) + > (action (copy %{deps} %{target}))) + > EOF + $ cat bar.v | dune rocq top bar_gen.v > /dev/null 2> /dev/null diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-nested.t/dune-project b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-nested.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-nested.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-nested.t/run.t b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-nested.t/run.t new file mode 100644 index 00000000000..6c7dce4bba8 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-nested.t/run.t @@ -0,0 +1,22 @@ +Checking that we compute the directory and file for dune rocq top correctly + + $ dune build theories/c.vo + $ dune build theories/b/b.vo + $ dune rocq top --toplevel=echo theories/c.v | ../../scrub_coq_args.sh + -topfile $TESTCASE_ROOT/_build/default/theories/c.v + -w -deprecated-native-compiler-option + -w -native-compiler-disabled + -native-compiler ondemand + -boot + -R coq/theories Corelib + -R $TESTCASE_ROOT/_build/default/theories foo + + $ dune rocq top --toplevel=echo theories/b/b.v | ../../scrub_coq_args.sh + -topfile $TESTCASE_ROOT/_build/default/theories/b/b.v + -w -deprecated-native-compiler-option + -w -native-compiler-disabled + -native-compiler ondemand + -boot + -R coq/theories Corelib + -R $TESTCASE_ROOT/_build/default/theories foo + diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-nested.t/theories/a/a.v b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-nested.t/theories/a/a.v new file mode 100644 index 00000000000..3085bc9cedc --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-nested.t/theories/a/a.v @@ -0,0 +1 @@ +Definition bar := 3. diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-nested.t/theories/b/b.v b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-nested.t/theories/b/b.v new file mode 100644 index 00000000000..d5bde6eccc8 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-nested.t/theories/b/b.v @@ -0,0 +1,3 @@ +Require a. + +Definition moo := a.bar. diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-nested.t/theories/c.v b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-nested.t/theories/c.v new file mode 100644 index 00000000000..2bbebffd410 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-nested.t/theories/c.v @@ -0,0 +1,3 @@ +Require d. + +Definition uuhh := d.aike. diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-nested.t/theories/d.v b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-nested.t/theories/d.v new file mode 100644 index 00000000000..d678e8cb591 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-nested.t/theories/d.v @@ -0,0 +1 @@ +Definition aike := 3. diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-nested.t/theories/dune b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-nested.t/theories/dune new file mode 100644 index 00000000000..174d3d16185 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-nested.t/theories/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name foo)) + +(include_subdirs qualified) diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-no-build.t b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-no-build.t new file mode 100644 index 00000000000..77b53cb6a13 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-no-build.t @@ -0,0 +1,42 @@ +Testing the -no-build option of dune rocq top: + + $ mkdir dir + $ cat >dir/bar.v < From basic Require Import foo. + > Definition mynum (i : mynat) := 3. + > EOF + $ cat >dir/foo.v < Definition mynat := nat. + > EOF + $ cat >dir/dune < (rocq.theory + > (name basic)) + > EOF + $ cat >dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + +On a fresh build, this should do nothing but should pass the correct flags: + + $ dune rocq top --no-build --display short --toplevel echo dir/bar.v | ../scrub_coq_args.sh + -topfile $TESTCASE_ROOT/_build/default/dir/bar.v + -w -deprecated-native-compiler-option + -w -native-compiler-disabled + -native-compiler ondemand + -boot + -R coq/theories Corelib + -R $TESTCASE_ROOT/_build/default/dir basic + +And for comparison normally a build would happen: + + $ dune rocq top --display short --toplevel echo dir/bar.v | ../scrub_coq_args.sh + rocq dir/.basic.theory.d + rocq dir/foo.{glob,vo} + -topfile $TESTCASE_ROOT/_build/default/dir/bar.v + -w -deprecated-native-compiler-option + -w -native-compiler-disabled + -native-compiler ondemand + -boot + -R coq/theories Corelib + -R $TESTCASE_ROOT/_build/default/dir basic diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-no-stanza.t b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-no-stanza.t new file mode 100644 index 00000000000..7394740db99 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-no-stanza.t @@ -0,0 +1,14 @@ +Running the Coq Toplevel on a file that is not part of a stanza. + + $ cat >foo.v < Definition mynat := nat. + > EOF + $ cat >dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + $ dune rocq top foo.v || echo failed + Error: Cannot find file: foo.v + Hint: Is the file part of a stanza? + Hint: Has the file been written to disk? + failed diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-recomp.t b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-recomp.t new file mode 100644 index 00000000000..ac489b38ff0 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-recomp.t @@ -0,0 +1,62 @@ +Check that dependencies are not recompiled when this is not necessary. This +was initially an issue, and was reported by @MackieLoeffel in #5457 (see +https://github.com/ocaml/dune/pull/5457#issuecomment-1084161587). + + $ mkdir dir + $ cat >dir/bar.v < From basic Require Import foo. + > Definition mynum (i : mynat) := 3. + > EOF + $ cat >dir/foo.v < Definition mynat := nat. + > EOF + $ cat >dir/dune < (rocq.theory + > (name basic)) + > EOF + $ cat >dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + $ dune rocq top --display short --toplevel echo dir/bar.v | ../scrub_coq_args.sh + rocq dir/.basic.theory.d + rocq dir/foo.{glob,vo} + -topfile $TESTCASE_ROOT/_build/default/dir/bar.v + -w -deprecated-native-compiler-option + -w -native-compiler-disabled + -native-compiler ondemand + -boot + -R coq/theories Corelib + -R $TESTCASE_ROOT/_build/default/dir basic + $ dune rocq top --display short --toplevel echo dir/bar.v | ../scrub_coq_args.sh + -topfile $TESTCASE_ROOT/_build/default/dir/bar.v + -w -deprecated-native-compiler-option + -w -native-compiler-disabled + -native-compiler ondemand + -boot + -R coq/theories Corelib + -R $TESTCASE_ROOT/_build/default/dir basic + $ dune clean + $ (cd dir && dune rocq top --root .. --display short --toplevel echo dir/bar.v) | ../scrub_coq_args.sh + Entering directory '..' + rocq dir/.basic.theory.d + rocq dir/foo.{glob,vo} + Leaving directory '..' + -topfile $TESTCASE_ROOT/_build/default/dir/bar.v + -w -deprecated-native-compiler-option + -w -native-compiler-disabled + -native-compiler ondemand + -boot + -R coq/theories Corelib + -R $TESTCASE_ROOT/_build/default/dir basic + $ (cd dir && dune rocq top --root .. --display short --toplevel echo dir/bar.v) | ../scrub_coq_args.sh + Entering directory '..' + Leaving directory '..' + -topfile $TESTCASE_ROOT/_build/default/dir/bar.v + -w -deprecated-native-compiler-option + -w -native-compiler-disabled + -native-compiler ondemand + -boot + -R coq/theories Corelib + -R $TESTCASE_ROOT/_build/default/dir basic + diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-root.t/dune-project b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-root.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-root.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-root.t/run.t b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-root.t/run.t new file mode 100644 index 00000000000..824ba7e6c63 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-root.t/run.t @@ -0,0 +1,26 @@ +All dune commands work when you run them in sub-directories, so this should be no exception. + + $ dune rocq top --toplevel=echo -- theories/foo.v | ../../scrub_coq_args.sh + -topfile $TESTCASE_ROOT/_build/default/theories/foo.v + -w -deprecated-native-compiler-option + -w -native-compiler-disabled + -native-compiler ondemand + -boot + -R coq/theories Corelib + -R $TESTCASE_ROOT/_build/default/theories foo + $ cd theories + +This test is currently broken due to the workspace resolution being faulty #5899. + $ dune rocq top --toplevel=echo -- foo.v + File ".", line 1, characters 0-0: + Warning: No dune-project file has been found in directory ".". A default one + is assumed but the project might break when dune is upgraded. Please create a + dune-project file. + Hint: generate the project file with: $ dune init project + File "dune", lines 1-2, characters 0-25: + 1 | (rocq.theory + 2 | (name foo)) + Error: 'rocq.theory' is available only when rocq is enabled in the + dune-project file. You must enable it using (using rocq 0.11) in your + dune-project file. + [1] diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-root.t/theories/dune b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-root.t/theories/dune new file mode 100644 index 00000000000..5c5490c5030 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-root.t/theories/dune @@ -0,0 +1,2 @@ +(rocq.theory + (name foo)) diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-root.t/theories/foo.v b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-root.t/theories/foo.v new file mode 100644 index 00000000000..8ac4c3baeac --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-root.t/theories/foo.v @@ -0,0 +1 @@ +Definition answer := 42. diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/coq_dir1/dir1/file3.v b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/coq_dir1/dir1/file3.v new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/coq_dir1/dune b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/coq_dir1/dune new file mode 100644 index 00000000000..f6a64602a38 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/coq_dir1/dune @@ -0,0 +1,3 @@ +(include_subdirs qualified) +(rocq.theory + (name theory2)) diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/coq_dir1/file2.v b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/coq_dir1/file2.v new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/dune b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/dune new file mode 100644 index 00000000000..784b4143d4e --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/dune @@ -0,0 +1,2 @@ +(rocq.theory + (name theory1)) diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/dune-project b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/dune-workspace b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/dune-workspace new file mode 100644 index 00000000000..e1b8e598780 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/dune-workspace @@ -0,0 +1 @@ +(lang dune 3.21) diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/file1.v b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/file1.v new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/project/coq_dir2/dir2/file6.v b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/project/coq_dir2/dir2/file6.v new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/project/coq_dir2/dune b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/project/coq_dir2/dune new file mode 100644 index 00000000000..c8a814bf474 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/project/coq_dir2/dune @@ -0,0 +1,3 @@ +(include_subdirs qualified) +(rocq.theory + (name theory4)) diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/project/coq_dir2/file5.v b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/project/coq_dir2/file5.v new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/project/dune b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/project/dune new file mode 100644 index 00000000000..dd6bd6a5c96 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/project/dune @@ -0,0 +1,2 @@ +(rocq.theory + (name theory3)) diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/project/dune-project b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/project/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/project/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/project/file4.v b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/project/file4.v new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/run.t b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/run.t new file mode 100644 index 00000000000..b78350d9d07 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/run.t @@ -0,0 +1,108 @@ +Running "dune rocq top" from different directories in a workspace. The setup is +a workspace whose root is the root of a first project, and a second project is +contained under directory "project". + + $ unset INSIDE_DUNE + $ . ./util.sh + +Calling "dune rocq top" from the workspace root. + + $ coqtop_test file1.v + $ coqtop_test coq_dir1/file2.v + $ coqtop_test coq_dir1/dir1/file3.v + $ coqtop_test project/file4.v + $ coqtop_test project/coq_dir2/file5.v + $ coqtop_test project/coq_dir2/dir2/file6.v + +Calling "dune rocq top" from the "coq_dir1" directory. + + $ cd coq_dir1 + + $ coqtop_test ../file1.v + $ coqtop_test ../file1.v + $ coqtop_test ../coq_dir1/file2.v + $ coqtop_test ../coq_dir1/dir1/file3.v + $ coqtop_test ../project/file4.v + $ coqtop_test ../project/coq_dir2/file5.v + $ coqtop_test ../project/coq_dir2/dir2/file6.v + + $ coqtop_test file2.v + $ coqtop_test dir1/file3.v + + $ cd .. + +Calling "dune rocq top" from the "coq_dir1/dir1" directory. + + $ cd coq_dir1/dir1 + + $ coqtop_test ../../file1.v + $ coqtop_test ../../file1.v + $ coqtop_test ../../coq_dir1/file2.v + $ coqtop_test ../../coq_dir1/dir1/file3.v + $ coqtop_test ../../project/file4.v + $ coqtop_test ../../project/coq_dir2/file5.v + $ coqtop_test ../../project/coq_dir2/dir2/file6.v + + $ coqtop_test ../file2.v + $ coqtop_test ../dir1/file3.v + $ coqtop_test file3.v + + $ cd ../.. + +Calling "dune rocq top" from the "project" directory. + + $ cd project + + $ coqtop_test ../file1.v + $ coqtop_test ../coq_dir1/file2.v + $ coqtop_test ../coq_dir1/dir1/file3.v + $ coqtop_test ../project/file4.v + $ coqtop_test ../project/coq_dir2/file5.v + $ coqtop_test ../project/coq_dir2/dir2/file6.v + + $ coqtop_test file4.v + $ coqtop_test coq_dir2/file5.v + $ coqtop_test coq_dir2/dir2/file6.v + + $ cd .. + +Calling "dune rocq top" from the "project/coq_dir2" directory. + + $ cd project/coq_dir2 + + $ coqtop_test ../../file1.v + $ coqtop_test ../../file1.v + $ coqtop_test ../../coq_dir1/file2.v + $ coqtop_test ../../coq_dir1/dir1/file3.v + $ coqtop_test ../../project/file4.v + $ coqtop_test ../../project/coq_dir2/file5.v + $ coqtop_test ../../project/coq_dir2/dir2/file6.v + + $ coqtop_test ../file4.v + $ coqtop_test ../coq_dir2/file5.v + $ coqtop_test ../coq_dir2/dir2/file6.v + $ coqtop_test file5.v + $ coqtop_test dir2/file6.v + + $ cd ../.. + +Calling "dune rocq top" from the "project/coq_dir2/dir2" directory. + + $ cd project/coq_dir2/dir2 + + $ coqtop_test ../../../file1.v + $ coqtop_test ../../../file1.v + $ coqtop_test ../../../coq_dir1/file2.v + $ coqtop_test ../../../coq_dir1/dir1/file3.v + $ coqtop_test ../../../project/file4.v + $ coqtop_test ../../../project/coq_dir2/file5.v + $ coqtop_test ../../../project/coq_dir2/dir2/file6.v + + $ coqtop_test ../../file4.v + $ coqtop_test ../../coq_dir2/file5.v + $ coqtop_test ../../coq_dir2/dir2/file6.v + $ coqtop_test ../file5.v + $ coqtop_test ../dir2/file6.v + $ coqtop_test file6.v + + $ cd ../../.. diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/util.sh b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/util.sh new file mode 100755 index 00000000000..56b4106860f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop-workspace.t/util.sh @@ -0,0 +1,5 @@ +OUTPUT="$PWD/coqtop_test.tmp" + +coqtop_test() { + (true | (dune rocq top --display=verbose "$1" 1>$OUTPUT 2>&1)) || cat $OUTPUT +} diff --git a/test/blackbox-tests/test-cases/rocq/coqtop/coqtop.t b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop.t new file mode 100644 index 00000000000..249948acd97 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/coqtop/coqtop.t @@ -0,0 +1,18 @@ +Running the Coq Toplevel on a file with a dependency. + + $ cat >bar.v < From basic Require Import foo. + > Definition mynum (i : mynat) := 3. + > EOF + $ cat >foo.v < Definition mynat := nat. + > EOF + $ cat >dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + $ cat >dune < (rocq.theory + > (name basic)) + > EOF + $ cat bar.v | dune rocq top bar.v > /dev/null 2> /dev/null diff --git a/test/blackbox-tests/test-cases/rocq/deprecate-libraries.t/bar.opam b/test/blackbox-tests/test-cases/rocq/deprecate-libraries.t/bar.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/deprecate-libraries.t/bar.v b/test/blackbox-tests/test-cases/rocq/deprecate-libraries.t/bar.v new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/deprecate-libraries.t/dune-project b/test/blackbox-tests/test-cases/rocq/deprecate-libraries.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/deprecate-libraries.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/deprecate-libraries.t/foo.ml b/test/blackbox-tests/test-cases/rocq/deprecate-libraries.t/foo.ml new file mode 100644 index 00000000000..4b3fcfa724c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/deprecate-libraries.t/foo.ml @@ -0,0 +1 @@ +let foo = "bar" diff --git a/test/blackbox-tests/test-cases/rocq/deprecate-libraries.t/run.t b/test/blackbox-tests/test-cases/rocq/deprecate-libraries.t/run.t new file mode 100644 index 00000000000..69428af0d73 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/deprecate-libraries.t/run.t @@ -0,0 +1,37 @@ +The libraries field is deprecated + $ cat > dune << EOF + > (library + > (public_name bar.foo) + > (name foo)) + > + > (rocq.theory + > (name bar) + > (libraries bar.foo)) + > EOF + + $ dune build + File "dune", line 7, characters 2-11: + 7 | (libraries bar.foo)) + ^^^^^^^^^ + Error: Unknown field "libraries" + [1] + +Having both a libraries and plugins field is an error + $ cat > dune << EOF + > (library + > (public_name bar.foo) + > (name foo)) + > + > (rocq.theory + > (name bar) + > (libraries bar.foo) + > (plugins bar.foo)) + > EOF + + $ dune build + File "dune", line 7, characters 2-11: + 7 | (libraries bar.foo) + ^^^^^^^^^ + Error: Unknown field "libraries" + [1] + diff --git a/test/blackbox-tests/test-cases/rocq/deprecate-public_name.t/Foo.opam b/test/blackbox-tests/test-cases/rocq/deprecate-public_name.t/Foo.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/deprecate-public_name.t/a.v b/test/blackbox-tests/test-cases/rocq/deprecate-public_name.t/a.v new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/deprecate-public_name.t/dune-project b/test/blackbox-tests/test-cases/rocq/deprecate-public_name.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/deprecate-public_name.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/deprecate-public_name.t/run.t b/test/blackbox-tests/test-cases/rocq/deprecate-public_name.t/run.t new file mode 100644 index 00000000000..5e816c3b26e --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/deprecate-public_name.t/run.t @@ -0,0 +1,28 @@ +public_name field is deprecated + $ cat > dune << EOF + > (rocq.theory + > (name foo) + > (public_name Foo)) + > EOF + + $ dune build + File "dune", line 3, characters 2-13: + 3 | (public_name Foo)) + ^^^^^^^^^^^ + Error: Unknown field "public_name" + [1] + +both package and public_name field is an error + $ cat > dune << EOF + > (rocq.theory + > (name foo) + > (public_name Foo) + > (package Foo)) + > EOF + + $ dune build + File "dune", line 3, characters 2-13: + 3 | (public_name Foo) + ^^^^^^^^^^^ + Error: Unknown field "public_name" + [1] diff --git a/test/blackbox-tests/test-cases/rocq/dune b/test/blackbox-tests/test-cases/rocq/dune new file mode 100644 index 00000000000..a6503f8c0cb --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/dune @@ -0,0 +1,9 @@ +; Coq for macos does not support native compilation yet. +; TODO Enable tests when ready + +(cram + (applies_to :whole_subtree) + (deps %{bin:rocq} scrub_coq_args.sh) + (alias runtest-rocq) + (enabled_if + (= %{env:DUNE_ROCQ_TEST=disable} enable))) diff --git a/test/blackbox-tests/test-cases/rocq/duplicate-theory-project.t/dune-project b/test/blackbox-tests/test-cases/rocq/duplicate-theory-project.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/duplicate-theory-project.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/duplicate-theory-project.t/run.t b/test/blackbox-tests/test-cases/rocq/duplicate-theory-project.t/run.t new file mode 100644 index 00000000000..572ec0e111f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/duplicate-theory-project.t/run.t @@ -0,0 +1,21 @@ +Duplicate theories in the same project should be caught by Dune: + + $ mkdir A + $ mkdir B + + $ cat > A/dune << EOF + > (rocq.theory + > (name foo)) + > EOF + + $ cat > B/dune << EOF + > (rocq.theory + > (name foo)) + > EOF + + $ dune build + Error: Rocq theory foo is defined twice: + - theory foo in A/dune:2 + - theory foo in B/dune:2 + -> required by alias default + [1] diff --git a/test/blackbox-tests/test-cases/rocq/duplicate-theory.t/dune-project b/test/blackbox-tests/test-cases/rocq/duplicate-theory.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/duplicate-theory.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/duplicate-theory.t/run.t b/test/blackbox-tests/test-cases/rocq/duplicate-theory.t/run.t new file mode 100644 index 00000000000..d5231a8d3f4 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/duplicate-theory.t/run.t @@ -0,0 +1,17 @@ +Duplicate theories should be caught by Dune: + + $ cat > dune << EOF + > (rocq.theory + > (name foo)) + > + > (rocq.theory + > (name foo)) + > EOF + +BUG The directory target is found before the theory + + $ dune build + Error: Rocq theory foo is defined twice: + - theory foo in dune:5 + - theory foo in dune:2 + [1] diff --git a/test/blackbox-tests/test-cases/rocq/empty-modules.t/dune-project b/test/blackbox-tests/test-cases/rocq/empty-modules.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/empty-modules.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/empty-modules.t/run.t b/test/blackbox-tests/test-cases/rocq/empty-modules.t/run.t new file mode 100644 index 00000000000..c78feee4457 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/empty-modules.t/run.t @@ -0,0 +1,11 @@ +We test that the empty modules field in a rocq.theory stanza is handled +correctly. + + $ cat > dune << EOF + > (rocq.theory + > (name foo) + > (modules)) + > EOF + +Builds fine as expected. + $ dune build 2>&1 diff --git a/test/blackbox-tests/test-cases/rocq/env.t b/test/blackbox-tests/test-cases/rocq/env.t new file mode 100644 index 00000000000..381ce64dd54 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/env.t @@ -0,0 +1,391 @@ +Test cases for rocq.theory and the env stanza to set coq flags, we +test all possibilities [Y/N/I/A] = [Yes/No/Inherited/Absent] : + +| dune | dune-workspace | +| A | A | +| A | I | +| A | N | +| A | Y | +| I | A | +| I | I | +| I | N | +| I | Y | +| N | A | +| N | I | +| N | N | +| N | Y | +| Y | A | +| Y | I | +| Y | N | +| Y | Y | + +Common files + + $ cat > foo.v < (* This will only compile with -type-in-type *) + > Definition t := Type. + > Definition false : t := t. + > EOF + + $ cat > dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + +Cases for A + + $ cat > dune < (rocq.theory + > (name basic)) + > EOF + +Case A / A + + $ cat > dune-workspace < (lang dune 3.21) + > EOF + + $ dune build @all + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + + $ dune build @all --profile unsound + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + +Case A / I + + $ cat > dune-workspace < (lang dune 3.21) + > (env (unsound (rocq (flags :standard)))) + > EOF + + $ dune build @all + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + + $ dune build @all --profile unsound + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + +Case A / N + + $ cat > dune-workspace < (lang dune 3.21) + > (env (unsound (rocq (flags )))) + > EOF + + $ dune build @all + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + + $ dune build @all --profile unsound + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + +Case A / Y + + $ cat > dune-workspace < (lang dune 3.21) + > (env (unsound (rocq (flags -type-in-type)))) + > EOF + + $ dune build @all + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + + $ dune build @all --profile unsound + +Cases for I + + $ cat > dune < (rocq.theory + > (name basic)) + > (env (unsound (rocq (flags :standard)))) + > EOF + +Case I / A + + $ cat > dune-workspace < (lang dune 3.21) + > EOF + + $ dune build @all + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + + $ dune build @all --profile unsound + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + +Case I / I + + $ cat > dune-workspace < (lang dune 3.21) + > (env (unsound (rocq (flags :standard)))) + > EOF + + $ dune build @all + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + + $ dune build @all --profile unsound + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + +Case I / N + + $ cat > dune-workspace < (lang dune 3.21) + > (env (unsound (rocq (flags)))) + > EOF + + $ dune build @all + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + + $ dune build @all --profile unsound + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + +Case I / Y + + $ cat > dune-workspace < (lang dune 3.21) + > (env (unsound (rocq (flags -type-in-type)))) + > EOF + + $ dune build @all + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + + $ dune build @all --profile unsound + +Cases for N + + $ cat > dune < (rocq.theory + > (name basic)) + > (env (unsound (rocq (flags)))) + > EOF + +Case N / A + + $ cat > dune-workspace < (lang dune 3.21) + > EOF + + $ dune build @all + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + + $ dune build @all --profile unsound + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + +Case N / I + + $ cat > dune-workspace < (lang dune 3.21) + > (env (unsound (rocq (flags :standard)))) + > EOF + + $ dune build @all + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + + $ dune build @all --profile unsound + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + +Case N / N + + $ cat > dune-workspace < (lang dune 3.21) + > (env (unsound (rocq (flags )))) + > EOF + + $ dune build @all + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + + $ dune build @all --profile unsound + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + +Case N / Y + + $ cat > dune-workspace < (lang dune 3.21) + > (env (unsound (rocq (flags -type-in-type)))) + > EOF + + $ dune build @all + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + + $ dune build @all --profile unsound + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + +Cases for Y + $ cat > dune < (rocq.theory + > (name basic)) + > (env (unsound (rocq (flags -type-in-type)))) + > EOF + +Case Y / A + + $ cat > dune-workspace < (lang dune 3.21) + > EOF + + $ dune build @all + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + + $ dune build @all --profile unsound + +Case Y / I + + $ cat > dune-workspace < (lang dune 3.21) + > (env (unsound (rocq (flags :standard)))) + > EOF + + $ dune build @all + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + + $ dune build @all --profile unsound + +Case Y / N + + $ cat > dune-workspace < (lang dune 3.21) + > (env (unsound (rocq (flags)))) + > EOF + + $ dune build @all + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + + $ dune build @all --profile unsound + +Case Y / Y + + $ cat > dune-workspace < (lang dune 3.21) + > (env (unsound (rocq (flags -type-in-type)))) + > EOF + + $ dune build @all + File "./foo.v", line 3, characters 24-25: + Error: + The term "t" has type "Type" while it is expected to have type + "t" (universe inconsistency: Cannot enforce t.u0 < t.u0 because t.u0 = t.u0). + + [1] + + $ dune build @all --profile unsound diff --git a/test/blackbox-tests/test-cases/rocq/extraction/extract.t b/test/blackbox-tests/test-cases/rocq/extraction/extract.t new file mode 100644 index 00000000000..e00b00debf2 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/extraction/extract.t @@ -0,0 +1,56 @@ + $ cat >dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + + $ cat >extract.v < Definition nb (b : bool) : bool := + > match b with + > | false => true + > | true => false + > end. + > + > Require Extraction. + > Separate Extraction nb. + > EOF + + $ cat >dune < (rocq.extraction + > (prelude extract) + > (extracted_modules Datatypes extract)) + > + > (executable + > (name foo)) + > EOF + + $ cat >foo.ml < open Datatypes + > let () = + > print_endline ( + > match Extract.nb Datatypes.Coq_true with + > | Coq_true -> "true" + > | Coq_false -> "false" + > ) + > EOF + + $ dune exec ./foo.exe + File "./extract.v", line 8, characters 0-23: + Warning: Setting extraction output directory by default to + "$TESTCASE_ROOT/_build/default". + Use "Set Extraction Output Directory" or command line option + "-output-directory" to set a different directory for extracted files to + appear in. [extraction-default-directory,extraction,default] + false + $ ls _build/default + Datatypes.ml + Datatypes.mli + extract.glob + extract.ml + extract.mli + extract.v + extract.vo + extract.vok + extract.vos + foo.exe + foo.ml + foo.mli diff --git a/test/blackbox-tests/test-cases/rocq/extraction/extraction-patch.t/dune b/test/blackbox-tests/test-cases/rocq/extraction/extraction-patch.t/dune new file mode 100644 index 00000000000..bb6a9e520db --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/extraction/extraction-patch.t/dune @@ -0,0 +1,14 @@ +(executable + (name my_prog)) + +(rule + (target my_coq_file.ml) + (deps extraction/my_coq_file.ml) + (action + (with-stdout-to %{target} + ; here you patch stuff + (cat %{deps})))) + +(copy_files extraction/Datatypes.ml) +(copy_files extraction/Datatypes.mli) +(copy_files extraction/my_coq_file.mli) diff --git a/test/blackbox-tests/test-cases/rocq/extraction/extraction-patch.t/dune-project b/test/blackbox-tests/test-cases/rocq/extraction/extraction-patch.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/extraction/extraction-patch.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/extraction/extraction-patch.t/extraction/dune b/test/blackbox-tests/test-cases/rocq/extraction/extraction-patch.t/extraction/dune new file mode 100644 index 00000000000..2e135f81db8 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/extraction/extraction-patch.t/extraction/dune @@ -0,0 +1,4 @@ +(rocq.extraction + (mode vo) + (prelude my_coq_file) + (extracted_modules Datatypes my_coq_file)) diff --git a/test/blackbox-tests/test-cases/rocq/extraction/extraction-patch.t/extraction/my_coq_file.v b/test/blackbox-tests/test-cases/rocq/extraction/extraction-patch.t/extraction/my_coq_file.v new file mode 100644 index 00000000000..9a6003556c6 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/extraction/extraction-patch.t/extraction/my_coq_file.v @@ -0,0 +1,8 @@ +Definition nb (b : bool) : bool := + match b with + | false => true + | true => false + end. + +Require Extraction. +Separate Extraction nb. diff --git a/test/blackbox-tests/test-cases/rocq/extraction/extraction-patch.t/my_prog.ml b/test/blackbox-tests/test-cases/rocq/extraction/extraction-patch.t/my_prog.ml new file mode 100644 index 00000000000..137c750150a --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/extraction/extraction-patch.t/my_prog.ml @@ -0,0 +1,10 @@ +let bool_to_string (b : Datatypes.bool) : string = + match b with + | Datatypes.Coq_true -> "true" + | Datatypes.Coq_false -> "false" + +let () = +Datatypes.Coq_true +|> My_coq_file.nb +|> bool_to_string +|> Printf.printf "Result: %s\n" \ No newline at end of file diff --git a/test/blackbox-tests/test-cases/rocq/extraction/extraction-patch.t/run.t b/test/blackbox-tests/test-cases/rocq/extraction/extraction-patch.t/run.t new file mode 100644 index 00000000000..73573a39ad1 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/extraction/extraction-patch.t/run.t @@ -0,0 +1,27 @@ + + $ dune build + File "./my_coq_file.v", line 8, characters 0-23: + Warning: Setting extraction output directory by default to + "$TESTCASE_ROOT/_build/default/extraction". + Use "Set Extraction Output Directory" or command line option + "-output-directory" to set a different directory for extracted files to + appear in. [extraction-default-directory,extraction,default] + + $ ls _build/default + Datatypes.ml + Datatypes.mli + extraction + my_coq_file.ml + my_coq_file.mli + my_prog.exe + my_prog.ml + my_prog.mli + + $ cat _build/default/Datatypes.ml + + type bool = + | Coq_true + | Coq_false + + $ dune exec -- ./my_prog.exe + Result: false diff --git a/test/blackbox-tests/test-cases/rocq/failed-config.t/dune-project b/test/blackbox-tests/test-cases/rocq/failed-config.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/failed-config.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/failed-config.t/run.t b/test/blackbox-tests/test-cases/rocq/failed-config.t/run.t new file mode 100644 index 00000000000..f7e0e549a12 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/failed-config.t/run.t @@ -0,0 +1,145 @@ +Here we test what happens when rocq --config or --print-version fails in an unexpected way +and how dune reacts to this failure. + +First we create a wrapper around coqc so we can make it fail. It should only fail on +--config and --print-version. + $ mkdir bin + $ cat > bin/rocq <<'EOF' + > #!/bin/sh + > if [ $1 = --config ] && [ -n "$FAIL_CONFIG" ]; then + > echo "rocq --config has failed for some reason" >&2 + > exit 1 + > elif [ $1 = --print-version ] && [ -n "$FAIL_VERSION" ]; then + > echo "rocq --print-version has failed for some reason" >&2 + > exit 1 + > fi + > EOF + > echo "$(which rocq) \$@" >> bin/rocq + > chmod +x bin/rocq + + $ export PATH=$PWD/bin:$PATH + +To make sure these are working correctly we test them. + +These should succeed. + $ rocq --print-version > /dev/null + $ rocq --config > /dev/null +These should fail. + $ FAIL_VERSION=1 \ + > rocq --print-version 2> /dev/null + [1] + $ FAIL_CONFIG=1 \ + > rocq --config 2> /dev/null + [1] + +Now we create a simple project that uses this coqc wrapper, should +fail when the stdlib cannot be determined + + $ cat > dune < (rocq.theory + > (flags -noinit) + > (name foo)) + > + > (rule + > (deps + > (env_var FAIL_VERSION) + > (env_var FAIL_CONFIG)) + > (action + > (write-file a.v ""))) + > EOF + +Should fail: first warning that installed theories are being skipped due to the +failure, then, as the library requires the stdlib, it fails: + $ FAIL_CONFIG=1 \ + > dune build + Warning: Skipping installed theories due to 'rocq --config' failure: + - $TESTCASE_ROOT/bin/rocq --config failed with exit code 1. + Hint: Try running 'rocq --config' manually to see the error. + Couldn't find Rocq standard library, and theory is not using (stdlib no) + -> required by _build/default/.foo.theory.d + -> required by alias all + -> required by alias default + [1] + +Here we build a simple Coq project. Neither a failing --config or --print-version should +block this as it doesn't depend on the stdlib. + + $ cat > dune < (rocq.theory + > (flags -noinit) + > (name foo) + > (stdlib no)) + > + > (rule + > (deps + > (env_var FAIL_VERSION) + > (env_var FAIL_CONFIG)) + > (action + > (write-file a.v ""))) + > EOF + +Should succeed, warning that installed theories are being skipped due to the +failure (c.f. #8958): + $ FAIL_CONFIG=1 \ + > dune build + Warning: Skipping installed theories due to 'rocq --config' failure: + - $TESTCASE_ROOT/bin/rocq --config failed with exit code 1. + Hint: Try running 'rocq --config' manually to see the error. + + $ FAIL_VERSION=1 \ + > dune build + + $ dune build + +Here we query the version of Coq. Due to the expansion of %{coq:_} macros we need coqc +--config. A failing --print-version or --config will block this value from being realised. + + $ cat > dune < (rule + > (alias version) + > (action + > (echo %{rocq:version}))) + > EOF + +Succeeds after PR #10631 + $ FAIL_CONFIG=1 \ + > dune build @version + 9.1.0 + +Should fail. + $ FAIL_VERSION=1 \ + > dune build @version + File "dune", line 4, characters 8-23: + 4 | (echo %{rocq:version}))) + ^^^^^^^^^^^^^^^ + Error: Could not expand %{rocq:version} as running rocq failed. + $TESTCASE_ROOT/bin/rocq --print-version failed with exit code 1. + [1] + +Here we query the config. A failing --config will block this value from being realised +however a failing --print-version will not. + + $ cat > dune < (rule + > (alias config) + > (action + > (echo %{rocq:rocqlib}))) + > EOF + +Should fail. + $ export coqlib="$(rocq -config | grep COQLIB | sed 's/COQLIB=//')" + $ FAIL_CONFIG=1 \ + > dune build @config + File "dune", line 4, characters 8-23: + 4 | (echo %{rocq:rocqlib}))) + ^^^^^^^^^^^^^^^ + Error: Could not expand %{rocq:rocqlib} as running rocq failed. + $TESTCASE_ROOT/bin/rocq --config failed with exit code 1. + [1] + +Should succeed. + $ FAIL_VERSION=1 \ + > dune build @config | sed "s,$coqlib,COQLIB," > /dev/null + +Should succeed. + $ dune build @config | sed "s,$coqlib,COQLIB," > /dev/null diff --git a/test/blackbox-tests/test-cases/rocq/flags.t b/test/blackbox-tests/test-cases/rocq/flags.t new file mode 100644 index 00000000000..79434151313 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/flags.t @@ -0,0 +1,184 @@ +Test cases to check Coq's flag setting is correct: + + $ cat > dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + + $ cat > foo.v < Definition t := 3. + > EOF + +Test case: default flags + + $ cat > dune < (rocq.theory + > (name foo)) + > EOF + + $ dune build foo.vo && tail -n 1 _build/log | ./scrub_coq_args.sh + rocq compile -q + -w -deprecated-native-compiler-option + -w -native-compiler-disabled + -native-compiler ondemand + -boot + -R coq/theories Corelib + -R . foo + foo.v + +TC: :standard + + $ cat > dune < (rocq.theory + > (name foo) + > (flags :standard)) + > EOF + + $ rm _build/default/foo.vo + $ dune build foo.vo && tail -n 1 _build/log | ./scrub_coq_args.sh + rocq compile -q + -w -deprecated-native-compiler-option + -w -native-compiler-disabled + -native-compiler ondemand + -boot + -R coq/theories Corelib + -R . foo + foo.v + +TC: override :standard + + $ cat > dune < (rocq.theory + > (name foo) + > (flags )) + > EOF + + $ dune build foo.vo && tail -n 1 _build/log | ./scrub_coq_args.sh + rocq compile + -w -deprecated-native-compiler-option + -w -native-compiler-disabled + -native-compiler ondemand + -boot + -R coq/theories Corelib + -R . foo + foo.v + +TC: add to :standard + + $ cat > dune < (rocq.theory + > (name foo) + > (flags :standard -type-in-type)) + > EOF + + $ dune build foo.vo && tail -n 1 _build/log | ./scrub_coq_args.sh + rocq compile -q -type-in-type + -w -deprecated-native-compiler-option + -w -native-compiler-disabled + -native-compiler ondemand + -boot + -R coq/theories Corelib + -R . foo + foo.v + +TC: extend in workspace + override standard + + $ cat > dune < (rocq.theory + > (name foo) + > (flags :standard)) + > EOF + + $ cat > dune-workspace < (lang dune 3.21) + > (env (dev (rocq (flags -type-in-type)))) + > EOF + + $ dune build foo.vo && tail -n 1 _build/log | ./scrub_coq_args.sh + rocq compile -type-in-type + -w -deprecated-native-compiler-option + -w -native-compiler-disabled + -native-compiler ondemand + -boot + -R coq/theories Corelib + -R . foo + foo.v + +TC: extend in workspace + override standard + + $ cat > dune-workspace < (lang dune 3.21) + > (env (dev (rocq (flags :standard -type-in-type)))) + > EOF + + $ dune build foo.vo && tail -n 1 _build/log | ./scrub_coq_args.sh + rocq compile -q -type-in-type + -w -deprecated-native-compiler-option + -w -native-compiler-disabled + -native-compiler ondemand + -boot + -R coq/theories Corelib + -R . foo + foo.v + +TC: extend in dune (env) + override standard + + $ cat > dune < (rocq.theory + > (name foo)) + > (env (dev (rocq (flags -type-in-type)))) + > EOF + + $ rm -rf _build/default/foo.vo + $ dune build foo.vo && tail -n 1 _build/log | ./scrub_coq_args.sh + rocq compile -type-in-type + -w -deprecated-native-compiler-option + -w -native-compiler-disabled + -native-compiler ondemand + -boot + -R coq/theories Corelib + -R . foo + foo.v + +TC: extend in dune (env) + standard + + $ cat > dune < (rocq.theory + > (name foo)) + > (env (dev (rocq (flags :standard -type-in-type)))) + > EOF + + $ rm -rf _build/default/foo.vo + $ dune build foo.vo && tail -n 1 _build/log | ./scrub_coq_args.sh + rocq compile -q -type-in-type -type-in-type + -w -deprecated-native-compiler-option + -w -native-compiler-disabled + -native-compiler ondemand + -boot + -R coq/theories Corelib + -R . foo + foo.v + +TC: extend in dune (env) + workspace + standard + + $ cat > dune < (rocq.theory + > (name foo)) + > (env (dev (rocq (flags :standard -bt)))) + > EOF + + $ cat > dune-workspace < (lang dune 3.21) + > (env (dev (rocq (flags :standard -type-in-type)))) + > EOF + + $ rm -rf _build/default/foo.vo + $ dune build foo.vo && tail -n 1 _build/log | ./scrub_coq_args.sh + rocq compile -q -type-in-type -bt + -w -deprecated-native-compiler-option + -w -native-compiler-disabled + -native-compiler ondemand + -boot + -R coq/theories Corelib + -R . foo + foo.v diff --git a/test/blackbox-tests/test-cases/rocq/github3624.t b/test/blackbox-tests/test-cases/rocq/github3624.t new file mode 100644 index 00000000000..b859c01095e --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/github3624.t @@ -0,0 +1,22 @@ +This used to be a reproduction case for #3624, where dune created a dune-project +with an incorrect using line. Since we dropped support for automatically +creating the dune-project file, this is now testing that the error message is +good when the coq extension is not enabled. + + $ cat >dune < (rocq.theory + > (name foo)) + > EOF + $ dune build + File ".", line 1, characters 0-0: + Warning: No dune-project file has been found in directory ".". A default one + is assumed but the project might break when dune is upgraded. Please create a + dune-project file. + Hint: generate the project file with: $ dune init project + File "dune", lines 1-2, characters 0-25: + 1 | (rocq.theory + 2 | (name foo)) + Error: 'rocq.theory' is available only when rocq is enabled in the + dune-project file. You must enable it using (using rocq 0.11) in your + dune-project file. + [1] diff --git a/test/blackbox-tests/test-cases/rocq/github5532.t b/test/blackbox-tests/test-cases/rocq/github5532.t new file mode 100644 index 00000000000..60f4be67d51 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/github5532.t @@ -0,0 +1,27 @@ +Reproducing test case for #5532. + + $ cat >foo.v < Lemma dummy : True. + > Proof. idtac "A". Qed. + > EOF + + $ cat >dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + + $ cat >dune < (rocq.theory + > (name basic)) + > EOF + + $ dune build + File "dune", lines 1-2, characters 0-27: + 1 | (rocq.theory + 2 | (name basic)) + A + File "./foo.v", line 2, characters 18-22: + Error: (in proof dummy): Attempt to save an incomplete proof + (there are remaining open goals). + + [1] diff --git a/test/blackbox-tests/test-cases/rocq/lang_08_warning_disable/run.t b/test/blackbox-tests/test-cases/rocq/lang_08_warning_disable/run.t new file mode 100644 index 00000000000..8553a175940 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/lang_08_warning_disable/run.t @@ -0,0 +1,29 @@ +Test that the warning for coq lang 0.8 can be disabled + + $ cat > dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + + $ cat > dune < (rocq.theory + > (name Foo)) + > EOF + + $ cat > a.v < Definition a := Type. + > EOF + + $ dune build + +We get the warning again, even on a zero-build: + + $ dune build + + $ cat > dune-project < (lang dune 3.21) + > (using rocq 0.11) + > (warnings (deprecated_coq_lang_lt_08 disabled)) + > EOF + + $ dune build diff --git a/test/blackbox-tests/test-cases/rocq/lazy-lib.t b/test/blackbox-tests/test-cases/rocq/lazy-lib.t new file mode 100644 index 00000000000..2bf15537b5f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/lazy-lib.t @@ -0,0 +1,25 @@ +We test that the calls to coqc -config in scope.ml is lazy enough that it will +not be called unless necessary. + +We test this using a dummy coqc that will fail if it is called. + + $ cat > coqc << EOF + > #!/bin/sh + > exit 5 + > EOF + $ chmod +x coqc + +We add this to path: + + $ export PATH=$PWD:$PATH + +Next we create an empty coq project: + + $ cat > dune-project << EOF + > (lang dune 3.21) + > (using rocq 0.11) + > EOF + +Finally we run dune build: + + $ dune build diff --git a/test/blackbox-tests/test-cases/rocq/main.t b/test/blackbox-tests/test-cases/rocq/main.t new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/ml-lib.t/dune-project b/test/blackbox-tests/test-cases/rocq/ml-lib.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/ml-lib.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/ml-lib.t/ml_lib.opam b/test/blackbox-tests/test-cases/rocq/ml-lib.t/ml_lib.opam new file mode 100644 index 00000000000..8d1c8b69c3f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/ml-lib.t/ml_lib.opam @@ -0,0 +1 @@ + diff --git a/test/blackbox-tests/test-cases/rocq/ml-lib.t/run.t b/test/blackbox-tests/test-cases/rocq/ml-lib.t/run.t new file mode 100644 index 00000000000..cda5721cf90 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/ml-lib.t/run.t @@ -0,0 +1 @@ + $ dune build @all diff --git a/test/blackbox-tests/test-cases/rocq/ml-lib.t/src_a/dune b/test/blackbox-tests/test-cases/rocq/ml-lib.t/src_a/dune new file mode 100644 index 00000000000..b733e847961 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/ml-lib.t/src_a/dune @@ -0,0 +1,7 @@ +(library + (public_name ml_lib.ml_plugin_a) + (name ml_plugin_a) + (flags :standard -rectypes) + (libraries rocq-runtime.plugins.ltac)) + +(rocq.pp (modules gram)) diff --git a/test/blackbox-tests/test-cases/rocq/ml-lib.t/src_a/gram.mlg b/test/blackbox-tests/test-cases/rocq/ml-lib.t/src_a/gram.mlg new file mode 100644 index 00000000000..4724c8819a9 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/ml-lib.t/src_a/gram.mlg @@ -0,0 +1,9 @@ +DECLARE PLUGIN "ml_lib.ml_plugin_a" + +{ + +(* We don't use any coqpp specific macros as to make the test more + resilient on different Coq versions *) +let foo = 3 + +} diff --git a/test/blackbox-tests/test-cases/rocq/ml-lib.t/src_a/gram.mli b/test/blackbox-tests/test-cases/rocq/ml-lib.t/src_a/gram.mli new file mode 100644 index 00000000000..bcc533d2e62 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/ml-lib.t/src_a/gram.mli @@ -0,0 +1 @@ +val foo : int diff --git a/test/blackbox-tests/test-cases/rocq/ml-lib.t/src_a/ml_plugin_a.mlpack b/test/blackbox-tests/test-cases/rocq/ml-lib.t/src_a/ml_plugin_a.mlpack new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/ml-lib.t/src_a/simple.ml b/test/blackbox-tests/test-cases/rocq/ml-lib.t/src_a/simple.ml new file mode 100644 index 00000000000..555166169c9 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/ml-lib.t/src_a/simple.ml @@ -0,0 +1,2 @@ +let a = 3 +let _ = a diff --git a/test/blackbox-tests/test-cases/rocq/ml-lib.t/src_b/dune b/test/blackbox-tests/test-cases/rocq/ml-lib.t/src_b/dune new file mode 100644 index 00000000000..e40e980f8d4 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/ml-lib.t/src_b/dune @@ -0,0 +1,5 @@ +(library + (public_name ml_lib.ml_plugin_b) + (name ml_plugin_b) + (flags :standard -rectypes) + (libraries ml_plugin_a)) diff --git a/test/blackbox-tests/test-cases/rocq/ml-lib.t/src_b/ml_plugin_b.mlpack b/test/blackbox-tests/test-cases/rocq/ml-lib.t/src_b/ml_plugin_b.mlpack new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/ml-lib.t/src_b/simple_b.ml b/test/blackbox-tests/test-cases/rocq/ml-lib.t/src_b/simple_b.ml new file mode 100644 index 00000000000..04ea5df11e8 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/ml-lib.t/src_b/simple_b.ml @@ -0,0 +1 @@ +let _ = Ml_plugin_a.Simple.a diff --git a/test/blackbox-tests/test-cases/rocq/ml-lib.t/theories/a.v b/test/blackbox-tests/test-cases/rocq/ml-lib.t/theories/a.v new file mode 100644 index 00000000000..0bcda0104aa --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/ml-lib.t/theories/a.v @@ -0,0 +1,3 @@ +Declare ML Module "ml_lib.ml_plugin_a". +Declare ML Module "ml_lib.ml_plugin_b". + diff --git a/test/blackbox-tests/test-cases/rocq/ml-lib.t/theories/dune b/test/blackbox-tests/test-cases/rocq/ml-lib.t/theories/dune new file mode 100644 index 00000000000..1cb44962beb --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/ml-lib.t/theories/dune @@ -0,0 +1,6 @@ +(rocq.theory + (name Plugin) + (package ml_lib) + (synopsis "Test Plugin") + (plugins ml_lib.ml_plugin_b) + (modules :standard)) diff --git a/test/blackbox-tests/test-cases/rocq/modules_flags.t b/test/blackbox-tests/test-cases/rocq/modules_flags.t new file mode 100644 index 00000000000..fa121fe24c7 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/modules_flags.t @@ -0,0 +1,34 @@ +Reproducing test case for https://github.com/ocaml/dune/issues/12638. + + $ cat > dune-project < (lang dune 3.21) + > (using rocq 0.11) + > EOF + + $ touch foo.v bar.v + + $ cat > dune < (rocq.theory + > (name a) + > (modules_flags + > (foo (-w -deprecated-since-8.15)) + > (bar (-w -deprecated-since-8.16)))) + > EOF + + $ dune build foo.vo && tail -n 1 _build/log | ./scrub_coq_args.sh | grep deprecated-since + -w -deprecated-since-8.15 + $ dune build bar.vo && tail -n 1 _build/log | ./scrub_coq_args.sh | grep deprecated-since + -w -deprecated-since-8.16 + $ dune clean + + $ cat > dune < (rocq.theory + > (name a) + > (modules_flags + > (bar (-w -deprecated-since-8.16)))) + > EOF + + $ dune build foo.vo && tail -n 1 _build/log | ./scrub_coq_args.sh | grep deprecated-since + [1] + $ dune build bar.vo && tail -n 1 _build/log | ./scrub_coq_args.sh | grep deprecated-since + -w -deprecated-since-8.16 diff --git a/test/blackbox-tests/test-cases/rocq/no-rebuild-on-dep-change.t b/test/blackbox-tests/test-cases/rocq/no-rebuild-on-dep-change.t new file mode 100644 index 00000000000..2bf5fd39d3e --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/no-rebuild-on-dep-change.t @@ -0,0 +1,17 @@ + $ echo "(rocq.theory (name bug) (mode vo))" > dune + $ echo "(lang dune 3.21)" > dune-project + $ echo "(using rocq 0.11)" >> dune-project + $ touch root.v leaf.v + $ dune build + $ find _build -name "*.vo" | sort + _build/default/leaf.vo + _build/default/root.vo + $ echo "Require Import bug.root." >> leaf.v + +This test makes sure that a full rebuild is not triggered when the output of +coqdep is changed. + +This is as expected: + $ dune build --display=short + rocq .bug.theory.d + rocq leaf.{glob,vo} diff --git a/test/blackbox-tests/test-cases/rocq/no-stdlib.t/bar.v b/test/blackbox-tests/test-cases/rocq/no-stdlib.t/bar.v new file mode 100644 index 00000000000..53e0ce1b152 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/no-stdlib.t/bar.v @@ -0,0 +1 @@ +Definition mynat := nat. diff --git a/test/blackbox-tests/test-cases/rocq/no-stdlib.t/dune b/test/blackbox-tests/test-cases/rocq/no-stdlib.t/dune new file mode 100644 index 00000000000..866382968f0 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/no-stdlib.t/dune @@ -0,0 +1,5 @@ +(rocq.theory + (name basic) + (package no-stdlib) + (stdlib no) + (synopsis "Test Coq library")) diff --git a/test/blackbox-tests/test-cases/rocq/no-stdlib.t/dune-project b/test/blackbox-tests/test-cases/rocq/no-stdlib.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/no-stdlib.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/no-stdlib.t/foo.v b/test/blackbox-tests/test-cases/rocq/no-stdlib.t/foo.v new file mode 100644 index 00000000000..67f3fb42097 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/no-stdlib.t/foo.v @@ -0,0 +1 @@ +From Corelib Require Import Prelude. diff --git a/test/blackbox-tests/test-cases/rocq/no-stdlib.t/no-stdlib.opam b/test/blackbox-tests/test-cases/rocq/no-stdlib.t/no-stdlib.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/no-stdlib.t/run.t b/test/blackbox-tests/test-cases/rocq/no-stdlib.t/run.t new file mode 100644 index 00000000000..8e1a7911f0e --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/no-stdlib.t/run.t @@ -0,0 +1,21 @@ +Test that when `(stdlib no)` is provided, the standard library is not bound to `Coq` +and the prelude is not imported; we expect the below two tests to fail. + + $ dune build --display=short foo.vo + rocq .basic.theory.d + Warning: in file foo.v, library Prelude is required + from root Corelib and has not been found in the loadpath! + [module-not-found,filesystem,default] + rocq foo.{glob,vo} (exit 1) + File "./foo.v", line 1, characters 28-35: + Error: Cannot find a physical path bound to logical path + Prelude with prefix Corelib. + + [1] + + $ dune build --display=short bar.vo + rocq bar.{glob,vo} (exit 1) + File "./bar.v", line 1, characters 20-23: + Error: The reference nat was not found in the current environment. + + [1] diff --git a/test/blackbox-tests/test-cases/rocq/per_file_flags.t/bar.v b/test/blackbox-tests/test-cases/rocq/per_file_flags.t/bar.v new file mode 100644 index 00000000000..1845f3b657f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/per_file_flags.t/bar.v @@ -0,0 +1,6 @@ +From basic Require Import foo. + +Definition mynum (i : mynat) := 3. + +(* This should not emit a warning *) +Variable (A : nat). diff --git a/test/blackbox-tests/test-cases/rocq/per_file_flags.t/base.opam b/test/blackbox-tests/test-cases/rocq/per_file_flags.t/base.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/per_file_flags.t/dune b/test/blackbox-tests/test-cases/rocq/per_file_flags.t/dune new file mode 100644 index 00000000000..7eb30a9b19a --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/per_file_flags.t/dune @@ -0,0 +1,14 @@ +(rocq.theory + (name basic) + (package base) + (modules :standard) + (flags :standard -w declaration-outside-section) + (modules_flags + (bar :standard -w -declaration-outside-section)) + (synopsis "Test Coq library")) + +; foo (:standard -w -declaration-outside-section -w declaration-outside-section))) + +(rule + (alias default) + (action (echo "%{read:base.install}"))) diff --git a/test/blackbox-tests/test-cases/rocq/per_file_flags.t/dune-project b/test/blackbox-tests/test-cases/rocq/per_file_flags.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/per_file_flags.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/per_file_flags.t/foo.v b/test/blackbox-tests/test-cases/rocq/per_file_flags.t/foo.v new file mode 100644 index 00000000000..fb5eea8e22c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/per_file_flags.t/foo.v @@ -0,0 +1,4 @@ +Definition mynat := nat. + +(* This should emit a warning *) +Variable (A : nat). diff --git a/test/blackbox-tests/test-cases/rocq/per_file_flags.t/run.t b/test/blackbox-tests/test-cases/rocq/per_file_flags.t/run.t new file mode 100644 index 00000000000..172cee1e844 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/per_file_flags.t/run.t @@ -0,0 +1,23 @@ + $ dune build --display short @all + rocq .basic.theory.d + rocq foo.{glob,vo} + File "./foo.v", line 4, characters 0-19: + Warning: Use of "Variable" or "Hypothesis" outside sections behaves as + "#[local] Parameter" or "#[local] Axiom". + [declaration-outside-section,vernacular,default] + rocq bar.{glob,vo} + + $ dune build --debug-dependency-path @default + lib: [ + "_build/install/default/lib/base/META" + "_build/install/default/lib/base/dune-package" + "_build/install/default/lib/base/opam" + ] + lib_root: [ + "_build/install/default/lib/coq/user-contrib/basic/bar.glob" {"coq/user-contrib/basic/bar.glob"} + "_build/install/default/lib/coq/user-contrib/basic/bar.v" {"coq/user-contrib/basic/bar.v"} + "_build/install/default/lib/coq/user-contrib/basic/bar.vo" {"coq/user-contrib/basic/bar.vo"} + "_build/install/default/lib/coq/user-contrib/basic/foo.glob" {"coq/user-contrib/basic/foo.glob"} + "_build/install/default/lib/coq/user-contrib/basic/foo.v" {"coq/user-contrib/basic/foo.v"} + "_build/install/default/lib/coq/user-contrib/basic/foo.vo" {"coq/user-contrib/basic/foo.vo"} + ] diff --git a/test/blackbox-tests/test-cases/rocq/plugin-meta.t/bar.opam b/test/blackbox-tests/test-cases/rocq/plugin-meta.t/bar.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/plugin-meta.t/bar.v b/test/blackbox-tests/test-cases/rocq/plugin-meta.t/bar.v new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/plugin-meta.t/dune-project b/test/blackbox-tests/test-cases/rocq/plugin-meta.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/plugin-meta.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/plugin-meta.t/foo.ml b/test/blackbox-tests/test-cases/rocq/plugin-meta.t/foo.ml new file mode 100644 index 00000000000..4b3fcfa724c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/plugin-meta.t/foo.ml @@ -0,0 +1 @@ +let foo = "bar" diff --git a/test/blackbox-tests/test-cases/rocq/plugin-meta.t/run.t b/test/blackbox-tests/test-cases/rocq/plugin-meta.t/run.t new file mode 100644 index 00000000000..fcf0dc5f368 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/plugin-meta.t/run.t @@ -0,0 +1,15 @@ +The META file for plugins is built before calling coqdep + $ cat > dune << EOF + > (library + > (public_name bar.foo) + > (name foo)) + > + > (rocq.theory + > (name bar) + > (plugins bar.foo)) + > EOF + + $ dune build .bar.theory.d + $ ls _build/install/default/lib/bar + META + diff --git a/test/blackbox-tests/test-cases/rocq/plugin-private.t/bar.opam b/test/blackbox-tests/test-cases/rocq/plugin-private.t/bar.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/plugin-private.t/bar.v b/test/blackbox-tests/test-cases/rocq/plugin-private.t/bar.v new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/plugin-private.t/dune-project b/test/blackbox-tests/test-cases/rocq/plugin-private.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/plugin-private.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/plugin-private.t/foo.ml b/test/blackbox-tests/test-cases/rocq/plugin-private.t/foo.ml new file mode 100644 index 00000000000..4b3fcfa724c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/plugin-private.t/foo.ml @@ -0,0 +1 @@ +let foo = "bar" diff --git a/test/blackbox-tests/test-cases/rocq/plugin-private.t/run.t b/test/blackbox-tests/test-cases/rocq/plugin-private.t/run.t new file mode 100644 index 00000000000..5e6f17d44c1 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/plugin-private.t/run.t @@ -0,0 +1,16 @@ +In Coq >= 0.6, depending on a private library as a plugin is an error. + $ cat > dune << EOF + > (library + > (name foo)) + > + > (rocq.theory + > (name bar) + > (plugins foo)) + > EOF + + $ dune build + File "dune", line 6, characters 10-13: + 6 | (plugins foo)) + ^^^ + Error: Using private library foo as a Rocq plugin is not supported + [1] diff --git a/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/dune b/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/dune new file mode 100644 index 00000000000..7c5eb6af132 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/dune @@ -0,0 +1,3 @@ +(rule + (alias default) + (action (echo "%{read:public.install}"))) diff --git a/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/dune-project b/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/private/a.v b/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/private/a.v new file mode 100644 index 00000000000..d4389c6d37d --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/private/a.v @@ -0,0 +1 @@ +Definition foo := 3. diff --git a/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/private/dune b/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/private/dune new file mode 100644 index 00000000000..7c4ffcaf0db --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/private/dune @@ -0,0 +1,2 @@ +(rocq.theory + (name private)) diff --git a/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/public.opam b/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/public.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/public/b.v b/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/public/b.v new file mode 100644 index 00000000000..5f955f638da --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/public/b.v @@ -0,0 +1,3 @@ +From private Require a. + +Definition bar := a.foo. diff --git a/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/public/dune b/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/public/dune new file mode 100644 index 00000000000..3df65c46edb --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/public/dune @@ -0,0 +1,4 @@ +(rocq.theory + (name public) + (package public) + (theories private)) diff --git a/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/run.t b/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/run.t new file mode 100644 index 00000000000..ed5c8044053 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/public-dep-on-private.t/run.t @@ -0,0 +1,14 @@ + $ dune build --display short --debug-dependency-path + File "public/dune", line 4, characters 11-18: + 4 | (theories private)) + ^^^^^^^ + Theory "private" is private, it cannot be a dependency of a public theory. + You need to associate "private" to a package. + -> required by theory public in public/dune:2 + -> required by _build/default/public/.public.theory.d + -> required by _build/default/public/b.glob + -> required by _build/install/default/lib/coq/user-contrib/public/b.glob + -> required by _build/default/public.install + -> required by %{read:public.install} at dune:3 + -> required by alias default in dune:1 + [1] diff --git a/test/blackbox-tests/test-cases/rocq/rec-module.t/a/bar.v b/test/blackbox-tests/test-cases/rocq/rec-module.t/a/bar.v new file mode 100644 index 00000000000..b1e4f474ced --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/rec-module.t/a/bar.v @@ -0,0 +1,5 @@ +From rec_module Require Import b.foo. +From rec_module Require Import c.ooo. +From rec_module Require c.d.bar. + +Definition mynum (i : mynat) := 3 + ooo_nat + c.d.bar.bar_nat. diff --git a/test/blackbox-tests/test-cases/rocq/rec-module.t/b/foo.v b/test/blackbox-tests/test-cases/rocq/rec-module.t/b/foo.v new file mode 100644 index 00000000000..53e0ce1b152 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/rec-module.t/b/foo.v @@ -0,0 +1 @@ +Definition mynat := nat. diff --git a/test/blackbox-tests/test-cases/rocq/rec-module.t/c/d/bar.v b/test/blackbox-tests/test-cases/rocq/rec-module.t/c/d/bar.v new file mode 100644 index 00000000000..b68bd7244fb --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/rec-module.t/c/d/bar.v @@ -0,0 +1 @@ +Definition bar_nat : nat := 4. diff --git a/test/blackbox-tests/test-cases/rocq/rec-module.t/c/ooo.v b/test/blackbox-tests/test-cases/rocq/rec-module.t/c/ooo.v new file mode 100644 index 00000000000..07d40e56798 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/rec-module.t/c/ooo.v @@ -0,0 +1 @@ +Definition ooo_nat : nat := 10. diff --git a/test/blackbox-tests/test-cases/rocq/rec-module.t/dune b/test/blackbox-tests/test-cases/rocq/rec-module.t/dune new file mode 100644 index 00000000000..730430b3461 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/rec-module.t/dune @@ -0,0 +1,11 @@ +(rocq.theory + (name rec_module) + (package rec) + (modules :standard) + (synopsis "Test Coq library")) + +(include_subdirs qualified) + +(rule + (alias default) + (action (echo "%{read:rec.install}"))) diff --git a/test/blackbox-tests/test-cases/rocq/rec-module.t/dune-project b/test/blackbox-tests/test-cases/rocq/rec-module.t/dune-project new file mode 100644 index 00000000000..ecb7623a549 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/rec-module.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.21) + +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/rec-module.t/rec.opam b/test/blackbox-tests/test-cases/rocq/rec-module.t/rec.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/rec-module.t/run.t b/test/blackbox-tests/test-cases/rocq/rec-module.t/run.t new file mode 100644 index 00000000000..a2c571a6595 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/rec-module.t/run.t @@ -0,0 +1,27 @@ + $ dune build --display short --debug-dependency-path @all + rocq .rec_module.theory.d + rocq b/foo.{glob,vo} + rocq c/ooo.{glob,vo} + rocq c/d/bar.{glob,vo} + rocq a/bar.{glob,vo} + + $ dune build --debug-dependency-path @default + lib: [ + "_build/install/default/lib/rec/META" + "_build/install/default/lib/rec/dune-package" + "_build/install/default/lib/rec/opam" + ] + lib_root: [ + "_build/install/default/lib/coq/user-contrib/rec_module/a/bar.glob" {"coq/user-contrib/rec_module/a/bar.glob"} + "_build/install/default/lib/coq/user-contrib/rec_module/a/bar.v" {"coq/user-contrib/rec_module/a/bar.v"} + "_build/install/default/lib/coq/user-contrib/rec_module/a/bar.vo" {"coq/user-contrib/rec_module/a/bar.vo"} + "_build/install/default/lib/coq/user-contrib/rec_module/b/foo.glob" {"coq/user-contrib/rec_module/b/foo.glob"} + "_build/install/default/lib/coq/user-contrib/rec_module/b/foo.v" {"coq/user-contrib/rec_module/b/foo.v"} + "_build/install/default/lib/coq/user-contrib/rec_module/b/foo.vo" {"coq/user-contrib/rec_module/b/foo.vo"} + "_build/install/default/lib/coq/user-contrib/rec_module/c/d/bar.glob" {"coq/user-contrib/rec_module/c/d/bar.glob"} + "_build/install/default/lib/coq/user-contrib/rec_module/c/d/bar.v" {"coq/user-contrib/rec_module/c/d/bar.v"} + "_build/install/default/lib/coq/user-contrib/rec_module/c/d/bar.vo" {"coq/user-contrib/rec_module/c/d/bar.vo"} + "_build/install/default/lib/coq/user-contrib/rec_module/c/ooo.glob" {"coq/user-contrib/rec_module/c/ooo.glob"} + "_build/install/default/lib/coq/user-contrib/rec_module/c/ooo.v" {"coq/user-contrib/rec_module/c/ooo.v"} + "_build/install/default/lib/coq/user-contrib/rec_module/c/ooo.vo" {"coq/user-contrib/rec_module/c/ooo.vo"} + ] diff --git a/test/blackbox-tests/test-cases/rocq/scrub_coq_args.sh b/test/blackbox-tests/test-cases/rocq/scrub_coq_args.sh new file mode 100755 index 00000000000..02dc5c6b0f0 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/scrub_coq_args.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +# This script is used for scrubbing the output of Dune actions calling Coq +# binaries. It contains some common patterns which are scurbbed for any +# non-reproducible paths and the arguments are displayed line by line. + +# \f (form feed) is used as a delayed new line for sed + +sed 's/$ (cd .*coqc/coqc/' $1 | # cleanup coqc +sed 's/$ (cd .*coqdep/coqdep/' | # cleanup coqdep +sed 's/$ (cd .*coqdoc/coqdoc/' | # cleanup coqdoc +sed 's/$ (cd .*rocq compile/rocq compile/' $1 | # cleanup rocq +sed 's/$ (cd .*rocq dep/rocq dep/' $1 | # cleanup rocq +sed 's/)//' | # remove trailing ) +sed 's/ -I/\f-I/g' | # new line for each -I +sed 's/ -nI/\f-nI/g' | # new line for each -nI +sed 's/ -R/\f-R/g' | # new line for each -R +sed 's/ -Q/\f-Q/g' | # new line for each -Q +sed 's/ -w/\f-w/g' | # new line for each -w +sed 's/ -boot/\f-boot/g' | # new line for each -boot +sed 's/ -native-compiler /\f-native-compiler /g' | # new line for each -native-compiler +sed 's/-R [^[:space:]]*coq /-R coq /g' | # scrub -R with coq +sed 's#-R [^[:space:]]*coq/theories #-R coq/theories #g' | # scrub -R with coq/theories +sed 's/-I [-A-Za-z0-9\/_\.]*lib\//-I lib\//g' | # scrub -I with lib/ +sed 's/-nI [-A-Za-z0-9\/_\.]*lib\//-nI lib\//g' | # scrub -nI with lib/ +sed 's/\(-R [^\f]* [^\f]*\) \(.*\)/\1\f\2/g' | # new line after each -R +sed 's/\(-I lib\/findlib\)\f\(.*\)/\2\f\1/g' | # move lib/findlib to the end +sed 's/\(-I lib\/zarith\)\f\(.*\)/\2\f\1/g' | # move lib/zarith to the end +tr '\f' '\n' # replace form feed with new line diff --git a/test/blackbox-tests/test-cases/rocq/theory-stanza-duplicate-module.t/dune-project b/test/blackbox-tests/test-cases/rocq/theory-stanza-duplicate-module.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/theory-stanza-duplicate-module.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/theory-stanza-duplicate-module.t/run.t b/test/blackbox-tests/test-cases/rocq/theory-stanza-duplicate-module.t/run.t new file mode 100644 index 00000000000..e515f72b4c8 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/theory-stanza-duplicate-module.t/run.t @@ -0,0 +1,15 @@ +Dune should warn about duplicate modules declared inside a rocq.theory stanza + + $ cat > dune << EOF + > (rocq.theory + > (name foo) + > (modules foo bar foo)) + > EOF + + $ dune build + File "dune", lines 1-3, characters 0-48: + 1 | (rocq.theory + 2 | (name foo) + 3 | (modules foo bar foo)) + Error: Duplicate Rocq module "foo". + [1] diff --git a/test/blackbox-tests/test-cases/rocq/vos-build.t/bar.v b/test/blackbox-tests/test-cases/rocq/vos-build.t/bar.v new file mode 100644 index 00000000000..4627b76131c --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/vos-build.t/bar.v @@ -0,0 +1,3 @@ +From basic Require Import foo. + +Definition mynum (i : mynat) := 3. diff --git a/test/blackbox-tests/test-cases/rocq/vos-build.t/base.opam b/test/blackbox-tests/test-cases/rocq/vos-build.t/base.opam new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/blackbox-tests/test-cases/rocq/vos-build.t/dune b/test/blackbox-tests/test-cases/rocq/vos-build.t/dune new file mode 100644 index 00000000000..9eb0d9cc6d9 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/vos-build.t/dune @@ -0,0 +1,10 @@ +(rocq.theory + (name basic) + (package base) + (modules :standard) + (mode vos) + (synopsis "Test Coq library")) + +(rule + (alias default) + (action (echo "%{read:base.install}"))) diff --git a/test/blackbox-tests/test-cases/rocq/vos-build.t/dune-project b/test/blackbox-tests/test-cases/rocq/vos-build.t/dune-project new file mode 100644 index 00000000000..2bc8f75237f --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/vos-build.t/dune-project @@ -0,0 +1,2 @@ +(lang dune 3.21) +(using rocq 0.11) diff --git a/test/blackbox-tests/test-cases/rocq/vos-build.t/dune-vo b/test/blackbox-tests/test-cases/rocq/vos-build.t/dune-vo new file mode 100644 index 00000000000..60c61e87ff5 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/vos-build.t/dune-vo @@ -0,0 +1,10 @@ +(rocq.theory + (name basic) + (package base) + (modules :standard) + (mode vo) + (synopsis "Test Coq library")) + +(rule + (alias default) + (action (echo "%{read:base.install}"))) diff --git a/test/blackbox-tests/test-cases/rocq/vos-build.t/foo.v b/test/blackbox-tests/test-cases/rocq/vos-build.t/foo.v new file mode 100644 index 00000000000..53e0ce1b152 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/vos-build.t/foo.v @@ -0,0 +1 @@ +Definition mynat := nat. diff --git a/test/blackbox-tests/test-cases/rocq/vos-build.t/run.t b/test/blackbox-tests/test-cases/rocq/vos-build.t/run.t new file mode 100644 index 00000000000..4e1617da454 --- /dev/null +++ b/test/blackbox-tests/test-cases/rocq/vos-build.t/run.t @@ -0,0 +1,53 @@ + $ dune build --display short foo.vos + rocq .basic.theory.d + rocq foo.vos + + $ dune clean + $ dune build --display short bar.vos + rocq .basic.theory.d + rocq foo.vos + rocq bar.vos + + $ cat foo.v | dune rocq top -- foo.v 2>/dev/null | sed '/^Welcome to Rocq/d' + mynat is defined + $ cat bar.v | dune rocq top -- bar.v 2>/dev/null | sed '/^Welcome to Rocq/d' + mynum is defined + + $ dune clean + $ dune build --display short --debug-dependency-path @all + rocq .basic.theory.d + rocq foo.vos + rocq bar.vos + $ dune build --debug-dependency-path @default + lib: [ + "_build/install/default/lib/base/META" + "_build/install/default/lib/base/dune-package" + "_build/install/default/lib/base/opam" + ] + lib_root: [ + "_build/install/default/lib/coq/user-contrib/basic/bar.v" {"coq/user-contrib/basic/bar.v"} + "_build/install/default/lib/coq/user-contrib/basic/bar.vos" {"coq/user-contrib/basic/bar.vos"} + "_build/install/default/lib/coq/user-contrib/basic/foo.v" {"coq/user-contrib/basic/foo.v"} + "_build/install/default/lib/coq/user-contrib/basic/foo.vos" {"coq/user-contrib/basic/foo.vos"} + ] + +Checking that we can go back to vo mode (without cleaning). + + $ mv dune-vo dune + $ dune build --display short --debug-dependency-path @all + rocq foo.{glob,vo} + rocq bar.{glob,vo} + $ dune build --debug-dependency-path @default + lib: [ + "_build/install/default/lib/base/META" + "_build/install/default/lib/base/dune-package" + "_build/install/default/lib/base/opam" + ] + lib_root: [ + "_build/install/default/lib/coq/user-contrib/basic/bar.glob" {"coq/user-contrib/basic/bar.glob"} + "_build/install/default/lib/coq/user-contrib/basic/bar.v" {"coq/user-contrib/basic/bar.v"} + "_build/install/default/lib/coq/user-contrib/basic/bar.vo" {"coq/user-contrib/basic/bar.vo"} + "_build/install/default/lib/coq/user-contrib/basic/foo.glob" {"coq/user-contrib/basic/foo.glob"} + "_build/install/default/lib/coq/user-contrib/basic/foo.v" {"coq/user-contrib/basic/foo.v"} + "_build/install/default/lib/coq/user-contrib/basic/foo.vo" {"coq/user-contrib/basic/foo.vo"} + ] diff --git a/test/blackbox-tests/test-cases/workspaces/workspace-env.t/run.t b/test/blackbox-tests/test-cases/workspaces/workspace-env.t/run.t index 5b1efc00b21..91daf5ffb91 100644 --- a/test/blackbox-tests/test-cases/workspaces/workspace-env.t/run.t +++ b/test/blackbox-tests/test-cases/workspaces/workspace-env.t/run.t @@ -17,6 +17,11 @@ Workspaces also allow you to set the env for a context: (coqdoc_flags (--toc)) (coqdoc_header ()) (coqdoc_footer ()) + (rocq_flags (-q)) + (rocqdep_flags ()) + (rocqdoc_flags (--toc)) + (rocqdoc_header ()) + (rocqdoc_footer ()) (js_of_ocaml_flags ()) (js_of_ocaml_build_runtime_flags ()) (js_of_ocaml_link_flags ())