Skip to content

Commit

Permalink
[stm] Make toplevels standalone executables.
Browse files Browse the repository at this point in the history
We turn coqtop "plugins" into standalone executables, which will be
installed in `COQBIN` and located using the standard `PATH`
mechanism. Using dynamic linking for `coqtop` customization didn't
make a lot of sense, given that only one of such "plugins" could be
loaded at a time. This cleans up some code and solves two problems:

- `coqtop` needing to locate plugins,
- dependency issues as plugins in `stm` depended on files in `toplevel`.

In order to implement this, we do some minor cleanup of the toplevel
API, making it functional, and implement uniform build rules. In
particular:

- `stm` and `toplevel` have become library-only directories,
- a new directory, `topbin`, contains the new executables,
- 4 new binaries have been introduced, for coqide and the stm.
- we provide a common and cleaned up way to locate toplevels.
  • Loading branch information
ejgallego committed May 21, 2018
1 parent 053812d commit 382ee49
Show file tree
Hide file tree
Showing 42 changed files with 256 additions and 224 deletions.
2 changes: 2 additions & 0 deletions .merlin
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ S vernac
B vernac
S toplevel
B toplevel
S topbin
B topbin
S plugins/ltac
B plugins/ltac
S API
Expand Down
12 changes: 12 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@ Tactic language
called by OCaml-defined tactics.
- Option "Ltac Debug" now applies also to terms built using Ltac functions.

Coq binaries and process model

- Before 8.9, Coq distributed a single `coqtop` binary and a set of
dynamically loadable plugins that used to take over the main loop
for tasks such as IDE language server or parallel proof checking.

These plugins have been turned into full-fledged binaries so each
different process has associated a particular binary now, in
particular `coqidetop` is the CoqIDE language server, and
`coq{proof,tactic,query}worker` are in charge of task-specific and
parallel proof checking.

Changes from 8.8.0 to 8.8.1
===========================

Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ cruftclean: ml4clean

indepclean:
rm -f $(GENFILES)
rm -f $(COQTOPBYTE) $(CHICKENBYTE)
rm -f $(COQTOPBYTE) $(CHICKENBYTE) $(TOPBYTE)
find . \( -name '*~' -o -name '*.cm[ioat]' -o -name '*.cmti' \) -delete
rm -f */*.pp[iox] plugins/*/*.pp[iox]
rm -rf $(SOURCEDOCDIR)
Expand Down Expand Up @@ -245,7 +245,7 @@ archclean: clean-ide optclean voclean
rm -f $(ALLSTDLIB).*

optclean:
rm -f $(COQTOPEXE) $(CHICKEN)
rm -f $(COQTOPEXE) $(CHICKEN) $(TOPBIN)
rm -f $(TOOLS) $(PRIVATEBINARIES) $(CSDPCERT)
find . -name '*.cmx' -o -name '*.cmx[as]' -o -name '*.[soa]' -o -name '*.so' | xargs rm -f

Expand Down
39 changes: 22 additions & 17 deletions Makefile.build
Original file line number Diff line number Diff line change
Expand Up @@ -383,29 +383,34 @@ grammar/%.cmi: grammar/%.mli

.PHONY: coqbinaries coqbyte

coqbinaries: $(COQTOPEXE) $(CHICKEN) $(CSDPCERT) $(FAKEIDE)
coqbinaries: $(TOPBIN) $(CHICKEN) $(CSDPCERT) $(FAKEIDE)
coqbyte: $(TOPBYTE) $(CHICKENBYTE)

coqbyte: $(COQTOPBYTE) $(CHICKENBYTE)

COQTOP_OPT=toplevel/coqtop_opt_bin.ml
COQTOP_BYTE=toplevel/coqtop_byte_bin.ml
# Special rule for coqtop
$(COQTOPEXE): $(TOPBIN:.opt=.$(BEST))
cp $< $@

ifeq ($(BEST),opt)
$(COQTOPEXE): $(LINKCMX) $(LIBCOQRUN) $(TOPLOOPCMA:.cma=.cmxs) $(COQTOP_OPT)
bin/%.opt$(EXE): topbin/%_bin.ml $(LINKCMX) $(LIBCOQRUN)
$(SHOW)'COQMKTOP -o $@'
$(HIDE)$(OCAMLOPT) -linkall -linkpkg -I vernac -I toplevel \
$(HIDE)$(OCAMLOPT) -linkall -linkpkg $(MLINCLUDES) \
-I kernel/byterun/ -cclib -lcoqrun \
$(SYSMOD) -package camlp5.gramlib \
$(LINKCMX) $(OPTFLAGS) $(LINKMETADATA) $(COQTOP_OPT) -o $@
$(LINKCMX) $(OPTFLAGS) $(LINKMETADATA) $< -o $@
$(STRIP) $@
$(CODESIGN) $@
else
$(COQTOPEXE): $(COQTOPBYTE)
cp $< $@
endif

bin/%.byte$(EXE): topbin/%_bin.ml $(LINKCMO) $(LIBCOQRUN)
$(SHOW)'COQMKTOP -o $@'
$(HIDE)$(OCAMLC) -linkall -linkpkg $(MLINCLUDES) \
-I kernel/byterun/ -cclib -lcoqrun $(VMBYTEFLAGS) \
$(SYSMOD) -package camlp5.gramlib \
$(LINKCMO) $(BYTEFLAGS) $< -o $@

COQTOP_BYTE=topbin/coqtop_byte_bin.ml

# Special rule for coqtop.byte
# VMBYTEFLAGS will either contain -custom of the right -dllpath for the VM
$(COQTOPBYTE): $(LINKCMO) $(LIBCOQRUN) $(TOPLOOPCMA) $(COQTOP_BYTE)
$(COQTOPBYTE): $(LINKCMO) $(LIBCOQRUN) $(COQTOP_BYTE)
$(SHOW)'COQMKTOP -o $@'
$(HIDE)$(OCAMLC) -linkall -linkpkg -I lib -I vernac -I toplevel \
-I kernel/byterun/ -cclib -lcoqrun $(VMBYTEFLAGS) \
Expand Down Expand Up @@ -477,7 +482,7 @@ COQMAKEFILECMO:=clib/clib.cma lib/lib.cma tools/coq_makefile.cmo

$(COQMAKEFILE): $(call bestobj,$(COQMAKEFILECMO))
$(SHOW)'OCAMLBEST -o $@'
$(HIDE)$(call bestocaml, -package str,unix,threads)
$(HIDE)$(call bestocaml, -package str)

$(COQTEX): $(call bestobj, tools/coq_tex.cmo)
$(SHOW)'OCAMLBEST -o $@'
Expand Down Expand Up @@ -506,9 +511,9 @@ FAKEIDECMO:=clib/clib.cma lib/lib.cma ide/document.cmo \
ide/xml_printer.cmo ide/richpp.cmo ide/xmlprotocol.cmo \
tools/fake_ide.cmo

$(FAKEIDE): $(call bestobj, $(FAKEIDECMO)) | $(IDETOPLOOPCMA:.cma=$(BESTDYN))
$(FAKEIDE): $(call bestobj, $(FAKEIDECMO)) | $(IDETOP)
$(SHOW)'OCAMLBEST -o $@'
$(HIDE)$(call bestocaml, -I ide -package str,unix,threads)
$(HIDE)$(call bestocaml, -I ide -package str -package dynlink)

# votour: a small vo explorer (based on the checker)

Expand Down
7 changes: 4 additions & 3 deletions Makefile.common
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,11 @@
# Executables
###########################################################################

COQTOPBYTE:=bin/coqtop.byte$(EXE)
TOPBIN:=$(addsuffix .opt$(EXE), $(addprefix bin/, coqtop coqproofworker coqtacticworker coqqueryworker))
TOPBYTE:=$(TOPBIN:.opt$(EXE)=.byte$(EXE))

COQTOPEXE:=bin/coqtop$(EXE)
COQTOPBYTE:=bin/coqtop.byte$(EXE)

COQDEP:=bin/coqdep$(EXE)
COQMAKEFILE:=bin/coq_makefile$(EXE)
Expand Down Expand Up @@ -107,8 +110,6 @@ CORECMA:=clib/clib.cma lib/lib.cma kernel/kernel.cma library/library.cma \
parsing/parsing.cma printing/printing.cma tactics/tactics.cma vernac/vernac.cma \
stm/stm.cma toplevel/toplevel.cma

TOPLOOPCMA:=stm/proofworkertop.cma stm/tacworkertop.cma stm/queryworkertop.cma

GRAMMARCMA:=grammar/grammar.cma

###########################################################################
Expand Down
50 changes: 36 additions & 14 deletions Makefile.ide
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ COQIDEFLAGS=$(addprefix -I , $(IDESRCDIRS)) $(COQIDEINCLUDES)

IDEDEPS:=clib/clib.cma lib/lib.cma
IDECMA:=ide/ide.cma
IDETOPLOOPCMA=ide/coqidetop.cma
IDETOPEXE=bin/coqidetop$(EXE)
IDETOP=bin/coqidetop.opt$(EXE)
IDETOPBYTE=bin/coqidetop.byte$(EXE)

LINKIDE:=$(IDEDEPS) $(IDECDEPS) $(IDECMA) ide/coqide_main.mli ide/coqide_main.ml
LINKIDEOPT:=$(IDEOPTCDEPS) $(patsubst %.cma,%.cmxa,$(IDEDEPS:.cmo=.cmx)) $(IDECMA:.cma=.cmxa) ide/coqide_main.mli ide/coqide_main.ml
Expand Down Expand Up @@ -88,15 +90,15 @@ endif

coqide-files: $(IDEFILES)

ide-byteloop: $(IDETOPLOOPCMA)
ide-optloop: $(IDETOPLOOPCMA:.cma=.cmxs)
ide-toploop: ide-$(BEST)loop
ide-byteloop: $(IDETOPBYTE)
ide-optloop: $(IDETOP)
ide-toploop: $(IDETOPEXE)

ifeq ($(HASCOQIDE),opt)
$(COQIDE): $(LINKIDEOPT)
$(SHOW)'OCAMLOPT -o $@'
$(HIDE)$(OCAMLOPT) $(COQIDEFLAGS) $(OPTFLAGS) -o $@ unix.cmxa threads.cmxa lablgtk.cmxa \
lablgtksourceview2.cmxa str.cmxa $(IDEFLAGS:.cma=.cmxa) $^
$(HIDE)$(OCAMLOPT) $(COQIDEFLAGS) $(OPTFLAGS) -o $@ \
-linkpkg -package str,unix,dynlink,threads,lablgtk2.sourceview2 $(IDEFLAGS:.cma=.cmxa) $^
$(STRIP) $@
else
$(COQIDE): $(COQIDEBYTE)
Expand All @@ -105,8 +107,8 @@ endif

$(COQIDEBYTE): $(LINKIDE)
$(SHOW)'OCAMLC -o $@'
$(HIDE)$(OCAMLC) $(COQIDEFLAGS) $(BYTEFLAGS) -o $@ unix.cma threads.cma lablgtk.cma \
lablgtksourceview2.cma str.cma $(IDEFLAGS) $(IDECDEPSFLAGS) $^
$(HIDE)$(OCAMLC) $(COQIDEFLAGS) $(BYTEFLAGS) -o $@ \
-linkpkg -package str,unix,dynlink,threads,lablgtk2.sourceview2 $(IDEFLAGS) $(IDECDEPSFLAGS) $^

ide/coqide_main.ml: ide/coqide_main.ml4 config/Makefile # no camlp5deps here
$(SHOW)'CAMLP5O $<'
Expand Down Expand Up @@ -135,6 +137,29 @@ ide/ideutils.cmx: ide/ideutils.ml
$(SHOW)'OCAMLOPT $<'
$(HIDE)$(filter-out -safe-string,$(OCAMLOPT)) $(COQIDEFLAGS) $(filter-out -safe-string,$(OPTFLAGS)) -c $<

IDETOPCMA:=ide/ide_common.cma
IDETOPCMX:=$(IDETOPCMA:.cma=.cmxa)

# Special rule for coqidetop
$(IDETOPEXE): $(IDETOP:.opt=.$(BEST))
cp $< $@

$(IDETOP): ide/idetop.ml $(LINKCMX) $(LIBCOQRUN) $(IDETOPCMX)
$(SHOW)'COQMKTOP -o $@'
$(HIDE)$(OCAMLOPT) -linkall -linkpkg $(MLINCLUDES) -I ide \
-I kernel/byterun/ -cclib -lcoqrun \
$(SYSMOD) -package camlp5.gramlib \
$(LINKCMX) $(IDETOPCMX) $(OPTFLAGS) $(LINKMETADATA) $< -o $@
$(STRIP) $@
$(CODESIGN) $@

$(IDETOPBYTE): ide/idetop.ml $(LINKCMO) $(LIBCOQRUN) $(IDETOPCMA)
$(SHOW)'COQMKTOP -o $@'
$(HIDE)$(OCAMLC) -linkall -linkpkg $(MLINCLUDES) -I ide \
-I kernel/byterun/ -cclib -lcoqrun $(VMBYTEFLAGS) \
$(SYSMOD) -package camlp5.gramlib \
$(LINKCMO) $(IDETOPCMA) $(BYTEFLAGS) $< -o $@

####################
## Install targets
####################
Expand Down Expand Up @@ -164,13 +189,11 @@ install-ide-bin:

install-ide-toploop:
ifeq ($(BEST),opt)
$(MKDIR) $(FULLCOQLIB)/toploop/
$(INSTALLBIN) $(IDETOPLOOPCMA:.cma=.cmxs) $(FULLCOQLIB)/toploop/
$(INSTALLBIN) $(IDETOPEXE) $(IDETOP) $(FULLBINDIR)
endif
install-ide-toploop-byte:
ifneq ($(BEST),opt)
$(MKDIR) $(FULLCOQLIB)/toploop/
$(INSTALLBIN) $(IDETOPLOOPCMA) $(FULLCOQLIB)/toploop/
$(INSTALLBIN) $(IDETOPEXE) $(IDETOPBYTE) $(FULLBINDIR)
endif

install-ide-devfiles:
Expand Down Expand Up @@ -206,8 +229,7 @@ $(COQIDEAPP)/Contents:
$(COQIDEINAPP): ide/macos_prehook.cmx $(LINKIDEOPT) | $(COQIDEAPP)/Contents
$(SHOW)'OCAMLOPT -o $@'
$(HIDE)$(OCAMLOPT) $(COQIDEFLAGS) $(OPTFLAGS) -o $@ \
unix.cmxa lablgtk.cmxa lablgtksourceview2.cmxa str.cmxa \
threads.cmxa $(IDEFLAGS:.cma=.cmxa) $^
-linkpkg -package str,unix,dynlink,threads,lablgtk2.sourceview2 $(IDEFLAGS:.cma=.cmxa) $^
$(STRIP) $@

$(COQIDEAPP)/Contents/Resources/share: $(COQIDEAPP)/Contents
Expand Down
10 changes: 2 additions & 8 deletions Makefile.install
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,11 @@ endif

install-binaries: install-tools
$(MKDIR) $(FULLBINDIR)
$(INSTALLBIN) $(COQC) $(COQTOPEXE) $(CHICKEN) $(FULLBINDIR)
$(MKDIR) $(FULLCOQLIB)/toploop
ifeq ($(BEST),opt)
$(INSTALLBIN) $(TOPLOOPCMA:.cma=.cmxs) $(FULLCOQLIB)/toploop/
endif
$(INSTALLBIN) $(COQC) $(CHICKEN) $(COQTOPEXE) $(TOPBIN) $(FULLBINDIR)

install-byte: install-coqide-byte
$(MKDIR) $(FULLBINDIR)
$(INSTALLBIN) $(COQTOPBYTE) $(FULLBINDIR)
$(MKDIR) $(FULLCOQLIB)/toploop
$(INSTALLBIN) $(TOPLOOPCMA) $(FULLCOQLIB)/toploop/
$(INSTALLBIN) $(TOPBYTE) $(FULLBINDIR)
$(INSTALLSH) $(FULLCOQLIB) $(LINKCMO) $(PLUGINS)
ifndef CUSTOM
$(INSTALLLIB) $(DLLCOQRUN) $(FULLCOQLIB)
Expand Down
5 changes: 3 additions & 2 deletions configure.ml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ let coq_macos_version = "8.7.90" (** "[...] should be a string comprised of
three non-negative, period-separated integers [...]" *)
let vo_magic = 8791
let state_magic = 58791
let distributed_exec = ["coqtop";"coqc";"coqchk";"coqdoc";"coqworkmgr";
"coqdoc";"coq_makefile";"coq-tex";"gallina";"coqwc";"csdpcert";"coqdep"]
let distributed_exec =
["coqtop.opt"; "coqidetop.opt"; "coqqueryworker.opt"; "coqproofworker.opt"; "coqtacticworker.opt";
"coqc";"coqchk";"coqdoc";"coqworkmgr";"coq_makefile";"coq-tex";"gallina";"coqwc";"csdpcert";"coqdep"]

let verbose = ref false (* for debugging this script *)

Expand Down
2 changes: 1 addition & 1 deletion dev/base_include
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ let _ = Flags.in_toplevel := true
let _ = Constrextern.set_extern_reference
(fun ?loc _ r -> CAst.make ?loc @@ Libnames.Qualid (Nametab.shortest_qualid_of_global Id.Set.empty r));;

let go () = Coqloop.loop ~state:Option.(get !Coqloop.drop_last_doc)
let go () = Coqloop.(loop ~opts:Option.(get !drop_args) ~state:Option.(get !drop_last_doc))

let _ =
print_string
Expand Down
15 changes: 13 additions & 2 deletions dev/ci/ci-pidetop.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@ pidetop_CI_DIR="${CI_BUILD_DIR}/pidetop"

git_checkout "${pidetop_CI_BRANCH}" "${pidetop_CI_GITURL}" "${pidetop_CI_DIR}"

( cd "${pidetop_CI_DIR}" && coq_makefile -f Make -o Makefile.top && make -f Makefile.top "-j${NJOBS}" && make install-toploop -f Makefile.top )
# Travis / Gitlab have different filesystem layout due to use of
# `-local`. We need to improve this divergence but if we use Dune this
# "local" oddity goes away automatically so not bothering...
if [ -d "$COQBIN/../lib/coq" ]; then
COQOCAMLLIB="$COQBIN/../lib/"
COQLIB="$COQBIN/../lib/coq/"
else
COQOCAMLLIB="$COQBIN/../"
COQLIB="$COQBIN/../"
fi

echo -en '4\nexit' | coqtop -main-channel stdfds -toploop pidetop
( cd "${pidetop_CI_DIR}" && OCAMLPATH="$COQOCAMLLIB" jbuilder build @install )

echo -en '4\nexit' | "$pidetop_CI_DIR/_build/install/default/bin/pidetop" -coqlib "$COQLIB" -main-channel stdfds
6 changes: 6 additions & 0 deletions dev/ci/user-overlays/06859-ejgallego-stm+top.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/sh

if [ "$CI_PULL_REQUEST" = "6859" ] || [ "$CI_BRANCH" = "stm+top" ] || [ "$CI_BRANCH" = "pr-6859" ]; then
pidetop_CI_BRANCH=stm+top
pidetop_CI_GITURL=https://bitbucket.org/ejgallego/pidetop.git
fi
1 change: 0 additions & 1 deletion ide/coqidetop.mllib → ide/ide_common.mllib
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@ Serialize
Richpp
Xmlprotocol
Document
Ide_slave
19 changes: 11 additions & 8 deletions ide/ide_slave.ml → ide/idetop.ml
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ let msg_format = ref (fun () ->

(* The loop ignores the command line arguments as the current model delegates
its handing to the toplevel container. *)
let loop _args ~state =
let loop ~opts:_ ~state =
let open Vernac.State in
set_doc state.doc;
init_signal_handler ();
Expand Down Expand Up @@ -506,13 +506,16 @@ let rec parse = function
| x :: rest -> x :: parse rest
| [] -> []

let () = Coqtop.toploop_init := (fun coq_args extra_args ->
let args = parse extra_args in
CoqworkmgrApi.(init High);
coq_args, args)

let () = Coqtop.toploop_run := loop

let () = Usage.add_to_usage "coqidetop"
" --xml_format=Ppcmds serialize pretty printing messages using the std_ppcmds format\
\n --help-XML-protocol print documentation of the Coq XML protocol\n"

let islave_init ~opts extra_args =
let args = parse extra_args in
CoqworkmgrApi.(init High);
opts, args

let () =
let open Coqtop in
let custom = { init = islave_init; run = loop; } in
start_coq custom
18 changes: 6 additions & 12 deletions ide/ideutils.ml
Original file line number Diff line number Diff line change
Expand Up @@ -289,25 +289,19 @@ let coqtop_path () =
| Some s -> s
| None ->
match cmd_coqtop#get with
| Some s -> s
| None ->
try
let old_prog = Sys.executable_name in
let pos = String.length old_prog - 6 in
let i = Str.search_backward (Str.regexp_string "coqide") old_prog pos
in
let new_prog = Bytes.of_string old_prog in
Bytes.blit_string "coqtop" 0 new_prog i 6;
let new_prog = Bytes.to_string new_prog in
| Some s -> s
| None ->
try
let new_prog = System.get_toplevel_path "coqidetop" in
if Sys.file_exists new_prog then new_prog
else
let in_macos_bundle =
Filename.concat
(Filename.dirname new_prog)
(Filename.concat "../Resources/bin" (Filename.basename new_prog))
in if Sys.file_exists in_macos_bundle then in_macos_bundle
else "coqtop"
with Not_found -> "coqtop"
else "coqidetop"
with Not_found -> "coqidetop"
in file

(* In win32, when a command-line is to be executed via cmd.exe
Expand Down
Loading

0 comments on commit 382ee49

Please sign in to comment.