forked from ocaml-flambda/flambda-backend
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMakefile.in
416 lines (395 loc) · 16.6 KB
/
Makefile.in
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
#**************************************************************************
#* *
#* The Flambda backend project for OCaml *
#* *
#* Copyright 2020--2021 Jane Street Group LLC *
#* *
#**************************************************************************
# CR mshinwell: Find out how to get something like "set -eu" in effect.
prefix=@prefix@
stage0_prefix=@stage0_prefix@
stage1_prefix=@stage1_prefix@
stage2_prefix=@stage2_prefix@
middle_end=@middle_end@
dune=@dune@
# The Flambda backend compiler build proceeds, from cold, in three stages.
# We call these (in order) stage0, stage1 and stage2. They are documented
# below.
.DEFAULT_GOAL := stage2
# Building stage0 is the same as an upstream compiler build with make. This is
# done in an rsynced tree to avoid polluting the ocaml/ subdirectory (see
# below for more details). We need to make sure the separate tree is in
# sync with the ocaml/ directory first, in case files were added or removed.
#
# We use the -i option to rsync in order to short-circuit a null build with
# make, since it seems faster.
#
# CR-someday mshinwell: We should replace this with a coldstart using dune.
.PHONY: stage0
stage0: _build0/config.status
rm -f .rsync-output
rsync -i -a --filter=':- $$(pwd)/ocaml/.gitignore' \
$$(pwd)/ocaml/ $$(pwd)/_build0 \
| grep -v '/$$' \
| tee .rsync-output
if [ -s .rsync-output ] || ! [ -d @stage0_prefix@ ]; then \
(cd _build0 && \
$(MAKE) world.opt && \
$(MAKE) ocamlnat && \
$(MAKE) install); \
fi
# stage1 builds the Flambda backend compiler using the stage0 compiler.
#
# At the end, we have a working Flambda backend compiler, equivalent to having
# done "make ocamlopt" upstream. For testing with a broken middle or backend,
# e.g. if the stdlib doesn't compile, you can stop here and run
# _build1/default/flambda_backend_main.exe.
#
# At this point we don't yet have a standard library and a set of otherlibs
# whose .cmx files are compatible with this new compiler. Neither are the
# Flambda backend compiler, or the compilerlibs that form it, built with the
# Flambda backend compiler itself. These steps comprise stage2.
#
# This code should use build contexts instead of --build-dir.
.PHONY: stage1
stage1: ocaml-stage1-config.status stage0 \
ocaml/otherlibs/dynlink/natdynlinkops2 \
flags.sexp
cp ocaml-stage1-config.status ocaml/config.status
(cd ocaml && ./config.status)
PATH=$(stage0_prefix)/bin:$$PATH \
$(dune) build --profile=release --build-dir=_build1 @install
(cd _build1/install/default/bin && \
rm -f ocamllex && \
ln -s ocamllex.opt ocamllex)
# CR mshinwell: We should add targets that don't use --profile=release, for
# speed, and also ensuring that warnings are errors. We should also consider
# adding a new Dune profile that is like "release" but has warnings as errors.
# stage2 rebuilds the whole compiler system with the Flambda backend compiler
# itself, including the stdlib, otherlibs, compilerlibs, etc. The result is
# equivalent to having done "make world.opt && make ocamlnat" upstream.
.PHONY: stage2
stage2: ocaml-stage2-config.status stage1
cp ocaml-stage2-config.status ocaml/config.status
(cd ocaml && ./config.status)
PATH=$(stage1_prefix)/bin:$$PATH \
$(dune) build --profile=release --build-dir=_build2 @install
# This target is like a polling version of upstream "make ocamlopt" (based
# on the stage1 target, above).
# It is likely to be what's most often wanted for day-to-day development of
# features, especially large ones that take a long time to get to compile,
# in the middle end and backend.
.PHONY: hacking
hacking: ocaml-stage1-config.status stage0 \
ocaml/otherlibs/dynlink/natdynlinkops2 \
flags.sexp
cp ocaml-stage1-config.status ocaml/config.status
(cd ocaml && ./config.status)
PATH=$(stage0_prefix)/bin:$$PATH \
$(dune) build -w --profile=release --build-dir=_build1 @install
# The stage0 configure step configures the tree to build pretty much the
# bare minimum that we need for building stage1.
# Currently the middle end for stage0 will match the selected middle end
# for the Flambda backend compiler.
_build0/config.status: ocaml/configure.ac
rm -rf _build0
mkdir _build0
rsync -a $$(pwd)/ocaml/ $$(pwd)/_build0
(cd _build0 && \
cat ../configure_opts | xargs -0 ./configure -C \
--prefix=@stage0_prefix@ \
--disable-ocamldoc \
--disable-ocamltest \
--disable-debug-runtime \
--disable-instrumented-runtime \
--disable-debugger)
# stage1 has already been configured by running the configure script.
# It is configured according to any options requested by the user, including
# selection of the middle end, but the prefix is set to a temporary build
# directory.
# This configures stage2 to have the same configure options as stage1
# except that the prefix is set to the ultimate installation directory.
# We save the config.status file (which is executable) for fast reconfiguration
# of the ocaml/ subdirectory during the dune builds for stage1 and stage2.
# The stage2 configure can be run by make in parallel with that for stage0.
# We add --enable-ocamltest so that the config.status generated here can be
# immediately reused for the "compare" target (see below).
ocaml-stage2-config.status: ocaml/configure.ac
rm -rf _stage2_configure
mkdir _stage2_configure
rsync -a --filter=':- $$(pwd)/ocaml/.gitignore' \
$$(pwd)/ocaml/ $$(pwd)/_stage2_configure
(cd _stage2_configure && \
cat ../configure_opts | xargs -0 ./configure -C \
--prefix=$(prefix) \
--enable-ocamltest \
--disable-ocamldoc && \
cp config.status ../ocaml-stage2-config.status)
# We need to augment dune's substitutions so this part isn't so
# difficult. We use /bin/echo to avoid builtin variants of "echo"
# which don't accept "-n". Unfortunately if there are no
# NATDYNLINKOPS, we need to provide a harmless option, otherwise dune
# will provide '' on the command line to ocamlopt which causes an
# error.
# CR mshinwell: This should be moved into the upstream dune build system.
ocaml/otherlibs/dynlink/natdynlinkops2: ocaml-stage1-config.status
cp ocaml-stage1-config.status ocaml/config.status
(cd ocaml && ./config.status)
cat ocaml/Makefile.config \
| sed 's/^NATDYNLINKOPTS=$$/NATDYNLINKOPTS=-g/' \
| grep '^NATDYNLINKOPTS=' \
| sed 's/^[^=]*=\(.*\)/-ccopt\n"\1"/' \
> ocaml/otherlibs/dynlink/natdynlinkops
/bin/echo -n $$(cat ocaml/Makefile.config \
| sed 's/^NATDYNLINKOPTS=$$/NATDYNLINKOPTS=-bin-annot/' \
| grep '^NATDYNLINKOPTS=' \
| sed 's/^[^=]*=\(.*\)/\1/') \
> ocaml/otherlibs/dynlink/natdynlinkops2
if [ "$$(cat ocaml/otherlibs/dynlink/natdynlinkops2)" \
!= "-bin-annot" ]; \
then \
/bin/echo -n "-ccopt" > ocaml/otherlibs/dynlink/natdynlinkops1; \
else \
/bin/echo -n "-bin-annot" > ocaml/otherlibs/dynlink/natdynlinkops1; \
fi
# Extract compilation flags from Makefile.config of stage1
# and write them to a file that dune can use in stage1 and stage2.
.PHONY: flags.sexp
flags.sexp: ocaml-stage1-config.status
cp ocaml-stage1-config.status ocaml/config.status
(cd ocaml && ./config.status)
grep -q '^FUNCTION_SECTIONS=true' ocaml/Makefile.config; \
if [ $$? -eq 0 ] ; then \
/bin/echo -n "(:standard -function-sections)" > ocamlopt_flags.sexp; \
else \
/bin/echo -n "(:standard)" > ocamlopt_flags.sexp; \
fi
# note: it looks like the use of "$(...)" with a command spanning over
# two lines triggers a bug in GNU make 3.81, that will as a consequence
# change the file name. It also looks like the bug is not triggered by
# "`...`".
/bin/echo -n "( `grep \"^OC_CFLAGS=\" ocaml/Makefile.config \
| sed 's/^OC_CFLAGS=//'` )" > oc_cflags.sexp
/bin/echo -n "( `grep \"^OC_CPPFLAGS=\" ocaml/Makefile.config \
| sed 's/^OC_CPPFLAGS=//'` )" > oc_cppflags.sexp
/bin/echo -n "( `grep \"^SHAREDLIB_CFLAGS=\" ocaml/Makefile.config \
| sed 's/^SHAREDLIB_CFLAGS=//'` )" > sharedlib_cflags.sexp
# Most of the installation tree is correctly set up by dune, but we need to
# copy it to the final destination, and rearrange a few things to match
# upstream.
.PHONY: install
install: stage2
mkdir -p $(prefix)
rsync --copy-links -r $(stage2_prefix)/bin $(prefix)
rsync --copy-links -r $(stage2_prefix)/lib $(prefix)
rm -f $(prefix)/bin/ocamllex
ln -s $(prefix)/bin/ocamllex.opt $(prefix)/bin/ocamllex
rm -f $(prefix)/bin/flambda_backend.main*
rm -rf $(prefix)/lib/ocaml-variants
rm -rf $(prefix)/lib/stublibs
rm -f $(prefix)/lib/ocaml/META
rm -f $(prefix)/lib/ocaml/dune-package
rm -f $(prefix)/lib/ocaml/compiler-libs/*.cmo
rm -rf $(prefix)/lib/flambda_backend
for file in topdirs opttopdirs; do \
for ext in cmi mli cmt cmti; do \
cp -f $(prefix)/lib/ocaml/compiler-libs/$${file}.$$ext \
$(prefix)/lib/ocaml; \
done; \
done
# This target only runs the dune-based tests, not the upstream testsuite.
# stage2 needs to have been built first.
.PHONY: runtest
runtest:
# It's a shame that dune needs the stage1 compiler on the path here.
# Ideally that would be inaccessible within tests (to prevent mistakes
# such as running "ocamlopt" rather than one of the stage2 binaries).
PATH=$(stage1_prefix)/bin:$$PATH \
$(dune) runtest --profile=release --build-dir=_build2
# The following horror will be removed when work to allow the testsuite to
# run on an installed tree (led by David Allsopp) is completed.
# stage2 needs to have been built first.
.PHONY: runtest-upstream
runtest-upstream:
rm -rf _runtest
mkdir _runtest
cp -a ocaml/testsuite _runtest/testsuite
# replace backend-specific testsuite/tools with their new versions
rm _runtest/testsuite/tools/*
cp -a testsuite/tools/* _runtest/testsuite/tools/
(cd _runtest/testsuite/tools && \
ln -s ../../../ocaml/testsuite/tools/Makefile Makefile)
(cd _runtest && ln -s ../ocaml/Makefile.tools Makefile.tools)
(cd _runtest && ln -s ../ocaml/Makefile.config Makefile.config)
cp _build2/install/default/bin/* _runtest/
# There seems to be an assumption that ocamlc/ocamlopt/ocamllex are
# bytecode...
cp -f _build2/install/default/bin/ocamlc.byte _runtest/ocamlc
cp -f _build2/install/default/bin/ocamlopt.byte _runtest/ocamlopt
mkdir _runtest/lex
mv _runtest/ocamllex.byte _runtest/lex/ocamllex
mkdir _runtest/yacc
mv _runtest/ocamlyacc _runtest/yacc/
(cd _runtest && ln -s ../_build2/default/ocaml/runtime runtime)
(cd _runtest && ln -s ../_build2/install/default/lib/ocaml stdlib)
# compilerlibs
mkdir _runtest/compilerlibs
cp _build2/install/default/lib/ocaml/compiler-libs/*.cma \
_runtest/compilerlibs
cp _build2/install/default/lib/ocaml/compiler-libs/*.a \
_runtest/compilerlibs
cp _build2/install/default/lib/ocaml/compiler-libs/*.cmxa \
_runtest/compilerlibs
mkdir _runtest/toplevel
cp _build2/default/ocaml/toplevel/.ocamltoplevel.objs/byte/*.cm* \
_runtest/toplevel/
# Various directories are put on the -I paths by tools/Makefile;
# utils/ is one such, so we just dump the .cm* files in there for
# various things.
mkdir _runtest/utils
cp _build2/install/default/lib/ocaml/compiler-libs/*.cmi \
_runtest/utils
cp _build2/install/default/lib/ocaml/compiler-libs/*.cmo \
_runtest/utils
cp _build2/install/default/lib/ocaml/compiler-libs/*.cmx \
_runtest/utils
cp _build2/install/default/lib/ocaml/*.cmi _runtest/utils
cp _build2/install/default/lib/ocaml/*.cma _runtest/utils
cp _build2/install/default/lib/ocaml/*.a _runtest/utils
cp _build2/install/default/lib/ocaml/*.cmxa _runtest/utils
cp _build2/default/ocaml/.ocamlcommon.objs/native/config.o \
_runtest/utils
# Suppress linker errors about -I directories not existing.
for dir in asmcomp bytecomp driver file_formats lambda middle_end \
parsing typing; do ln -s utils _runtest/$$dir; done
# dynlink
mkdir -p _runtest/otherlibs/dynlink
cp _build2/install/default/lib/ocaml/dynlink* \
_runtest/otherlibs/dynlink
# stublibs
mkdir -p _runtest/lib/ocaml/stublibs/
cp _build2/install/default/lib/ocaml/stublibs/*.so \
_runtest/lib/ocaml/stublibs
# str
mkdir -p _runtest/otherlibs/str
cp _build2/install/default/lib/ocaml/str*.cmi \
_runtest/otherlibs/str
cp _build2/install/default/lib/ocaml/libstr*.a \
_runtest/otherlibs/str
cp _build2/install/default/lib/ocaml/str*.cma \
_runtest/otherlibs/str
cp _build2/install/default/lib/ocaml/str*.cmxa \
_runtest/otherlibs/str
cp _build2/install/default/lib/ocaml/str*.a \
_runtest/otherlibs/str
cp _build2/install/default/lib/ocaml/str*.cmx \
_runtest/otherlibs/str
# unix
mkdir -p _runtest/otherlibs/unix
cp _build2/install/default/lib/ocaml/unix*.cmi \
_runtest/otherlibs/unix
cp _build2/install/default/lib/ocaml/libunix*.a \
_runtest/otherlibs/unix
cp _build2/install/default/lib/ocaml/unix*.cma \
_runtest/otherlibs/unix
cp _build2/install/default/lib/ocaml/unix*.cmxa \
_runtest/otherlibs/unix
cp _build2/install/default/lib/ocaml/unix*.a \
_runtest/otherlibs/unix
cp _build2/install/default/lib/ocaml/unix*.cmx \
_runtest/otherlibs/unix
# systhreads
mkdir -p _runtest/otherlibs/systhreads
cp _build2/install/default/lib/ocaml/threads/*.cmi \
_runtest/otherlibs/systhreads
cp _build2/install/default/lib/ocaml/threads/*.cma \
_runtest/otherlibs/systhreads
cp _build2/install/default/lib/ocaml/threads/*.a \
_runtest/otherlibs/systhreads
cp _build2/install/default/lib/ocaml/threads/*.cmxa \
_runtest/otherlibs/systhreads
cp _build2/install/default/lib/ocaml/threads/*.cmx \
_runtest/otherlibs/systhreads
# ocamldebug
mkdir _runtest/debugger
mv _runtest/ocamldebug _runtest/debugger
cp _build2/default/ocaml/debugger/.main.eobjs/byte/*.cm* \
_runtest/debugger
# The ast_invariants test needs VERSION to be present. In fact ideally
# we should have all the source files in _runtest too for this test,
# but for the moment we accept it being a weaker check. We're not
# working on parts of the compiler that deal with the AST anyway in
# this repo.
touch _runtest/VERSION
# tools
mkdir _runtest/tools
cp _build2/default/ocaml/tools/ocamlmklib_byte.bc \
_runtest/tools/ocamlmklib
cp _build2/default/ocaml/tools/ocamlobjinfo_byte.bc \
_runtest/tools/ocamlobjinfo
cp ./_build2/install/default/lib/ocaml/objinfo_helper _runtest/tools
# ocamltest itself
mkdir _runtest/ocamltest
# This is deliberately run with the stage0 compiler in case the new
# one is broken. As such, we use the stage1 build dir, not that from
# stage2.
# This might be causing a spurious rebuild of the runtime
PATH=$(stage0_prefix)/bin:$$PATH \
$(dune) build --profile=release --build-dir=_build1 \
ocaml/tools/cmpbyt.bc
PATH=$(stage0_prefix)/bin:$$PATH \
$(dune) build --profile=release --build-dir=_build1 \
ocaml/ocamltest/ocamltest.byte
cp _build1/default/ocaml/tools/cmpbyt.bc _runtest/tools/cmpbyt
# We should build the native ocamltest too.
cp _build1/default/ocaml/ocamltest/ocamltest.byte \
_runtest/ocamltest/ocamltest
(export OCAMLSRCDIR=$$(pwd)/_runtest; \
export CAML_LD_LIBRARY_PATH=$$(pwd)/_runtest/lib/ocaml/stublibs; \
cd _runtest/testsuite \
&& if $$(which parallel > /dev/null 2>&1); \
then make parallel; \
else make all; \
fi)
# Compare the Flambda backend installation tree against the upstream one.
# "make install" needs to have been done first.
#
# We can't use the stage0 installation directory to compare against because
# it won't have been configured with the correct options. Instead we build
# a fresh upstream compiler using the same configure options as the user
# originally specified when they configured the Flambda backend tree.
.PHONY: compare
compare: _compare/config.status
rm -f .rsync-output-compare
rsync -i -a --filter=':- $$(pwd)/ocaml/.gitignore' \
$$(pwd)/ocaml/ $$(pwd)/_compare \
| grep -v '/$$' \
| tee .rsync-output-compare
if [ -s .rsync-output-compare ] || ! [ -d _compare/_install ]; then \
(cd _compare && \
$(MAKE) world.opt && \
$(MAKE) ocamlnat && \
$(MAKE) install); \
fi
./scripts/compare.sh $$(pwd)/_compare/_install $(prefix) \
@stage0_prefix@/bin/ocamlobjinfo.opt
# CR mshinwell: Why does the ocamltest build complain about
# Ocaml_directories being missing?
_compare/config.status: ocaml/configure.ac
rm -rf _compare
mkdir _compare
rsync -a --filter=':- $$(pwd)/ocaml/.gitignore' \
$$(pwd)/ocaml/ $$(pwd)/_compare
(cd _compare && \
cat ../configure_opts | xargs -0 ./configure -C \
--prefix=$$(pwd)/_install \
--disable-stdlib-manpages \
--disable-ocamltest \
--disable-ocamldoc)
# For Github Actions checks
.PHONY: ci
ci:
$(MAKE) stage2
$(MAKE) install
$(MAKE) runtest
$(MAKE) runtest-upstream