-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathcompile-ocaml.sh
executable file
·187 lines (138 loc) · 4.86 KB
/
compile-ocaml.sh
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
#!/bin/bash
set -euo pipefail
IFS=$' \n\t'
# This script compiles OCaml using the current version of Menhir and verifies
# that it behaves exactly as expected.
# One can use either the table back-end (used by standard OCaml) or the new
# code back-end (using a slightly modified copy of OCaml 4.13).
USE_TABLE_BACKEND=true
for arg in "$@" ; do
case "$arg" in
--table ) USE_TABLE_BACKEND=true; shift;;
--code ) USE_TABLE_BACKEND=false; shift;;
*) echo "Unknown argument: $arg"; break;;
esac
done
# This working copy of Menhir's repository.
MENHIR_ROOT=$(pwd)
# We use a dedicated opam switch where it is permitted to uninstall/reinstall
# Menhir.
if opam switch list | grep 'test-menhir' >/dev/null ; then
echo "The switch test-menhir already exists." ;
else
echo "Creating switch test-menhir..." ;
opam switch create test-menhir 4.13.1 ;
echo "Installing required packages..." ;
opam install --yes dune ;
fi
eval "$(opam env --set-switch --switch test-menhir)"
# Uninstall Menhir if it is installed.
# We are not sure whether it was installed via opam or directly
# via [make install], so we try both uninstallation methods.
echo "Attempting to remove menhir if already installed..."
# read -p "Can I remove it [Enter/^C]?" -n 1 -r ;
(opam remove menhir menhirLib menhirSdk || true) >/dev/null 2>&1
(make -C "$MENHIR_ROOT" uninstall || true) >/dev/null 2>&1
# Check if everything has been committed.
# This seems required for [opam pin] to work properly.
if git status --porcelain | grep -v compile-ocaml ; then
echo "Error: there remain uncommitted changes." ;
git status ;
exit 1 ;
fi
# This function runs a command silently, and prints its execution time.
execute () {
echo "$1" > .command
T="$(date +%s)"
if eval "$1" >log.out 2>log.err ; then
T="$(($(date +%s)-T))"
echo " $T seconds." ;
else
code=$?
echo " failure."
cat log.err
exit $code
fi
}
# Check out a fresh copy of OCaml at a specific tag.
TEMPDIR=/tmp/menhir-test-ocaml
mkdir -p $TEMPDIR
cd $TEMPDIR
rm -rf ocaml
echo -n "Cloning OCaml..."
if $USE_TABLE_BACKEND ; then
execute "git clone [email protected]:ocaml/ocaml.git --depth 1 --branch 4.13.1"
else
execute "git clone [email protected]:fpottier/ocaml.git --depth 1 --branch code"
fi
cd ocaml
# Configure and compile OCaml. This step does not depend on Menhir.
echo -n "Configuring OCaml..."
execute "./configure"
echo -n "Compiling OCaml..."
execute "make -j"
ls -l ocamlc
if false ; then
echo -n "Testing OCaml..."
execute "make -C testsuite parallel"
execute "make -C testsuite clean"
fi
# Install Menhir.
# Should we install Menhir via [make install] or via [opam]?
# [make install], which invokes [dune install], is likely to be much
# faster (especially if Menhir has already been compiled in its
# working directory). Unfortunately, I have seen dune (2.8.2) become
# confused and install files partly in one switch, partly in another,
# so perhaps installing via [opam pin ...] is preferable.
echo -n "Installing Menhir..."
if true ; then
# Installation via opam.
execute "make -C $MENHIR_ROOT pin"
else
# Installation via [make install].
execute "make -C $MENHIR_ROOT install"
fi
ls -l "$(which menhir)"
# Re-compile OCaml's parser using Menhir.
echo -n "Recompiling OCaml's parser using Menhir..."
execute "make promote-menhir"
echo -n "Committing the recompiled parser..."
execute "git add boot/menhir && git commit -m 'make promote-menhir'"
# Take a snapshot of the ASTs produced by the current parser.
# We do this only when OCaml's standard repository is used.
# The custom repository used when $USE_TABLE_BACKEND is false
# already contains a committed snapshot of the correct ASTs.
if $USE_TABLE_BACKEND ; then
echo -n "Constructing ASTs for all source files..."
execute "make -j build-all-asts"
echo -n "Committing all ASTs..."
execute "make list-all-asts | xargs git add && git commit -m 'Build all ASTs.'"
fi
# Compile OCaml (again).
# Cleaning up first should be unnecessary, but let's make sure the
# compiler is correctly reconstructed from scratch.
echo -n "Cleaning up..."
execute "make clean"
echo -n "Compiling OCaml..."
execute "make -j"
ls -l ocamlc
if false ; then
echo -n "Testing OCaml..."
execute "make ocamltest"
execute "make -C testsuite parallel"
fi
# Reconstruct all ASTs.
# Removing them first should be unnecessary, but let's make sure they
# are correctly reconstructed from scratch.
echo -n "Removing previous ASTs..."
execute "make list-all-asts | xargs rm -f"
echo -n "Constructing ASTs for all source files..."
execute "make -j build-all-asts"
# Compare the ASTs produced by the current parser with the snapshot.
rm -f .command log.{err,out}
if git diff --exit-code >/dev/null ; then
echo "Success: the original parser and the recompiled parser agree."
else
echo "Failure: the original parser and the recompiled parser disagree."
echo "cd $TEMPDIR/ocaml && git status"
fi