Skip to content

Commit 5140472

Browse files
Merge PR coq#19901: Add relocatable mode
Reviewed-by: ppedrot Ack-by: Janno Ack-by: ejgallego Co-authored-by: ppedrot <[email protected]>
2 parents 9696e45 + 48df6ab commit 5140472

20 files changed

+251
-105
lines changed

.gitlab-ci.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ before_script:
9393
- dev/ci/gitlab-section.sh end coq.clean
9494

9595
- dev/ci/gitlab-section.sh start coq.config coq.config
96-
- ./configure -prefix "$(pwd)/_install_ci" $COQ_EXTRA_CONF
96+
- ./configure -relocatable $COQ_EXTRA_CONF
9797
- dev/ci/gitlab-section.sh end coq.config
9898

9999
- dev/ci/gitlab-section.sh start coq.build coq.build
@@ -157,7 +157,7 @@ before_script:
157157
- cd test-suite
158158
- make clean
159159
- export OCAMLPATH=$(readlink -f ../_install_ci/lib/):"$OCAMLPATH"
160-
- COQEXTRAFLAGS="${COQEXTRAFLAGS}" make -j "$NJOBS" TIMED=1 all
160+
- COQEXTRAFLAGS="${COQEXTRAFLAGS}" make -j "$NJOBS" TIMED=1 all ROCQ_EXE=$(pwd)/../_install_ci/bin/rocq
161161
artifacts:
162162
name: "$CI_JOB_NAME.logs"
163163
when: on_failure

INSTALL.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -89,17 +89,17 @@ for more details.
8989

9090
To build and install Rocq (and RocqIDE if desired) do:
9191

92-
$ ./configure -prefix <install_prefix> $options
9392
$ make dunestrap
9493
$ dune build -p rocq-runtime,coq-core,rocq-core,coq,coqide-server,rocqide
9594
$ dune install --prefix=<install_prefix> rocq-runtime coq-core rocq-core coq coqide-server rocqide
9695

9796
You can drop the `rocqide` packages if not needed.
9897

9998
Packagers may want to play with `dune install` options as to tweak
100-
installation path, the `-prefix` argument in `./configure` tells Rocq
101-
where to find its standard library, but doesn't control any other
102-
installation path these days.
99+
installation paths, and the `-libdir` argument for `./configure` to tell Rocq
100+
where to find its standard library, (`configure` doesn't control
101+
installation paths these days). See refman "Command-line and graphical tools"
102+
-> "The Rocq Prover commands" -> "System configuration" for more info.
103103

104104
OCaml toolchain advisory
105105
------------------------

Makefile

-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ help-install:
8989
@echo "The Dune-based Rocq build is split into several packages; see Dune and dev/doc"
9090
@echo "documentation for more details. A quick install of Rocq alone can be done with"
9191
@echo ""
92-
@echo " $$ ./configure -prefix <install_prefix>"
9392
@echo " $$ make dunestrap"
9493
@echo " $$ dune build -p rocq-runtime,coq-core,rocq-core"
9594
@echo " $$ dune install --prefix=<install_prefix> rocq-runtime coq-core rocq-core"

boot/dune

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
(synopsis "Rocq Enviroment and Paths facilities")
77
; until ocaml/dune#4892 fixed
88
; (private_modules util)
9-
(libraries rocq-runtime.config))
9+
(libraries rocq-runtime.config rocq-runtime.clib))
1010

1111
(deprecated_library_name
1212
(old_public_name coq-core.boot)

boot/env.ml

+43-20
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,6 @@ type t =
2424
; lib : Path.t
2525
}
2626

27-
(* fatal error *)
28-
let fail_msg =
29-
"cannot guess a path for Rocq libraries; please use -coqlib option \
30-
or ensure you have installed the package containing Rocq's prelude (rocq-core in OPAM) \
31-
If you intend to use Rocq without prelude, the -boot -noinit options must be used."
32-
33-
let fail s = Format.eprintf "%s@\n%!" fail_msg; exit 1
34-
3527
(* This code needs to be refactored, for now it is just what used to be in envvars *)
3628

3729
let use_suffix prefix suffix =
@@ -54,21 +46,54 @@ let theories_dir = "theories"
5446
let plugins_dir = "plugins"
5547
let prelude = Filename.concat theories_dir "Init/Prelude.vo"
5648

57-
let coqbin =
58-
canonical_path_name (Filename.dirname Sys.executable_name)
49+
let find_in_PATH f =
50+
match Sys.getenv_opt "PATH" with
51+
| None -> None
52+
| Some paths ->
53+
let sep = if Coq_config.arch_is_win32 then ';' else ':' in
54+
let paths = String.split_on_char sep paths in
55+
paths |> List.find_opt (fun path ->
56+
Sys.file_exists (if path = "" then f else Filename.concat path f))
57+
58+
let rocqbin =
59+
(* avoid following symlinks if possible (Sys.executable_name followed symlinks) *)
60+
if Filename.basename Sys.argv.(0) <> Sys.argv.(0) then
61+
(* explicit directory (maybe relative to current dir) *)
62+
canonical_path_name (Filename.dirname Sys.argv.(0))
63+
else match find_in_PATH Sys.argv.(0) with
64+
| Some p -> p
65+
| None -> canonical_path_name (Filename.dirname Sys.executable_name)
5966

6067
(** The following only makes sense when executables are running from
6168
source tree (e.g. during build or in local mode). *)
62-
let coqroot =
63-
Filename.dirname coqbin
69+
let rocqroot =
70+
let rec search = function
71+
| [] ->
72+
(* couldn't recognize the layout, guess the executable is 1 dir below the root
73+
(eg "mybin/rocq")
74+
XXX we should search only when we need the root
75+
and produce an error if we can't find it *)
76+
Filename.dirname rocqbin
77+
| path :: rest ->
78+
if Sys.file_exists (Filename.concat path "bin") then path
79+
else search rest
80+
in
81+
(* we can be "bin/rocq" or "lib/rocq-runtime/rocqworker"
82+
so rocqbin can be "bin/" or "lib/rocq-runtime/" *)
83+
let dirname = Filename.dirname in
84+
search [ dirname rocqbin; dirname @@ dirname rocqbin ]
85+
86+
let relocate = function
87+
| Coq_config.NotRelocatable p -> p
88+
| Coq_config.Relocatable p -> Filename.concat rocqroot p
6489

6590
(** [check_file_else ~dir ~file oth] checks if [file] exists in
6691
the installation directory [dir] given relatively to [coqroot],
6792
which maybe has been relocated.
6893
If the check fails, then [oth ()] is evaluated.
6994
Using file system equality seems well enough for this heuristic *)
7095
let check_file_else ~dir ~file oth =
71-
let path = use_suffix coqroot dir in
96+
let path = use_suffix rocqroot dir in
7297
if Sys.file_exists (Filename.concat path file) then path else oth ()
7398

7499
let guess_coqlib () =
@@ -78,12 +103,10 @@ let guess_coqlib () =
78103
check_file_else
79104
~dir:Coq_config.coqlibsuffix
80105
~file:prelude
81-
(fun () ->
82-
if Sys.file_exists (Filename.concat Coq_config.coqlib prelude)
83-
then Coq_config.coqlib
84-
else fail ())
106+
(fun () -> relocate Coq_config.coqlib)
85107

86-
(* Build layout uses coqlib = coqcorelib *)
108+
(* Build layout uses coqlib = coqcorelib
109+
XXX we should be using -boot in build layout so is that dead code? *)
87110
let guess_coqcorelib lib =
88111
if Sys.file_exists (Path.relative lib plugins_dir)
89112
then lib
@@ -161,8 +184,8 @@ let ocamlfind () = match Util.getenv_opt "OCAMLFIND" with
161184

162185
let docdir () =
163186
(* This assumes implicitly that the suffix is non-trivial *)
164-
let path = use_suffix coqroot Coq_config.docdirsuffix in
165-
if Sys.file_exists path then path else Coq_config.docdir
187+
let path = use_suffix rocqroot Coq_config.docdirsuffix in
188+
if Sys.file_exists path then path else relocate Coq_config.docdir
166189

167190
(* Print the configuration information *)
168191

boot/env.mli

+2
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,5 @@ val query_needs_env : Usage.query -> bool
117117
(** Internal, should be set automatically by passing cmdline args to
118118
init; note that this will set both [coqlib] and [corelib] for now. *)
119119
val set_coqlib : string -> unit
120+
121+
val relocate : Coq_config.relocatable_path -> string

config/coq_config.mli

+9-5
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,16 @@
88
(* * (see LICENSE file for the text of the license) *)
99
(************************************************************************)
1010

11+
type relocatable_path =
12+
| NotRelocatable of string (* absolute path *)
13+
| Relocatable of string (* relative to the inferred prefix *)
14+
1115
(* The fields below are absolute paths *)
12-
val install_prefix : string (* Install prefix passed by the user *)
13-
val coqlib : string (* where the std library is installed *)
14-
val configdir : string (* where configuration files are installed *)
15-
val datadir : string (* where extra data files are installed *)
16-
val docdir : string (* where the doc is installed *)
16+
val install_prefix : relocatable_path (* Install prefix passed by the user *)
17+
val coqlib : relocatable_path (* where the std library is installed *)
18+
val configdir : relocatable_path (* where configuration files are installed *)
19+
val datadir : relocatable_path (* where extra data files are installed *)
20+
val docdir : relocatable_path (* where the doc is installed *)
1721

1822
(* The fields below are paths relative to the installation prefix *)
1923
(* However, if an absolute path, it means discarding the actual prefix *)

config/dune

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,4 @@
3636
%{project_root}/dev/header.c
3737
; Needed to generate include lists for coq_makefile
3838
plugin_list)
39-
(action (chdir %{project_root} (run %{project_root}/tools/configure/configure.exe -quiet -prefix %{workspace_root}/../install/default))))
39+
(action (chdir %{project_root} (run %{project_root}/tools/configure/configure.exe -quiet -relocatable))))

dev/ci/scripts/ci-coq_lsp.sh

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ git_download coq_lsp
99

1010
if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi
1111

12+
if [ -n "${GITLAB_CI}" ]; then
13+
export ROCQLIB="$PWD/_install_ci/lib/coq"
14+
export ROCQRUNTIMELIB="$PWD/_install_ci/lib/rocq-runtime"
15+
fi
16+
1217
( cd "${CI_BUILD_DIR}/coq_lsp"
1318
dune build --root . --only-packages=coq-lsp @install
1419
# Tests

dev/ci/scripts/ci-vscoq.sh

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ git_download vscoq
99

1010
if [ "$DOWNLOAD_ONLY" ]; then exit 0; fi
1111

12+
if [ -n "${GITLAB_CI}" ]; then
13+
export ROCQLIB="$PWD/_install_ci/lib/coq"
14+
export ROCQRUNTIMELIB="$PWD/_install_ci/lib/rocq-runtime"
15+
fi
16+
1217
( cd "$CI_BUILD_DIR/vscoq/language-server"
1318
dune build --root . --only-packages=vscoq-language-server @install
1419
dune runtest --root .
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
overlay coq_lsp https://github.com/SkySkimmer/coq-lsp configure-clean 19901

doc/sphinx/practical-tools/coq-commands.rst

+79
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,85 @@ See :ref:`rocq_makefile` and :ref:`building_dune`.
7373
.. rocqdoc::
7474
-R <PATH> Mod1
7575

76+
System configuration
77+
--------------------
78+
79+
Running `rocq` (or the `coq` compatibility commands) will fail if it
80+
cannot find certain expected files (except for subcommands like
81+
`rocq wc` which do not need to find anything).
82+
83+
The files are searched according to Rocq's build time configuration,
84+
the location of the `rocq` executable and the available command line
85+
arguments and environment variables.
86+
87+
.. note::
88+
89+
If `configure` is not explicitly called, it is equivalent to
90+
`configure -relocatable`.
91+
92+
Let `$root` be the parent directory of the directory of the `rocq`
93+
executable (typically `rocq` is `$root/bin/rocq`, or
94+
`$root\bin\rocq.exe` on Windows).
95+
96+
Let `$libdirconf` be the value passed to `configure -libdir`, or
97+
`coq/lib` if `libdir` was not used.
98+
99+
Let `$libdir` be
100+
101+
- if the `coqlib` command line argument was used, its value
102+
103+
- otherwise, if the `ROCQLIB` environment variable is defined, its value
104+
105+
- otherwise, if the deprecated `COQLIB` environment variable is defined, its value
106+
107+
- otherwise, if `$libdirconf` is absolute, its value
108+
109+
- otherwise, if `$root/$libdirconf/theories/Init/Prelude.vo` exists or
110+
Rocq was configured with `-relocatable`, `$root/$libdirconf`
111+
112+
- otherwise, if Rocq was configured with `-prefix $prefix`, `$prefix/$libdirconf`
113+
(if the user gave a relative `$prefix`, it is turned into an absolute
114+
path based on the working directory of the `configure` invocation)
115+
116+
.. note::
117+
118+
Rocq must be configured with either `-prefix` or `-relocatable`.
119+
120+
If `$libdirconf` is relative, and `-prefix` was used, usually either
121+
`$root/$libdirconf/theories/Init/Prelude.vo` does not exist so we
122+
use `$prefix/$libdirconf`, or it is the same as `$prefix/$libdirconf`.
123+
If `-relocatable` was used we only have `$root/$libdirconf`.
124+
125+
.. exn:: The path for Rocq libraries is wrong.
126+
127+
Unless `-boot` was passed, Rocq fails with this error if
128+
`$libdir/theories/Init/Prelude.vo` does not exist.
129+
130+
Unless `-boot` was passed, Rocq acts as though `-R $libdir/theories
131+
Corelib -Q $libdir/user-contrib ""` was passed.
132+
133+
Let `$runtimelib` be
134+
135+
- if the `ROCQRUNTIMELIB` environment variable is defined, its value
136+
137+
- otherwise, if the deprecated `COQCORELIB` environment variable is defined, its value
138+
139+
- otherwise, `$libdir/../rocq-runtime`
140+
141+
.. exn:: The path for Rocq plugins is wrong.
142+
143+
Unless `-boot` was passed, Rocq fails with this error if
144+
`$runtimelib/plugins` does not exist.
145+
146+
If `-boot` was not passed, Rocq will add `$runtimelib/..` to the
147+
OCamlfind search path (as though `-I $runtimelib/..` was passed).
148+
149+
Then regardless of `-boot` Rocq will search for OCamlfind package `rocq-runtime`.
150+
151+
.. exn:: Could not find package rocq-runtime.
152+
153+
Rocq fails with this error if OCamlfind package `rocq-runtime` could not be found.
154+
76155
Customization at launch time
77156
---------------------------------
78157

lib/envars.ml

+12-23
Original file line numberDiff line numberDiff line change
@@ -81,34 +81,23 @@ let expand_path_macros ~warn s =
8181

8282
(** {2 Rocq paths} *)
8383

84-
let coqbin =
85-
CUnix.canonical_path_name (Filename.dirname Sys.executable_name)
86-
87-
(** The following only makes sense when executables are running from
88-
source tree (e.g. during build or in local mode). *)
89-
let coqroot =
90-
Filename.dirname coqbin
91-
92-
(** On win32, we add coqbin to the PATH at launch-time (this used to be
93-
done in a .bat script). *)
94-
let _ =
95-
if Coq_config.arch_is_win32 then
96-
Unix.putenv "PATH" (coqbin ^ ";" ^ getenv_else "PATH" (fun () -> ""))
97-
9884
(** Add a local installation suffix (unless the suffix is itself
9985
absolute in which case the prefix does not matter) *)
100-
let use_suffix prefix suffix =
101-
if String.length suffix > 0 && suffix.[0] = '/' then suffix else prefix / suffix
86+
let use_suffix suffix =
87+
if String.length suffix > 0 && suffix.[0] = '/' then suffix
88+
else Boot.Env.relocate (Relocatable suffix)
10289

103-
let datadir () =
90+
(* XXX do we actually need the local_suffix? *)
91+
let relocate local_suffix path =
10492
(* This assumes implicitly that the suffix is non-trivial *)
105-
let path = use_suffix coqroot Coq_config.datadirsuffix in
106-
if Sys.file_exists path then path else Coq_config.datadir
93+
let local_path = use_suffix local_suffix in
94+
if Sys.file_exists local_path
95+
then local_path
96+
else Boot.Env.relocate path
10797

108-
let configdir () =
109-
(* This assumes implicitly that the suffix is non-trivial *)
110-
let path = use_suffix coqroot Coq_config.configdirsuffix in
111-
if Sys.file_exists path then path else Coq_config.configdir
98+
let datadir () = relocate Coq_config.datadirsuffix Coq_config.datadir
99+
100+
let configdir () = relocate Coq_config.configdirsuffix Coq_config.configdir
112101

113102
let coqpath () =
114103
let make_search_path path =

lib/envars.mli

-9
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,6 @@ val datadir : unit -> string
3737
(** [configdir] is the path to the installed config directory. *)
3838
val configdir : unit -> string
3939

40-
(** [coqbin] is the name of the current executable. *)
41-
val coqbin : string
42-
43-
(** [coqroot] is the path to [coqbin].
44-
The following value only makes sense when executables are running from
45-
source tree (e.g. during build or in local mode).
46-
*)
47-
val coqroot : string
48-
4940
(** [coqpath] is the standard path to coq.
5041
Notice that coqpath is stored in reverse order, since that is
5142
the order it gets added to the search path. *)

0 commit comments

Comments
 (0)