···109109# Some Unicode characters here and there
110110utils/misc.ml typo.non-ascii
111111runtime/sak.c typo.non-ascii
112112+tools/opam/process.sh typo.non-ascii
112113113114testsuite/tests/** typo.missing-header typo.long-line=may
114115testsuite/tests/lib-bigarray-2/bigarrf.f typo.tab linguist-language=Fortran
···8686endif
87878888DESTDIR ?=
8989-INSTALL_BINDIR := $(DESTDIR)$(BINDIR)
9090-INSTALL_LIBDIR := $(DESTDIR)$(LIBDIR)
9191-INSTALL_INCDIR=$(INSTALL_LIBDIR)/caml
9292-INSTALL_STUBLIBDIR := $(DESTDIR)$(STUBLIBDIR)
9393-INSTALL_LIBDIR_PROFILING = $(INSTALL_LIBDIR)/profiling
9494-INSTALL_MANDIR := $(DESTDIR)$(MANDIR)
9595-INSTALL_PROGRAMS_MAN_DIR := $(DESTDIR)$(PROGRAMS_MAN_DIR)
9696-INSTALL_LIBRARIES_MAN_DIR := $(DESTDIR)$(LIBRARIES_MAN_DIR)
9797-INSTALL_DOCDIR := $(DESTDIR)$(DOCDIR)
8989+9090+# Augment directories from Makefile.config / Makefile.build_config with
9191+# $(DESTDIR). i.e. each of these 5 directories may be overridden by the user,
9292+# and the compiler distribution makes no assumptions about where they are
9393+# relative to each other.
9494+INSTALL_BINDIR = $(DESTDIR)$(BINDIR)
9595+INSTALL_DOCDIR = $(DESTDIR)$(DOCDIR)
9696+INSTALL_LIBDIR = $(DESTDIR)$(LIBDIR)
9797+INSTALL_MANDIR = $(DESTDIR)$(MANDIR)
9898+INSTALL_STUBLIBDIR = $(DESTDIR)$(STUBLIBDIR)
9999+100100+# Library subdirectories. The compiler distribution does make assumptions about
101101+# these, and they cannot be freely overridden by the user.
102102+INSTALL_LIBDIR_CAML = caml
103103+INSTALL_LIBDIR_COMPILERLIBS = compiler-libs
104104+INSTALL_LIBDIR_DYNLINK = dynlink
105105+INSTALL_LIBDIR_FLEXDLL = flexdll
106106+INSTALL_LIBDIR_OCAMLDOC = ocamldoc
107107+INSTALL_LIBDIR_PROFILING = profiling
108108+INSTALL_LIBDIR_STDLIB = stdlib
109109+INSTALL_LIBDIR_SYSTHREADS = threads
110110+111111+INSTALL_MANDIR_PROGRAMS = man1
112112+INSTALL_MANDIR_LIBRARIES = man3
113113+114114+INSTALL_MODE ?= install
115115+116116+# The scripts and commands generated by this installation system allow the user
117117+# to be installing OCaml to any kind of tortuously difficult path they choose,
118118+# but it is written assuming that the directory and file names which the
119119+# distribution is in control of will follow some more restrictive rules, for
120120+# simplicity.
121121+# Paths in the installation system should always use forward slashes (these will
122122+# be automatically translated to backslashes on Windows where required). Both
123123+# the single and double quote characters are prohibited in all names and paths
124124+# (this vastly simplifies the quoting assumptions between Unix/Windows). The @
125125+# symbol is not permitted in directory names because it used internally in
126126+# filename mangling to represent forward slashes; it is permitted in filenames.
127127+# Principally owing to escaping limitations of GNU make, it is not possible to
128128+# use spaces in either source or target file names or in subdirectory names.
129129+# tools/opam/generate.ml contains some sanity checking on the paths and names
130130+# generated by these macros - make INSTALL_MODE=clone install is a good
131131+# confidence check that all rules have been adhered to.
132132+133133+# INSTALL_ITEM installs a single file, possibly with a different name and
134134+# possibly creating additional symlinks/copies
135135+# $1 = source file (may include directories)
136136+# $2 = section (bin, doc, lib, libexec, man, stublibs)
137137+# $3 = directory within section (may be empty)
138138+# $4 = target basename (may be empty)
139139+# $5 = additional basenames (either symlinked or copied, depending on what the
140140+# platform supports)
141141+# The $(origin n) dance is necessary to suppress warnings about undefined
142142+# variables.
143143+INSTALL_ITEM = \
144144+ $(INSTALL_$(INSTALL_MODE)_PREFIX)$(call INSTALL_ENSURE_DIR,$\
145145+ $(strip $(2)),$(if $(filter-out undefined,$(origin 3)),$(strip $(3))))$\
146146+ $(call INSTALL_DESPATCH_$(INSTALL_MODE)_ITEM,$\
147147+ $(strip $(1)),$\
148148+ $(strip $(2)),$\
149149+ $(if $(filter-out undefined,$(origin 3)),$(strip $(3))),$\
150150+ $(if $(filter-out undefined,$(origin 4)),$(strip $(4))),$\
151151+ $(if $(filter-out undefined,$(origin 5)),$(strip $(5))))
152152+153153+# INSTALL_ITEMS installs a series of files to a single directory
154154+# $1 = source file(s) (may include directories and glob patterns)
155155+# $2 = section (as for INSTALL_ITEM)
156156+# $3 = directory within section (may be omitted)
157157+# INSTALL_ITEMS is sometimes an alias for INSTALL_ITEM. For simplicity with
158158+# undefined variable warnings, INSTALL_DESPATCH_foo_ITEMS is passed 5 parameters
159159+# but $4 and $5 are always empty.
160160+INSTALL_ITEMS = \
161161+ $(INSTALL_$(INSTALL_MODE)_PREFIX)$(call INSTALL_ENSURE_DIR,$\
162162+ $(strip $(2)),$(if $(filter-out undefined,$(origin 3)),$(strip $(3))))$\
163163+ $(call INSTALL_DESPATCH_$(INSTALL_MODE)_ITEMS,$\
164164+ $(strip $(1)),$\
165165+ $(strip $(2)),$\
166166+ $(if $(filter-out undefined,$(origin 3)),$(strip $(3))),,)
167167+168168+# INSTALL_ITEMS_OPT is INSTALL_ITEMS, but does nothing if the source file(s) do
169169+# not exist
170170+INSTALL_ITEMS_OPT = \
171171+ $(if $(wildcard $(1)),$(call INSTALL_ITEMS, \
172172+ $(1), $(2), $(if $(filter-out undefined,$(origin 3)), $(3))))
173173+174174+INSTALL_ENSURE_DIR = \
175175+ $(if $(filter undefined,$(origin DIR_CREATED_$(subst exec,,$(1))_$(2))),$\
176176+ $(eval DIR_CREATED_$(subst exec,,$(1))_$(2):=)$\
177177+ $(call INSTALL_DESPATCH_$(INSTALL_MODE)_MKDIR,$\
178178+ $(subst exec,,$(1)),$(2)))
179179+180180+# INSTALL_RM takes a single argument which may include glob patterns of files to
181181+# be removed when performing a physical install.
182182+INSTALL_RM = $(call INSTALL_DESPATCH_$(INSTALL_MODE)_RM,$(strip $(1)))
183183+184184+# INSTALL_BEGIN and INSTALL_END are used in the root Makefile's install target
185185+INSTALL_BEGIN = $(INSTALL_DESPATCH_$(INSTALL_MODE)_BEGIN)
186186+INSTALL_END = $(INSTALL_DESPATCH_$(INSTALL_MODE)_END)
187187+188188+# Normal installation
189189+INSTALL_CMD_bin = $(INSTALL_PROG)
190190+INSTALL_CMD_doc = $(INSTALL_DATA)
191191+INSTALL_CMD_lib = $(INSTALL_DATA)
192192+INSTALL_CMD_libexec = $(INSTALL_PROG)
193193+INSTALL_CMD_man = $(INSTALL_DATA)
194194+INSTALL_CMD_stublibs = $(INSTALL_PROG)
195195+196196+INSTALL_SECTION_bin = $(INSTALL_BINDIR)
197197+INSTALL_SECTION_doc = $(INSTALL_DOCDIR)
198198+INSTALL_SECTION_lib = $(INSTALL_LIBDIR)
199199+INSTALL_SECTION_libexec = $(INSTALL_LIBDIR)
200200+INSTALL_SECTION_man = $(INSTALL_MANDIR)
201201+INSTALL_SECTION_stublibs = $(INSTALL_STUBLIBDIR)
202202+203203+QUOTE_SINGLE = '$(subst ','\'',$(1))'
204204+205205+define NEWLINE
206206+207207+208208+endef
209209+SH_AND = && \$(NEWLINE)
210210+211211+INSTALL_install_PREFIX =
212212+213213+INSTALL_DESPATCH_install_RM = rm -f $(1)
214214+215215+INSTALL_DESPATCH_install_MKDIR = \
216216+ $(MKDIR) $(call QUOTE_SINGLE,$(INSTALL_SECTION_$(1))$(addprefix /,$(2))) \
217217+ $(SH_AND)
218218+219219+MK_LINK = \
220220+ (cd "$(INSTALL_SECTION_$(2))$(addprefix /,$(3))" && \
221221+ $(LN) $(call QUOTE_SINGLE,$(1)) $(call QUOTE_SINGLE,$(4)))
222222+223223+INSTALL_DESPATCH_install_ITEM = \
224224+ $(INSTALL_CMD_$(2)) $(1) \
225225+ $(call QUOTE_SINGLE,$\
226226+ $(INSTALL_SECTION_$(2))$(addprefix /,$(3))$(addprefix /,$(4))) \
227227+ $(foreach link, $(5),$(SH_AND)$\
228228+ $(call MK_LINK,$(if $(4),$(4),$(notdir $(1))),$(2),$(3),$(link)))
229229+230230+INSTALL_DESPATCH_install_ITEMS = $(INSTALL_DESPATCH_install_ITEM)
231231+232232+INSTALL_DESPATCH_install_BEGIN = @
233233+INSTALL_DESPATCH_install_END = @
234234+235235+INSTALL_display_PREFIX = @
236236+237237+INSTALL_DESPATCH_display_RM = @
238238+239239+INSTALL_DESPATCH_display_MKDIR = \
240240+ echo $(call QUOTE_SINGLE,$\
241241+ -> MKDIR $(INSTALL_SECTION_$(1))$(addprefix /,$(2))) $(SH_AND)
242242+243243+MKLINK_display = \
244244+ echo $(call QUOTE_SINGLE,-> LN \
245245+ $(abspath $(INSTALL_SECTION_$(2))$(addprefix /,$(3))/$(1)) -> \
246246+ $(if $(4),$(4),$(notdir $(1))))
247247+248248+INSTALL_DESPATCH_display_ITEM = \
249249+ echo $(call QUOTE_SINGLE,-> INSTALL $(1) \
250250+ $(INSTALL_SECTION_$(2))$(addprefix /,$(3))$(addprefix /,$(4))) \
251251+ $(foreach link, $(5), && \
252252+ $(call MKLINK_display,$(if $(4),$(4),$(notdir $(1))),$(2),$(3),$(link)))
253253+254254+INSTALL_DESPATCH_display_ITEMS = $(INSTALL_DESPATCH_display_ITEM)
255255+256256+INSTALL_DESPATCH_display_BEGIN = @
257257+INSTALL_DESPATCH_display_END = @
258258+259259+INSTALL_list_PREFIX = @
260260+261261+INSTALL_DESPATCH_list_RM = @
262262+263263+INSTALL_DESPATCH_list_MKDIR =
264264+265265+MKLINK_list = \
266266+ echo $(call QUOTE_SINGLE,-> \
267267+ $(abspath $(INSTALL_SECTION_$(2))$(addprefix /,$(3))/$\
268268+ $(if $(4),$(4),$(notdir $(1)))))
269269+270270+INSTALL_DESPATCH_list_ITEM = \
271271+ echo $(call QUOTE_SINGLE,-> \
272272+ $(abspath $(INSTALL_SECTION_$(2))$(addprefix /,$(3))/$\
273273+ $(if $(4),$(4),$(notdir $(1))))) \
274274+ $(foreach link, $(5), && \
275275+ $(call MKLINK_list,$(if $(4),$(4),$(notdir $(1))),$(2),$(3),$(link)))
276276+277277+INSTALL_DESPATCH_list_ITEMS = \
278278+ $(foreach file, $(wildcard $(1)), \
279279+ echo $(call QUOTE_SINGLE,-> \
280280+ $(INSTALL_SECTION_$(2))$(addprefix /,$(3))/$(notdir $(file)));) \
281281+ true
282282+283283+INSTALL_DESPATCH_list_BEGIN = @
284284+INSTALL_DESPATCH_list_END = @
285285+286286+OPAM_PACKAGE_NAME ?= ocaml-compiler
287287+288288+# Generate $(OPAM_PACKAGE_NAME).install and $(OPAM_PACKAGE_NAME)-fixup.sh
289289+# (INSTALL_MODE=opam)
290290+# opam's .install format isn't quite rich enough at present to express the
291291+# installation of the compiler. In particular, we can't install the doc files to
292292+# doc/ocaml using a .install and we can't create symlinks. The things which
293293+# can't be handled by the .install file are dealt with by the fixup script
294294+# instead.
295295+296296+INVOKE = $(strip $(1)) $(call QUOTE_SINGLE,$(strip $(2)))
297297+ADD_LINE = $(call INVOKE, echo, $(2)) >> $(1)
298298+299299+# RECORD_SYMLINK_TO_INSTALL
300300+# $1 = file to install, implicitly relative to $(ROOTDIR)
301301+# $2 = section
302302+# $3 = subdirectory within $2 (may be empty)
303303+# $4 = name to install $1 (must be specified)
304304+# $5 = single name of symlink
305305+# If symlinks are supported, $1 is ignored and the three pieces of information
306306+# are recorded in create-symlinks: the directory, implicitly relative to the
307307+# prefix, in which the symlink is to be created, the source file and name of the
308308+# symlink.
309309+# These can then be munged to a cd + ln combination in the fixup script.
310310+# If symlinks are not supported, $1 is instead used to create an additional copy
311311+# of the file, using the .install file.
312312+ifeq "$(firstword $(LN))" "ln"
313313+RECORD_SYMLINK_TO_INSTALL = \
314314+ $(call ADD_LINE, $(ROOTDIR)/create-symlinks, \
315315+ $(patsubst lib%,lib,$(2))$(addprefix /,$(3)) $(4) $(5))
316316+else
317317+# Symlinks aren't available, so copy the file again using the target name
318318+RECORD_SYMLINK_TO_INSTALL = \
319319+ $(call RECORD_$(INSTALL_MODE)_ITEM_TO_INSTALL,$(1),$(2),$(3),$(5))
320320+endif
321321+322322+# Process the arguments to pass to RECORD_$(INSTALL_MODE)_ITEM_TO_INSTALL:
323323+# - Items installed to the stublibs section need to be remapped to the stublibs
324324+# subdirectory of libexec (since we install to lib/ocaml/stublibs rather than
325325+# opam's default lib/stublibs)
326326+# - Source files must be given implicitly relative to $(ROOTDIR), so prefix with
327327+# $(SUBDIR_NAME) if necessary
328328+# - Items installed to the lib/libexec sections will in fact be installed to
329329+# lib_root/libexec_root, so remap the installation directory to ocaml (i.e. to
330330+# install to lib/ocaml rather than lib)
331331+# - If no target basename has been explictly given, use the source's basename
332332+RECORD_ITEM_TO_INSTALL = \
333333+ $(if $(filter stublibs,$(2)),\
334334+ $(call RECORD_ITEM_TO_INSTALL,$\
335335+ $(1),libexec,stublibs$(addprefix /,$(3)),$(4),$(5)),\
336336+ $(call RECORD_$(INSTALL_MODE)_ITEM_TO_INSTALL,$\
337337+ $(addsuffix /,$(SUBDIR_NAME))$(1),$\
338338+ $(2),$\
339339+ $(if $(filter doc lib%,$(2)),ocaml$(addprefix /,$(3)),$(3)),$\
340340+ $(if $(4),$(4),$(notdir $(1))),$\
341341+ $(5)))
342342+343343+# All files must be explicitly installed, so evaluate the wildcards and call
344344+# INSTALL_DESPATCH_opam_ITEM for each file.
345345+INSTALL_EVALUATE_GLOBS = \
346346+ $(foreach file, $(wildcard $(1)), \
347347+ $(call INSTALL_DESPATCH_$(INSTALL_MODE)_ITEM,$(file),$(2),$(3));) \
348348+ true
349349+350350+# RECORD_FILE_TO_INSTALL
351351+# $1 = file to install, implicitly relative to $(ROOTDIR)
352352+# $2 = bin/lib/libexec/man
353353+# $3 = subdirectory within $2 (may be empty, but otherwise must end with "/")
354354+# $4 = name to install $1 (must be specified)
355355+# Writes an opam .install line to the section file for $(2). Each line consists
356356+# of a double-quoted implicit filename relative to $(ROOTDIR) and optionally a
357357+# second double-quoted implicit filename relative to the $(2) for the name to
358358+# install the file under.
359359+# e.g. "lex/ocamllex" {"ocamllex.byte"} or "expunge" {"ocaml/expunge"}
360360+RECORD_FILE_TO_INSTALL = \
361361+ $(call ADD_LINE, $(ROOTDIR)/opam-$(2), \
362362+ "$(1)" $(if $(3)$(filter-out $(notdir $(1)),$(4)), {"$(3)$(4)"}))
363363+364364+# RECORD_FILE_TO_CLONE
365365+# $1 = file to install, implicitly relative to $(ROOTDIR)
366366+# $2 = subdirectory (may be empty, but otherwise must end with "/")
367367+# $3 = name to install $1 (must be specified)
368368+# The compiler is installed as the ocaml package in opam, but the actual files
369369+# are installed from other packages (typically ocaml-compiler). For the lib
370370+# directory, the lib_root and libexec_root sections allow files to be installed
371371+# to lib/ocaml, but there's no equivalent mechanism for the doc directory. These
372372+# files are recorded to be copied manually in the fixup script.
373373+RECORD_FILE_TO_CLONE = \
374374+ $(call ADD_LINE, $(ROOTDIR)/clone-$(subst /,@,$(2)), $(1) $(3))
375375+376376+# RECORD_opam_ITEM_TO_INSTALL despatches the processed arguments of
377377+# INSTALL_DESPATCH_opam_ITEM to the appropriate RECORD_ macro.
378378+RECORD_opam_ITEM_TO_INSTALL = \
379379+ $(if $(filter doc,$(2)),\
380380+ $(call RECORD_FILE_TO_CLONE,$(1),doc/$(3),$(4)), \
381381+ $(call RECORD_FILE_TO_INSTALL,$(1),$(2),$(addsuffix /,$(3)),$(4))) \
382382+ $(foreach link, $(5), && \
383383+ $(call RECORD_SYMLINK_TO_INSTALL,$(1),$(2),$(3),$(4),$(link)))
384384+385385+INSTALL_DESPATCH_opam_ITEM = $(RECORD_ITEM_TO_INSTALL)
386386+387387+INSTALL_DESPATCH_opam_ITEMS = $(INSTALL_EVALUATE_GLOBS)
388388+389389+INSTALL_opam_PREFIX = @
390390+391391+INSTALL_DESPATCH_opam_RM = @
392392+393393+# INSTALL_MKDIR is ignored (opam creates them when executing the .install file)
394394+INSTALL_DESPATCH_opam_MKDIR =
395395+396396+INSTALL_DESPATCH_opam_BEGIN = \
397397+ rm -f opam-bin clone-* opam-lib opam-libexec opam-man create-symlinks
398398+399399+# Munge opam-bin, opam-lib, opam-libexec and opam-man into a .install file and
400400+# then munge clone-* and create-symlinks into the fixup script.
401401+INSTALL_DESPATCH_opam_END = \
402402+ $(OCAMLRUN) ./ocaml$(EXE) $(STDLIBFLAGS) \
403403+ tools/opam/generate.ml $(INSTALL_MODE) $(OPAM_PACKAGE_NAME) '$(LN)'
404404+405405+# Generate $(OPAM_PACKAGE_NAME)-clone.sh (INSTALL_MODE=clone)
406406+407407+# ld.conf is explicitly copied, rather than cloned, to allow (in principle, if
408408+# not in practice) the cloning installation to edit it.
409409+RECORD_clone_ITEM_TO_INSTALL = \
410410+ $(if $(filter runtime/ld.conf Makefile.config, $(1)), true, \
411411+ $(if $(filter libexec,$(2)), \
412412+ $(call RECORD_clone_ITEM_TO_INSTALL,$(1),lib,$(3),$(4),$(5)), \
413413+ $(call ADD_LINE, \
414414+ $(ROOTDIR)/clone-$(2)$(addprefix @,$(subst /,@,$(3))), \
415415+ $(2)$(addprefix /,$(3))/$(if $(4),$(4),$(notdir $(1)))) \
416416+ $(foreach link, $(5), && \
417417+ $(call RECORD_SYMLINK_TO_INSTALL,$(1),$(2),$(3),$(4),$(link)))))
418418+419419+INSTALL_DESPATCH_clone_ITEM = $(RECORD_ITEM_TO_INSTALL)
420420+421421+INSTALL_DESPATCH_clone_ITEMS = $(INSTALL_EVALUATE_GLOBS)
422422+423423+INSTALL_clone_PREFIX = @
424424+425425+INSTALL_DESPATCH_clone_RM = @
426426+427427+# INSTALL_MKDIR is ignored - INSTALL_DESPATCH_clone_END automatically creates
428428+# directories for each cp file.
429429+INSTALL_DESPATCH_clone_MKDIR =
430430+431431+INSTALL_DESPATCH_clone_BEGIN = rm -f clone-* create-symlinks
432432+433433+INSTALL_DESPATCH_clone_END = $(INSTALL_DESPATCH_opam_END)
9843499435FLEXDLL_SUBMODULE_PRESENT := $(wildcard $(ROOTDIR)/flexdll/Makefile)
100436···510846$(eval $(call _OCAML_NATIVE_LIBRARY,$(1)))
511847endef # OCAML_LIBRARY
512848513513-# Installing a bytecode executable, with debug information removed
514514-define INSTALL_STRIPPED_BYTE_PROG
515515-$(OCAMLRUN) $(ROOTDIR)/tools/stripdebug$(EXE) $(1) $(1).tmp \
516516-&& $(INSTALL_PROG) $(1).tmp $(2) \
517517-&& rm $(1).tmp
518518-endef # INSTALL_STRIPPED_BYTE_PROG
849849+# Strip debug information from a bytecode executable
850850+define STRIP_BYTE_PROG
851851+$(OCAMLRUN) $(ROOTDIR)/tools/stripdebug$(EXE) \
852852+ $(strip $(1)) $(strip $(1)).stripped
853853+endef # STRIP_BYTE_PROG
519854520855# ocamlc has several mechanisms for linking a bytecode image to the runtime
521856# which executes it. The exact mechanism depends on the platform and the precise
+1
api_docgen/Makefile
···1414#**************************************************************************
1515# Used by included Makefiles
1616ROOTDIR = ..
1717+SUBDIR_NAME = api_docgen
1718-include ../Makefile.build_config
18191920odoc-%:
+2-4
api_docgen/ocamldoc/Makefile
···1414#**************************************************************************
1515# Used by included Makefiles
1616ROOTDIR = ../..
1717+SUBDIR_NAME = api_docgen/ocamldoc
1718include ../Makefile.common
1819vpath %.mli ../../stdlib $(DOC_COMPILERLIBS_DIRS) $(DOC_STDLIB_DIRS)
1920···121122122123.PHONY: install
123124install:
124124- $(MKDIR) "$(INSTALL_LIBRARIES_MAN_DIR)"
125125- if test -d build/man; then \
126126- $(INSTALL_DATA) build/man/*.3o "$(INSTALL_LIBRARIES_MAN_DIR)"; \
127127- fi
125125+ $(call INSTALL_ITEMS_OPT, build/man/*.3o, man, $(INSTALL_MANDIR_LIBRARIES))
+5-7
api_docgen/odoc/Makefile
···15151616# Used by included Makefiles
1717ROOTDIR = ../..
1818+SUBDIR_NAME = api_docgen/odoc
18191920include ../Makefile.common
2021···191192# Man pages are the only installed documentation
192193.PHONY: install
193194install:
194194- $(MKDIR) "$(INSTALL_LIBRARIES_MAN_DIR)"
195195- if test -d build/man/libref ; then \
196196- $(INSTALL_DATA) build/man/libref/* "$(INSTALL_LIBRARIES_MAN_DIR)"; \
197197- fi
198198- if test -d build/man/compilerlibref ; then \
199199- $(INSTALL_DATA) build/man/libref/* "$(INSTALL_LIBRARIES_MAN_DIR)"; \
200200- fi
195195+ $(call INSTALL_ITEMS_OPT, \
196196+ build/man/libref/*, man, $(INSTALL_MANDIR_LIBRARIES))
197197+ $(call INSTALL_ITEMS_OPT, \
198198+ build/man/compilerlibref/*, man, $(INSTALL_MANDIR_LIBRARIES))
201199202200# Dependencies for stdlib modules.
203201# Use the same dependencies used for compiling .cmx files.
···1414#**************************************************************************
15151616ROOTDIR=..
1717+SUBDIR_NAME=otherlibs
1718include $(ROOTDIR)/Makefile.common
18191920# Although the OTHERLIBS variable is defined in ../Makefile.config,
···1414#**************************************************************************
15151616ROOTDIR = ..
1717+SUBDIR_NAME = stdlib
1718# NOTE: it is important that the OCAMLDEP variable is defined *before*
1819# Makefile.common gets included, so that its local definition here
1920# take precedence over its general shared definitions in Makefile.common.
···4748OPTCOMPILER=$(ROOTDIR)/ocamlopt$(EXE)
4849CAMLOPT=$(OCAMLRUN) $(OPTCOMPILER)
49505151+# At present, only META is installed to the package directory
5252+LIBNAME = stdlib
5353+5054include StdlibModules
51555256OBJS=$(addsuffix .cmo,$(STDLIB_MODULES))
···6064allopt: stdlib.cmxa std_exit.cmx
6165opt.opt: allopt
62666363-INSTALL_STDLIB_META_DIR=$(DESTDIR)$(LIBDIR)/stdlib
6464-6567.PHONY: install
6668install::
6767- $(INSTALL_DATA) \
6868- stdlib.cma std_exit.cmo *.cmi "$(INSTALL_LIBDIR)"
6969- $(MKDIR) "$(INSTALL_STDLIB_META_DIR)"
7070- $(INSTALL_DATA) META "$(INSTALL_STDLIB_META_DIR)"
6969+ $(call INSTALL_ITEMS, stdlib.cma std_exit.cmo *.cmi, lib)
7070+ $(call INSTALL_ITEMS, META, lib, $(LIBNAME))
7171ifeq "$(INSTALL_SOURCE_ARTIFACTS)" "true"
7272- $(INSTALL_DATA) \
7373- *.cmt *.cmti *.mli *.ml *.ml.in \
7474- "$(INSTALL_LIBDIR)"
7272+ $(call INSTALL_ITEMS, *.cmt *.cmti *.mli *.ml *.ml.in, lib)
7573endif
7676- $(INSTALL_DATA) $(HEADER_NAME) "$(INSTALL_LIBDIR)/$(HEADER_NAME)"
7474+ $(call INSTALL_ITEMS, $(HEADER_NAME), lib)
77757876.PHONY: installopt
7977installopt: installopt-default
80788179.PHONY: installopt-default
8280installopt-default:
8383- $(INSTALL_DATA) \
8484- stdlib.cmxa stdlib.$(A) std_exit.$(O) *.cmx \
8585- "$(INSTALL_LIBDIR)"
8181+ $(call INSTALL_ITEMS, stdlib.cmxa stdlib.$(A) std_exit.$(O) *.cmx, lib)
86828783MANGLING = $(filter true,$(SUFFIXING))
8884runtime-launch-info: tmpheader.exe
+47-5
tools/ci/actions/runner.sh
···16161717set -xe
18181919-PREFIX=~/local
1919+# The prefix is designed to be usable as an opam local switch
2020+PREFIX=~/local/_opam
20212122MAKE="make $MAKE_ARG"
2223SHELL=dash
···5657 # $CONFIG_ARG also appears last to allow settings specified here to be
5758 # overridden by the workflows.
5859 call-configure --prefix="$PREFIX" \
6060+ --docdir="$PREFIX/doc/ocaml" \
5961 --enable-flambda-invariants \
6062 --enable-ocamltest \
6163 --enable-native-toplevel \
6264 --disable-dependency-generation \
6363- $CONFIG_ARG
6565+ -C $CONFIG_ARG
6466}
65676668Build () {
···125127}
126128127129Install () {
128128- $MAKE install
130130+ $MAKE INSTALL_MODE=list install | grep '^->' | sort | uniq -d > duplicates
131131+ if [ -s duplicates ]; then
132132+ echo "The installation duplicates targets:"
133133+ cat duplicates
134134+ exit 1
135135+ fi
136136+ rm duplicates
137137+ $MAKE DESTDIR="$PWD/install" install
138138+ find $PWD/install -name _opam -type d
139139+ $MAKE INSTALL_MODE=clone install
140140+ ret="$PWD"
141141+ script="$PWD/ocaml-compiler-clone.sh"
142142+ cd "$(find $PWD/install -name _opam -type d)"
143143+ mkdir -p "share/ocaml"
144144+ cp "$ret/config.status" "$ret/config.cache" "share/ocaml"
145145+ cp "$ret/ocaml-compiler-clone.sh" "share/ocaml/clone"
146146+ sh $script ~/local/_opam
147147+ cd "$ret"
148148+ rm -rf install
149149+ rm ocaml-compiler-clone.sh
129150}
130151131152target_libdir_is_relative='^ *TARGET_LIBDIR_IS_RELATIVE *= *false'
···225246 # we would need to redo (small parts of) world.opt afterwards to
226247 # use the compiler again
227248 $MAKE check_all_arches
228228- # Ensure that .gitignore is up-to-date - this will fail if any untreacked or
249249+ # Ensure that .gitignore is up-to-date - this will fail if any untracked or
229250 # altered files exist.
230251 test -z "$(git status --porcelain)"
231252 # check that the 'clean' target also works
···234255 $MAKE -C manual distclean
235256 # check that the `distclean` target definitely cleans the tree
236257 $MAKE distclean
237237- # Check the working tree is clean
258258+ # Check the working tree is clean - config.cache is intentionally not deleted
259259+ # by any of the clean targets
260260+ rm config.cache
238261 test -z "$(git status --porcelain)"
239262 # Check that there are no ignored files
240263 test -z "$(git ls-files --others -i --exclude-standard)"
···298321 ReportBuildStatus 0
299322}
300323324324+CreateSwitch () {
325325+ # This can be switched to use the Ubuntu package when Ubuntu 26.04 is deployed
326326+ # (opam 2.1.5 in Ubuntu 24.04 is too old)
327327+ curl -Lo opam \
328328+ 'https://github.com/ocaml/opam/releases/download/2.4.1/opam-2.4.1-x86_64-linux'
329329+ chmod +x opam
330330+ ./opam init --cli=2.4 --bare --disable-sandboxing --yes --auto-setup
331331+ # This is intentionally done before the switch is created - if the install
332332+ # target creates _opam then the switch creation will fail.
333333+ $MAKE INSTALL_MODE=opam OPAM_PACKAGE_NAME=ocaml-variants install
334334+ # These commands intentionally run using opam's "default" CLI
335335+ ./opam switch create ~/local --empty
336336+ ./opam switch --switch ~/local set-invariant --no-action ocaml-option-flambda
337337+ ./opam pin add --switch ~/local --no-action --kind=path ocaml-variants .
338338+ ./opam install --switch ~/local --yes --assume-built ocaml-variants
339339+ ./opam exec --switch ~/local -- ocamlopt -v
340340+}
341341+301342case $1 in
302343configure) Configure;;
303344build) Build;;
···311352manual) BuildManual;;
312353other-checks) Checks;;
313354basic-compiler) BasicCompiler;;
355355+opam) CreateSwitch;;
314356*) echo "Unknown CI instruction: $1"
315357 exit 1;;
316358esac
+18-4
tools/ci/appveyor/appveyor_build.cmd
···22222323chcp 65001 > nul
2424set BUILD_PREFIX=🐫реализация
2525-set OCAMLROOT=%PROGRAMFILES%\Бактріан🐫
2525+set OCAMLROOT=C:\Бактріан🐫
26262727if "%1" neq "install" goto %1
2828setlocal enabledelayedexpansion
···6969 )
7070)
7171if "%CYGWIN_INSTALL_PACKAGES%" neq "" "%CYG_ROOT%\setup-x86_64.exe" --quiet-mode --no-shortcuts --no-startmenu --no-desktop --only-site --root "%CYG_ROOT%" --site "%CYG_MIRROR%" --local-package-dir "%CYG_CACHE%" %CYGWIN_FLAGS% --packages %CYGWIN_INSTALL_PACKAGES:~1%
7272-for %%P in (%CYGWIN_COMMANDS%) do "%CYG_ROOT%\bin\%%P.exe" --version 2> nul > nul || set CYGWIN_UPGRADE_REQUIRED=1
7272+for %%P in (%CYGWIN_COMMANDS%) do (
7373+ if %%P equ unzip (
7474+ "%CYG_ROOT%\bin\%%P.exe" -v 2> nul > nul || set CYGWIN_UPGRADE_REQUIRED=1
7575+ ) else (
7676+ "%CYG_ROOT%\bin\%%P.exe" --version 2> nul > nul || set CYGWIN_UPGRADE_REQUIRED=1
7777+ )
7878+)
7379"%CYG_ROOT%\bin\bash.exe" -lc "cygcheck -dc %CYGWIN_PACKAGES%"
7480if %CYGWIN_UPGRADE_REQUIRED% equ 1 (
7581 echo Cygwin package upgrade required - please go and drink coffee
···8793 if "%PORT%" equ "mingw32" set SDK=call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars32.bat"
8894)
8995%SDK%
9696+rem The environment block becomes very large on AppVeyor, which can cause
9797+rem problems for xargs in Cygwin. These two environment variables from the SDK
9898+rem infrastructure can be safely junked to reduce the size of the block.
9999+set __VSCMD_PREINIT_PATH=
100100+set EXTERNAL_INCLUDE=
90101goto :EOF
9110292103:install
···103114cd "%APPVEYOR_BUILD_FOLDER%"
104115appveyor DownloadFile "https://github.com/ocaml/flexdll/archive/%FLEXDLL_VERSION%.tar.gz" -FileName "flexdll.tar.gz" || exit /b 1
105116appveyor DownloadFile "https://github.com/ocaml/flexdll/releases/download/%FLEXDLL_VERSION%/flexdll-bin-%FLEXDLL_VERSION%.zip" -FileName "flexdll.zip" || exit /b 1
117117+appveyor DownloadFile "https://github.com/ocaml/opam/releases/download/2.4.1/opam-2.4.1-x86_64-windows.exe" -FileName "opam.exe" || exit /b 1
118118+md "%PROGRAMFILES%\flexdll"
119119+move opam.exe "%PROGRAMFILES%\flexdll"
106120rem flexdll.zip is processed here, rather than in appveyor_build.sh because the
107121rem unzip command comes from MSYS2 (via Git for Windows) and it has to be
108122rem invoked via cmd /c in a bash script which is weird(er).
···115129rem CYGWIN_COMMANDS is a corresponding command to run with --version to test
116130rem whether the package works. This is used to verify whether the installation
117131rem needs upgrading.
118118-set CYGWIN_PACKAGES=cygwin make diffutils
119119-set CYGWIN_COMMANDS=cygcheck make diff
132132+set CYGWIN_PACKAGES=cygwin make diffutils unzip
133133+set CYGWIN_COMMANDS=cygcheck make diff unzip
120134if "%PORT%" equ "mingw32" (
121135 rem mingw64-i686-runtime does not need explicitly installing, but it's useful
122136 rem to have the version reported.
···11+(**************************************************************************)
22+(* *)
33+(* OCaml *)
44+(* *)
55+(* David Allsopp, University of Cambridge & Tarides *)
66+(* *)
77+(* Copyright 2025 David Allsopp Ltd. *)
88+(* *)
99+(* All rights reserved. This file is distributed under the terms of *)
1010+(* the GNU Lesser General Public License version 2.1, with the *)
1111+(* special exception on linking described in the file LICENSE. *)
1212+(* *)
1313+(**************************************************************************)
1414+1515+(* This script is called from the root of the repository at the end of
1616+ `make INSTALL_MODE=<opam|clone> install` and is responsible for converting
1717+ the various files generated by the installation backend into final output.
1818+ Parameters are the following Makefile variables:
1919+ $1 = $(INSTALL_MODE) (opam or clone)
2020+ $2 = $(OPAM_PACKAGE_NAME)
2121+ $3 = $(LN) *)
2222+2323+let exit_because fmt = Printf.ksprintf (fun s -> prerr_endline s; exit 1) fmt
2424+2525+let () =
2626+ if Array.length Sys.argv <> 4
2727+ || Sys.argv.(1) <> "clone" && Sys.argv.(1) <> "opam" then begin
2828+ exit_because "Invalid command line arguments"
2929+ end
3030+3131+let mode = Sys.argv.(1)
3232+let package = Sys.argv.(2)
3333+let ln_command = Sys.argv.(3)
3434+3535+let output_endline oc = Printf.kfprintf (fun oc -> output_char oc '\n') oc
3636+3737+let write_install_lines oc file =
3838+ In_channel.with_open_text file @@
3939+ In_channel.fold_lines (fun _ -> output_endline oc " %s") ()
4040+4141+let remove_file = Sys.remove
4242+4343+let output_section oc section =
4444+ let file = "opam-" ^ section in
4545+ if Sys.file_exists file then begin
4646+ let section =
4747+ if section = "lib" || section = "libexec" then
4848+ section ^ "_root"
4949+ else
5050+ section
5151+ in
5252+ output_endline oc {|%s: [
5353+%a]|} section write_install_lines file;
5454+ remove_file file
5555+ end
5656+5757+(* See note in Makefile.common *)
5858+let valid_in_path = function '\'' | '"' | '\\' -> false | _ -> true
5959+let valid_in_section c = c <> '@' && valid_in_path c
6060+let valid_path path =
6161+ if String.for_all valid_in_path path then
6262+ path
6363+ else
6464+ exit_because "%S contains characters invalid in a path" path
6565+let valid_section dir =
6666+ if String.for_all valid_in_section dir then
6767+ dir
6868+ else
6969+ exit_because "%S contains characters invalid in a section" dir
7070+7171+(* [generate_install file] processes then erases opam-bin, opam-lib opam-libexec
7272+ and opam-man to produce [file] *)
7373+let generate_install file =
7474+ Out_channel.with_open_text file @@ fun oc ->
7575+ List.iter (output_section oc) ["bin"; "lib"; "libexec"; "man"];
7676+ output_endline oc {|share_root: [
7777+ "config.cache" {"ocaml/config.cache"}
7878+ "config.status" {"ocaml/config.status"}
7979+]|}
8080+8181+(* [process_clone oc process] processes clone-* in the current directory,
8282+ emitting mkdir commands to [oc] and passing the directory name and a channel
8383+ set to the start of each clone file to [process]. The clone files are erased
8484+ after processing. *)
8585+let process_clone oc process =
8686+ let process_file file =
8787+ if String.starts_with ~prefix:"clone-" file then begin
8888+ let dir =
8989+ String.map (function '@' -> '/' | c -> c)
9090+ (String.sub file 6 (String.length file - 6))
9191+ |> valid_section
9292+ in
9393+ output_endline oc {|mkdir -p "$1"'/%s'|} dir;
9494+ In_channel.with_open_text file @@ process oc dir;
9595+ remove_file file
9696+ end
9797+ in
9898+ let files = Sys.readdir Filename.current_dir_name in
9999+ Array.sort String.compare files;
100100+ Array.iter process_file files
101101+102102+(* [process_symlinks oc ~mkdir] processes create-symlinks, if it exists, writing
103103+ any required mkdir commands to [oc] if [~mkdir = true] and also the
104104+ appropriate ln / mklink commands. create-symlinks is erased after
105105+ processing. *)
106106+let process_symlinks oc ~mkdir =
107107+ let module StringSet = Set.Make(String) in
108108+ let file = "create-symlinks" in
109109+ if Sys.file_exists file then
110110+ let lines =
111111+ let parse acc line =
112112+ match String.split_on_char ' ' line with
113113+ | [dir; target; source] ->
114114+ (valid_section dir, valid_path target, valid_path source)::acc
115115+ | _ ->
116116+ exit_because "Invalid line encountered in create-symlinks"
117117+ in
118118+ In_channel.with_open_text file @@ fun ic ->
119119+ List.rev (In_channel.fold_lines parse [] ic)
120120+ in
121121+ output_endline oc {|cd "$1"|};
122122+ let _ =
123123+ let create_dir seen (dir, _, _) =
124124+ if not (StringSet.mem dir seen) && String.contains dir '/' then
125125+ output_endline oc {|mkdir -p '%s'|} dir;
126126+ StringSet.add dir seen
127127+ in
128128+ List.fold_left create_dir StringSet.empty (if mkdir then lines else [])
129129+ in
130130+ if not Sys.win32 then
131131+ let ln (dir, target, source) =
132132+ output_endline oc {|%s '%s' '%s/%s'|} ln_command target dir source
133133+ in
134134+ List.iter ln lines
135135+ else begin
136136+ let mklink (dir, target, source) =
137137+ (* Convert all slashes to _two_ backslashes *)
138138+ let to_backslashes oc s =
139139+ output_string oc (String.concat {|\\|} (String.split_on_char '/' s))
140140+ in
141141+ output_endline oc
142142+ {| cmd /c "mklink %a\\%s %s"|} to_backslashes dir source target
143143+ and cp (dir, target, source) =
144144+ output_endline oc {| $CP '%s/%s' '%s/%s'|} dir target dir source
145145+ in
146146+ output_endline oc {|cmd /c "mklink __ln_test mklink-test"|};
147147+ output_endline oc {|if test -L "$1/__ln_test"; then|};
148148+ List.iter mklink lines;
149149+ output_endline oc {|else|};
150150+ List.iter cp lines;
151151+ output_endline oc {|fi|};
152152+ output_endline oc {|rm -f __ln_test|}
153153+ end;
154154+ remove_file file
155155+156156+let copy_files oc dir =
157157+ In_channel.fold_lines (fun _ line ->
158158+ match String.split_on_char ' ' line with
159159+ | [source; dest] ->
160160+ let source = valid_path source in
161161+ let dest = valid_path dest in
162162+ output_endline oc {|cp '%s' "$1"'/%s/%s'|} source dir dest
163163+ | _ ->
164164+ exit_because "Invalid line encountered in clone files") ()
165165+166166+let clone_files oc dir ic =
167167+ output_endline oc
168168+ {|dest="$1"'/%s' xargs sh "$1/clone-files" <<'EOF'|} dir;
169169+ In_channel.fold_lines (fun _ -> output_endline oc "%s") () ic;
170170+ output_endline oc {|EOF|}
171171+172172+let () =
173173+ if mode = "opam" then begin
174174+ generate_install (package ^ ".install");
175175+ (* The script must be written with Unix line-endings on Windows *)
176176+ Out_channel.with_open_bin (package ^ "-fixup.sh") @@ fun oc ->
177177+ output_endline oc {|#!/bin/sh
178178+set -eu|};
179179+ process_clone oc copy_files;
180180+ process_symlinks oc ~mkdir:true
181181+ end else begin
182182+ (* Don't pass -p to cp on Windows - it's never going to be relevant (no
183183+ execute bit which needs preserving) and there are scenarios in which it's
184184+ more likely to fail than add anything useful (especially if copying from
185185+ a Cygwin-managed build directory to /cygdrive) *)
186186+ let preserve = if Sys.win32 then "" else "p" in
187187+ (* The script must be written with Unix line-endings on Windows *)
188188+ Out_channel.with_open_bin (package ^ "-clone.sh") @@ fun oc ->
189189+ output_endline oc {|#!/bin/sh
190190+set -eu
191191+mkdir -p "$1"
192192+rm -f "$1/__cp_test" "$1/__ln_test"
193193+if cp --reflink=always doc/ocaml/LICENSE "$1/__cp_test" 2>/dev/null; then
194194+ rm -f "$1/__cp_test"
195195+ CP='cp --reflink=always -%sf'
196196+ if ! test -e "$1/clone-files"; then
197197+ echo "$CP"' "$@" "$dest/"' > "$1/clone-files"
198198+ fi
199199+else
200200+ CP='cp -%sf'
201201+ if ! test -e "$1/clone-files"; then
202202+ if ln -f doc/ocaml/LICENSE "$1/__ln_test" 2>/dev/null; then
203203+ rm -f "$1/__ln_test"
204204+ echo 'ln -f "$@" "$dest/"' > "$1/clone-files"
205205+ else
206206+ echo "$CP"' "$@" "$dest/"' > "$1/clone-files"
207207+ fi
208208+ fi
209209+fi|} preserve preserve;
210210+ Out_channel.with_open_text "clone-share@ocaml" (fun oc ->
211211+ output_endline oc "share/ocaml/clone";
212212+ if Sys.file_exists "config.cache" then
213213+ output_endline oc "share/ocaml/config.cache");
214214+ process_clone oc clone_files;
215215+ (* ld.conf is a configuration file, so is always copied.
216216+ Makefile.config and config.status will both contain the original
217217+ prefix, which must be updated. *)
218218+ output_endline oc {|cp lib/ocaml/ld.conf "$1/lib/ocaml/ld.conf"
219219+cat > "$1/prefix.awk" <<'ENDAWK'
220220+{
221221+ rest = $0
222222+ while ((p = index(rest, ENVIRON["O"]))) {
223223+ printf "%%s%%s", substr(rest, 1, p-1), ENVIRON["N"]
224224+ rest = substr(rest, p + length(ENVIRON["O"]))
225225+ }
226226+ print rest
227227+}
228228+ENDAWK
229229+prefix="$(sed -ne 's/^prefix *= *//p' lib/ocaml/Makefile.config)"
230230+for file in lib/ocaml/Makefile.config share/ocaml/config.status; do
231231+ O="$prefix" N="$1" awk -f "$1/prefix.awk" "$file" > "$1/$file"
232232+done
233233+rm -f "$1/clone-files" "$1/prefix.awk"|};
234234+ process_symlinks oc ~mkdir:false
235235+ end
+190
tools/opam/process.sh
···11+#!/bin/sh
22+#**************************************************************************
33+#* *
44+#* OCaml *
55+#* *
66+#* David Allsopp, University of Cambridge & Tarides *
77+#* *
88+#* Copyright 2025 David Allsopp Ltd. *
99+#* *
1010+#* All rights reserved. This file is distributed under the terms of *
1111+#* the GNU Lesser General Public License version 2.1, with the *
1212+#* special exception on linking described in the file LICENSE. *
1313+#* *
1414+#**************************************************************************
1515+1616+set -eu
1717+1818+# POSIX.1-2024 (Issue 8) lifts this from being a bashism. The sub-shell dance is
1919+# necessary because set is a builtin and is permitted to abort the script
2020+# unconditionally on error.
2121+if (set -o pipefail 2> /dev/null); then
2222+ set -o pipefail
2323+fi
2424+2525+# This script is responsible for building and cloning OCaml installations. It is
2626+# invoked by both the build and install sections of an opam package.
2727+# $1 = make command (the `make` variable in opam). This should be the path to
2828+# a binary only and is invoked without word-splitting (i.e. any
2929+# additional arguments should be passed in $2 and the command is invoked
3030+# "$1").
3131+# $2 = additional arguments passed to "$1". This variable will be used
3232+# unquoted - arguments with spaces cannot be passed. From the build
3333+# section, this allows the -j argument to be specified. For the install
3434+# section, this argument must be "install".
3535+# $3 = opam build-id variable of this package.
3636+# $4 = name of the opam package to be used when generating .install and
3737+# .config files.
3838+# The remaining arguments depend on the value of $2. When it is "install":
3939+# $5 = installation prefix, which may be a native Windows path, rather than a
4040+# Cygwin path.
4141+# When $2 is not "install" (the build opam section):
4242+# $5 = "enabled" if cloning the compiler from an existing switch is permitted
4343+# and "disabled" to force the compiler to be built from sources.
4444+# $6, and any further arguments are additional options to pass to `configure`
4545+# if the compiler is built from sources.
4646+4747+make="$1"
4848+make_args="$2"
4949+build_id="$3"
5050+package_name="$4"
5151+5252+if [ x"$make_args" = 'xinstall' ]; then
5353+ prefix="$5"
5454+5555+ echo "📦 Installing the compiler to $prefix"
5656+ if [ -e 'config.status' ]; then
5757+ echo "📜 Using make install"
5858+ "$make" install
5959+ else
6060+ origin="$(tail -n 1 build-id)"
6161+ origin_prefix="$(opam var --safe --switch="$origin" prefix | tr -d '\r')"
6262+ echo "🪄 Duplicating $origin_prefix"
6363+ ( cd "$origin_prefix" && sh ./share/ocaml/clone "$prefix" )
6464+ fi
6565+6666+ exit 0
6767+fi
6868+6969+# Build the package
7070+7171+cloning="$5"
7272+shift 5
7373+# "$@" now expands to the correctly-quoted arguments to pass to configure
7474+7575+origin=''
7676+clone_mechanism=''
7777+if [ x"$cloning" = 'xenabled' ]; then
7878+ echo "🕵️ Searching for a switch containing build-id $build_id"
7979+8080+ if [ -e "$OPAM_SWITCH_PREFIX/share/ocaml/build-id" ]; then
8181+ switch="$(tail -n 1 "$OPAM_SWITCH_PREFIX/share/ocaml/build-id")"
8282+ if [ -n "$switch" ]; then
8383+ switch_share_dir="$(opam var --safe --switch="$switch" share \
8484+ | tr -d '\r')"
8585+ switch_build_id="$switch_share_dir/ocaml/build-id"
8686+ if [ -e "$switch_build_id" ]; then
8787+ if [ x"$build_id" = x"$(head -n 1 "$switch_build_id")" ]; then
8888+ echo "🔁 Prefer to re-clone from $switch"
8989+ echo "$switch" > opam-switches
9090+ origin="$switch"
9191+ if ln "$switch_build_id" __cp_test 2>/dev/null; then
9292+ rm __cp_test
9393+ clone_mechanism='hard-linking'
9494+ fi
9595+ fi
9696+ fi
9797+ fi
9898+ fi
9999+100100+ echo "🐫 Requesting list of switches from opam"
101101+ opam switch list --safe --short | tr -d '\r' | grep -Fxv "$OPAMSWITCH" \
102102+ >> opam-switches 2> /dev/null || true
103103+104104+ while IFS= read -r switch; do
105105+ switch_share_dir="$(opam var --safe --switch="$switch" share | tr -d '\r')"
106106+ switch_build_id="$switch_share_dir/ocaml/build-id"
107107+ if [ -e "$switch_build_id" ]; then
108108+ if [ x"$build_id" = x"$(head -n 1 "$switch_build_id")" ]; then
109109+ # There are three ways of cloning a switch:
110110+ # - Copy-on-Write (cp --reflink=always)
111111+ # - Hard linking
112112+ # - Copy
113113+ # Copy-on-Write is the ideal - virtually no space overhead, but with
114114+ # defence against accidental subsequent alterations. Hard linking is
115115+ # preferred over copying for the space-saving, and because the
116116+ # compiler should not being subsequently altered.
117117+ if cp --reflink=always "$switch_build_id" __cp_test 2>/dev/null; then
118118+ rm __cp_test
119119+ echo "📝 - can reflink from: $switch"
120120+ origin="$switch"
121121+ clone_mechanism='copy-on-write'
122122+ break
123123+ elif ln "$switch_build_id" __cp_test 2>/dev/null; then
124124+ rm __cp_test
125125+ if [ -z "$clone_mechanism" ]; then
126126+ echo "🔗 - can hard link from: $switch"
127127+ origin="$switch"
128128+ clone_mechanism='hard-linking'
129129+ fi
130130+ elif [ -z "$origin" ]; then
131131+ echo "📄 - can copy from: $switch"
132132+ origin="$switch"
133133+ fi
134134+ elif [ -z "$origin" ]; then
135135+ echo "⛔ - different compiler: $switch"
136136+ fi
137137+ fi
138138+ done < opam-switches
139139+fi
140140+141141+{ echo "$build_id"; echo "$origin" ; } > build-id
142142+143143+if [ -n "$origin" ]; then
144144+145145+ echo "🧬 Will clone the compiler from $origin"
146146+ test -n "$clone_mechanism" || clone_mechanism='copying'
147147+148148+ cloned='true'
149149+ clone_source="$(sed -e '1d;s/\\/\\\\/g;s/%/%%/g;s/"/\\"/g' build-id)"
150150+ case "$origin" in
151151+ */*|*\\*) clone_source="local switch $clone_source";;
152152+ *) clone_source="global switch $clone_source";;
153153+ esac
154154+155155+ cat > "$package_name.install" <<'EOF'
156156+share_root: [
157157+ "build-id" {"ocaml/build-id"}
158158+]
159159+EOF
160160+161161+else
162162+163163+ echo "🏗️ Will build the compiler from sources"
164164+165165+ cloned='false'
166166+ clone_source=''
167167+168168+ ./configure --cache-file=config.cache "$@"
169169+ "$make" $make_args
170170+ "$make" OPAM_PACKAGE_NAME=ocaml-compiler INSTALL_MODE=clone install
171171+172172+ cat > "$package_name.install" <<'EOF'
173173+share_root: [
174174+ "build-id" {"ocaml/build-id"}
175175+ "ocaml-compiler-clone.sh" {"ocaml/clone"}
176176+ "config.cache" {"ocaml/config.cache"}
177177+ "config.status" {"ocaml/config.status"}
178178+]
179179+EOF
180180+fi
181181+182182+# Create the .config file
183183+cat > "$package_name.config" <<EOF
184184+opam-version: "2.0"
185185+variables {
186186+ cloned: $cloned
187187+ clone-source: "$clone_source"
188188+ clone-mechanism: "$clone_mechanism"
189189+}
190190+EOF