Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for CoqMakefile.local-late #12411

Merged
merged 3 commits into from May 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions doc/changelog/08-tools/12411-makefile-local-late.rst
@@ -0,0 +1,5 @@
- **Added:**
``coq_makefile``\-made ``Makefile``\s now support inclusion of a
``.local-late`` file at the end, allowing the user to access
more variables (`#12411 <https://github.com/coq/coq/pull/12411>`_, fixes
`#10912 <https://github.com/coq/coq/issues/10912>`_, by Jason Gross).
67 changes: 57 additions & 10 deletions doc/sphinx/practical-tools/utilities.rst
Expand Up @@ -152,14 +152,27 @@ Including the generated makefile with an include directive is
discouraged, since the contents of this file, including variable names and
status of rules, may change in the future.

An optional file ``CoqMakefile.local`` can be provided by the user in order to
extend ``CoqMakefile``. In particular one can declare custom actions to be
performed before or after the build process. Similarly one can customize the
install target or even provide new targets. Extension points are documented in
paragraph :ref:`coqmakefilelocal`.

The extensions of the files listed in ``_CoqProject`` is used in order to
decide how to build them. In particular:
Use the optional file ``CoqMakefile.local`` to extend
``CoqMakefile``. In particular, you can declare custom actions to run
before or after the build process. Similarly you can customize the
install target or even provide new targets. See
:ref:`coqmakefilelocal` for extension-point documentation. Although
you can use all variables defined in ``CoqMakefile`` in the *recipes*
of rules that you write and in the definitions of any variables that
you assign with ``=``, many variables are not available for use if you
assign variable values with ``:=`` nor to define the *targets* of
rules nor in top-level conditionals such as ``ifeq``. Additionally,
you must use `secondary expansion
<https://www.gnu.org/software/make/manual/html_node/Secondary-Expansion.html>`_
to make use of such variables in the prerequisites of rules. To access
variables defined in ``CoqMakefile`` in rule target computation,
top-level conditionals, and ``:=`` variable assignment, for example to
add new dependencies to compiled outputs, use the optional file
``CoqMakefile.local-late``. See :ref:`coqmakefilelocallate` for a
non-exhaustive list of variables.

The extensions of files listed in ``_CoqProject`` determine
how they are built. In particular:


+ Coq files must use the ``.v`` extension
Expand Down Expand Up @@ -188,8 +201,8 @@ file ``CoqMakefile``. It can contain two kinds of directives.
**Variable assignment**

The variable must belong to the variables listed in the ``Parameters``
section of the generated makefile.
Here we describe only few of them.
section of the generated makefile. Use
``CoqMakefile.local-late`` instead to access more variables. These include:

:CAMLPKGS:
can be used to specify third party findlib packages, and is
Expand Down Expand Up @@ -273,6 +286,40 @@ The following makefile rules can be extended.
One can append lines to the generated ``.merlin`` file extending this
target.

.. _coqmakefilelocallate:

CoqMakefile.local-late
++++++++++++++++++++++

The optional file ``CoqMakefile.local-late`` is included at the end of the generated
file ``CoqMakefile``. The following is a partial list of accessible variables:

:COQ_VERSION:
Copy link
Member

@gares gares Apr 27, 2021

Choose a reason for hiding this comment

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

This variable is also available in the non -late file (I'm using it already). Please move it upward.
Ditto for COQMAKEFILE_VERSION, COQC and COQFLAGS and COQLIBS.

I did not check the others.

Copy link
Member Author

Choose a reason for hiding this comment

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

All variables are available for use in recipes of rules in the non-late file, as well as in the definitions of variables assigned using =. They are also available in the prerequisites of rules only if you double the $ and enable secondary expansion. However, these variables are not available when naming the outputs of rules, nor in top-level ifeq/ifneq statements, nor in variables assigned with :=. (I presume your use-cases involve the former kind and not the latter kind?) Do you have suggestions for making this distinction more clear in the documentation?

Copy link
Member

Choose a reason for hiding this comment

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

Indeed. I think it is fine, your explanation could also go in the doc, since the external pointer is a bit boring to follow.

Copy link
Member Author

Choose a reason for hiding this comment

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

I've added some explanation in the doc, please take a look

the version of ``coqc`` being used, which can be used to
provide different behavior depending on the Coq version
:COQMAKEFILE_VERSION:
the version of Coq used to generate the
Makefile, which can be used to detect version mismatches
:ALLDFILES:
the list of generated dependency files, which can be used,
for example, to cause ``make`` to recompute dependencies
when files change by writing ``$(ALLDFILES): myfiles`` or to
indicate that files must be generated before dependencies can
be computed by writing ``$(ALLDFILES): | mygeneratedfiles``
:VOFILES, GLOBFILES, CMOFILES, CMXFILES, OFILES, CMAFILES, CMXAFILES, CMIFILES, CMXSFILES:
lists of files that are generated by various invocations of the compilers

In addition, the following variables may be useful for
deciding what targets to present via ``$(shell ...)``; these
variables are already accessible in recipes for rules added in
``CoqMakefile.local``, but are only accessible from top-level ``$(shell
...)`` invocations in ``CoqMakefile.local-late``:

:COQC, COQDEP, COQDOC, CAMLC, CAMLOPTC:
compiler binaries
:COQFLAGS, CAMLFLAGS, COQLIBS, COQDEBUG, OCAMLLIBS:
flags passed to the Coq or OCaml compilers

Timing targets and performance testing
++++++++++++++++++++++++++++++++++++++

Expand Down
@@ -0,0 +1,4 @@
MYVOFILES := $(VOFILES)

printvo::
@echo '$(MYVOFILES)'
@@ -0,0 +1 @@
foo.vo
15 changes: 15 additions & 0 deletions test-suite/coq-makefile/local-late-extension/run.sh
@@ -0,0 +1,15 @@
#!/usr/bin/env bash

. ../template/path-init.sh

set -x
coq_makefile -Q . Top foo.v -o Makefile
rm -f .*.d *.d
make --no-print-directory -j1 printvo 2>&1 \
| grep -v 'make[^:]*: warning: -jN forced in submake: disabling jobserver mode.' \
| grep -v 'coq_makefile -Q . Top foo.v -o Makefile' \
| grep -v 'make[^:]*: Entering directory' \
| grep -v 'make[^:]*: Leaving directory' \
| grep -v 'exit 1' \
> make-printvo.log
diff -u make-printvo.log.expected make-printvo.log || exit $?
5 changes: 5 additions & 0 deletions tools/CoqMakefile.in
Expand Up @@ -913,6 +913,11 @@ debug:

.DEFAULT_GOAL := all

# Users can create @LOCAL_LATE_FILE@ to hook into double-colon rules
# or add other needed Makefile code, using defined
# variables if necessary.
-include @LOCAL_LATE_FILE@

# Local Variables:
# mode: makefile-gmake
# End:
7 changes: 4 additions & 3 deletions tools/coq_makefile.ml
Expand Up @@ -122,7 +122,7 @@ let read_whole_file s =

let quote s = if String.contains s ' ' || CString.is_empty s then "'" ^ s ^ "'" else s

let generate_makefile oc conf_file local_file dep_file args project =
let generate_makefile oc conf_file local_file local_late_file dep_file args project =
let coqcorelib = Envars.coqcorelib () in
let makefile_template = Filename.concat coqcorelib "tools/CoqMakefile.in" in
if not (Sys.file_exists makefile_template) then
Expand All @@ -134,6 +134,7 @@ let generate_makefile oc conf_file local_file dep_file args project =
(fun s (k,v) -> Str.global_substitute (Str.regexp_string k) (fun _ -> v) s) s
[ "@CONF_FILE@", conf_file;
"@LOCAL_FILE@", local_file;
"@LOCAL_LATE_FILE@", local_late_file;
"@DEP_FILE@", dep_file;
"@COQ_VERSION@", Coq_config.version;
"@PROJECT_FILE@", (Option.default "" project.project_file);
Expand Down Expand Up @@ -434,6 +435,7 @@ let _ =

let conf_file = Option.default "CoqMakefile" project.makefile ^ ".conf" in
let local_file = Option.default "CoqMakefile" project.makefile ^ ".local" in
let local_late_file = Option.default "CoqMakefile" project.makefile ^ ".local-late" in
let dep_file = "." ^ Option.default "CoqMakefile" project.makefile ^ ".d" in

if project.extra_targets <> [] then begin
Expand All @@ -459,10 +461,9 @@ let _ =
Envars.set_coqlib ~fail:(fun x -> Printf.eprintf "Error: %s\n" x; exit 1);

let ocm = Option.cata open_out stdout project.makefile in
generate_makefile ocm conf_file local_file dep_file (prog :: args) project;
generate_makefile ocm conf_file local_file local_late_file dep_file (prog :: args) project;
close_out ocm;
let occ = open_out conf_file in
generate_conf occ project (prog :: args);
close_out occ;
exit 0