Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
3-manifolds
GitHub Repository: 3-manifolds/Sage_macOS
Path: blob/main/Sage_framework/files/BuildPackages.sh
173 views
1
#!/usr/bin/env bash
2
3
# This script attempts to build all GAP packages contained in the current
4
# directory. Normally, you should run this script from the 'pkg'
5
# subdirectory of your GAP installation.
6
7
# You can also run it from other locations, but then you need to tell the
8
# script where your GAP root directory is, by passing it as an argument
9
# to the script with '--with-gaproot='. By default, the script assumes that
10
# the parent of the current working directory is the GAP root directory.
11
12
# If arguments are added, then they are considered packages. In that case
13
# only these packages will be built, and all others are ignored.
14
15
# You need at least 'gzip', GNU 'tar', a C compiler, sed, pdftex to run this.
16
# Some packages also need a C++ compiler.
17
18
# Contact [email protected] for questions and complaints.
19
20
# Note, that this isn't and is not intended to be a sophisticated script.
21
# Even if it doesn't work completely automatically for you, you may get
22
# an idea what to do for a complete installation of GAP.
23
24
set -e
25
26
CURDIR="$(pwd)"
27
GAPROOT="$(cd .. && pwd)"
28
COLORS=yes
29
STRICT=no # exit with non-zero exit code when encountering any failures
30
PARALLEL=no
31
PACKAGES=()
32
33
# If output does not go into a terminal (but rather into a log file),
34
# turn off colors.
35
[[ -t 1 ]] || COLORS=no
36
37
while [[ "$#" -ge 1 ]]; do
38
option="$1" ; shift
39
case "$option" in
40
--with-gaproot) GAPROOT="$1"; shift ;;
41
--with-gaproot=*) GAPROOT=${option#--with-gaproot=}; ;;
42
--parallel) PARALLEL=yes; ;;
43
44
--with-gap) GAP_EXE="$1"; shift ;;
45
--with-gap=*) GAP_EXE=${option#--with-gap=}; ;;
46
47
--no-color) COLORS=no ;;
48
--color) COLORS=yes ;;
49
50
--no-strict) STRICT=no ;;
51
--strict) STRICT=yes ;;
52
--add-package-config-*) typeset PACKAGE_CONFIG_ARGS_${option:21}="$1"; shift ;;
53
54
-*) echo "ERROR: unsupported argument $option" ; exit 1;;
55
*) PACKAGES+=("$option") ;;
56
esac
57
done
58
59
# Some helper functions for printing user messages
60
if [[ "x$COLORS" = xyes ]]
61
then
62
# print notices in green, warnings in yellow, errors in read
63
notice() { printf "\033[32m%s\033[0m\n" "$@" ; }
64
warning() { printf "\033[33mWARNING: %s\033[0m\n" "$@" ; }
65
error() { printf "\033[31mERROR: %s\033[0m\n" "$@" ; exit 1 ; }
66
std_error() { printf "\033[31m%s\033[0m\n" "$@" ; }
67
else
68
notice() { printf "%s\n" "$@" ; }
69
warning() { printf "WARNING: %s\n" "$@" ; }
70
error() { printf "ERROR: %s\n" "$@" ; exit 1 ; }
71
std_error() { printf "%s\n" "$@" ; }
72
fi
73
74
# Is someone trying to run us from inside the 'bin' directory?
75
if [[ -f BuildPackages.sh ]]
76
then
77
error "This script must be run from inside the pkg directory" \
78
"Type: cd ../pkg; ../bin/BuildPackages.sh"
79
fi
80
81
if [ "x$PARALLEL" = "xyes" ] && [ "x$STRICT" = "xyes" ]; then
82
error "The options --strict and --parallel cannot be used simultaneously"
83
fi
84
85
if [ "x$PARALLEL" = "xyes" ]; then
86
export MAKEFLAGS="${MAKEFLAGS:--j3}"
87
fi;
88
89
# If user specified no packages to build, build all packages in subdirectories.
90
if [[ ${#PACKAGES[@]} == 0 ]]
91
then
92
# Put package directory names into a bash array to avoid issues with
93
# spaces in filenames. This code will still break if there are newlines
94
# in the name.
95
old_IFS=$IFS
96
IFS=$'\n' PACKAGES=($(find . -maxdepth 2 -type f -name PackageInfo.g | sort -f))
97
IFS=$old_IFS
98
PACKAGES=( "${PACKAGES[@]%/PackageInfo.g}" )
99
fi
100
101
notice "Using GAP root $GAPROOT"
102
103
# Check whether $GAPROOT is valid
104
if [[ ! -f "$GAPROOT/sysinfo.gap" ]]
105
then
106
error "$GAPROOT is not the root of a gap installation (no sysinfo.gap)" \
107
"Please provide the absolute path of your GAP root directory as" \
108
"first argument with '--with-gaproot=' to this script."
109
fi
110
111
# read in sysinfo
112
source "$GAPROOT/sysinfo.gap"
113
114
# determine the GAP executable to call:
115
# - if the user specified one explicitly via the `--gap` option, then
116
# GAP_EXE is set and we should use that
117
# - otherwise if sysinfo.gap set the GAP variable, use that
118
# - otherwise fall back to $GAPROOT/bin/gap.sh
119
if [[ -n $GAP_EXE ]]
120
then
121
GAP="$GAP_EXE"
122
else
123
GAP="${GAP:-$GAPROOT/bin/gap.sh}"
124
fi
125
126
127
128
# detect whether GAP was built in 32bit mode
129
# TODO: once all packages have adapted to the new build system,
130
# this should no longer be necessary, as package build systems should
131
# automatically adjust to 32bit mode.
132
case "$GAP_ABI" in
133
32)
134
notice "Building with 32-bit ABI"
135
CONFIGFLAGS="CFLAGS=-m32 LDFLAGS=-m32 LOPTS=-m32 CXXFLAGS=-m32"
136
;;
137
64)
138
notice "Building with 64-bit ABI"
139
CONFIGFLAGS=""
140
;;
141
*)
142
error "Unsupported GAP ABI '$GAParch_abi'."
143
;;
144
esac
145
146
147
LOGDIR=log
148
mkdir -p "$LOGDIR"
149
150
151
# Many package require GNU make. So use gmake if available,
152
# for improved compatibility with *BSD systems where "make"
153
# is BSD make, not GNU make.
154
if hash gmake 2> /dev/null
155
then
156
MAKE=gmake
157
else
158
MAKE=make
159
fi
160
161
notice \
162
"Attempting to build GAP packages." \
163
"Note that many GAP packages require extra programs to be installed," \
164
"and some are quite difficult to build. Please read the documentation for" \
165
"packages which fail to build correctly, and only worry about packages" \
166
"you require!"
167
168
# print the given command plus arguments, single quoted, then run it
169
echo_run() {
170
# when printf is given a format string with only one format specification,
171
# it applies that format string to each argument in sequence
172
notice "Running $(printf "'%s' " "$@")"
173
"$@"
174
}
175
176
build_fail() {
177
echo ""
178
warning "Failed to build $PKG"
179
echo "$PKG" >> "$LOGDIR/fail.log"
180
if [[ $STRICT = yes ]]
181
then
182
exit 1
183
fi
184
}
185
186
run_configure_and_make() {
187
# We want to know if this is an autoconf configure script
188
# or not, without actually executing it!
189
if [[ -x autogen.sh && ! -x configure ]]
190
then
191
./autogen.sh
192
fi
193
if [[ -x configure ]]
194
then
195
if grep Autoconf ./configure > /dev/null
196
then
197
local PKG_NAME=$($GAP -q -T -A -r -M --bare <<GAPInput
198
Read("PackageInfo.g");
199
Print(GAPInfo.PackageInfoCurrent.PackageName);
200
GAPInput
201
)
202
local CONFIG_ARGS_FLAG_NAME="PACKAGE_CONFIG_ARGS_${PKG_NAME}"
203
echo_run ./configure --with-gaproot="$GAPROOT" $CONFIGFLAGS ${!CONFIG_ARGS_FLAG_NAME}
204
# hack: run `make clean` in case the package was built before with different settings
205
echo_run "$MAKE" clean
206
else
207
echo_run ./configure "$GAPROOT"
208
# hack: run `make clean` in case the package was built before with different settings
209
echo_run "$MAKE" clean
210
# hack: in browse and edim, `make clean` removes `Makefile` so run configure
211
# again to ensure we can actually build them (we could restrict this hack to
212
# the two offending packages, but since non-autoconf configure is super cheap,
213
# there seems little reason to bother)
214
echo_run ./configure "$GAPROOT"
215
fi
216
echo_run "$MAKE"
217
else
218
notice "No building required for $PKG"
219
fi
220
}
221
222
build_one_package() {
223
# requires one argument which is the package directory
224
PKG="$1"
225
[[ $GITHUB_ACTIONS = true ]] && echo "::group::$PKG"
226
echo ""
227
date
228
echo ""
229
notice "==== Checking $PKG"
230
( # start subshell
231
set -e
232
cd "$CURDIR/$PKG"
233
if [[ -x prerequisites.sh ]]
234
then
235
./prerequisites.sh "$GAPROOT"
236
fi
237
run_configure_and_make
238
) &&
239
( # start subshell
240
if [[ $GITHUB_ACTIONS = true ]]
241
then
242
echo "::endgroup::"
243
fi
244
) || build_fail
245
}
246
247
date >> "$LOGDIR/fail.log"
248
for PKG in "${PACKAGES[@]}"
249
do
250
( # start a background process
251
# cut off the ending slash (if exists)
252
PKG="${PKG%/}"
253
# cut off everything before the first slash to only keep the package name
254
# (these two commands are mainly to accommodate the logs better,
255
# as they make no difference with changing directories)
256
PKG="${PKG##*/}"
257
if [[ -e "$CURDIR/$PKG/PackageInfo.g" ]]
258
then
259
(build_one_package "$PKG" \
260
> >(tee "$LOGDIR/$PKG.out") \
261
2> >(while read line
262
do \
263
std_error "$line"
264
done \
265
> >(tee "$LOGDIR/$PKG.err" >&2) \
266
) \
267
)> >(tee "$LOGDIR/$PKG.log" ) 2>&1
268
269
# remove superfluous log files if there was no error message
270
if [[ ! -s "$LOGDIR/$PKG.err" ]]
271
then
272
rm -f "$LOGDIR/$PKG.err"
273
rm -f "$LOGDIR/$PKG.out"
274
fi
275
276
# remove log files if package needed no compilation
277
if [[ "$(grep -c 'No building required for' $LOGDIR/$PKG.log)" -ge 1 ]]
278
then
279
rm -f "$LOGDIR/$PKG.err"
280
rm -f "$LOGDIR/$PKG.out"
281
rm -f "$LOGDIR/$PKG.log"
282
fi
283
else
284
echo
285
warning "$PKG does not seem to be a package directory, skipping"
286
fi
287
) &
288
BUILD_PID=$!
289
if [ "x$PARALLEL" = "xyes" ]; then
290
# If more than 4 background jobs are running, wait for one to finish (if
291
# <wait -n> is available) or for all to finish (if only <wait> is available)
292
if [[ $(jobs -r -p | wc -l) -gt 4 ]]; then
293
wait -n 2>&1 >/dev/null || wait
294
fi
295
else
296
# wait for this package to finish building
297
if ! wait $BUILD_PID && [[ $STRICT = yes ]]
298
then
299
exit 1
300
fi
301
fi;
302
done
303
# Wait until all packages are built, if in parallel
304
wait
305
306
echo "" >> "$LOGDIR/fail.log"
307
echo ""
308
notice "Packages which failed to build are in ./$LOGDIR/fail.log"
309
310