recipes: compressors/zstd: Migrated to meson's build system
[dragora.git] / bootstrap
blob4d0d332aae0a56c0cf5979c7638d0a49c089f529
1 #! /bin/sh -
2 # Builder of custom stages (cross compilers, GNU/Linux distributions)
4 # Copyright (c) 2014-2022 Matias Fonzo, <selk@dragora.org>.
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 # EXIT STATUS
20 # 0 = Successful completion
21 # 1 = Minor common errors (e.g: help usage, support not available)
22 # 2 = Command execution error
23 # 3 = Integrity check error for compressed files
25 PROGRAM="${0##*/}"
27 # Override locale settings
28 LC_ALL=C
29 LANGUAGE=C
30 export LC_ALL LANGUAGE
32 # Get physical working directory (absolute path)
33 CWD="$(CDPATH='' cd -P -- "$(dirname -- "$0")" && pwd -P)" || exit $?
35 ### Functions
37 usage()
39 printf '%s' \
40 "Usage: $PROGRAM [OPTIONS] [FILE]...
41 Builder of custom stages (cross compilers, GNU/Linux distributions).
43 Where FILE is any shell script (as long as it is executable) from
44 a stage number. Without FILE, it loads all the found scripts from
45 the stage number. Stage numbers come from the stages directory
46 (${CWD}/stages).
48 Defaults for the options are specified in brackets.
50 Options:
51 -a Target architecture [${arch}]
52 -j Parallel jobs for the compiler [${jobs}]
53 -k Keep (don't delete) source directory
54 -o Output directory [${output}]
55 -s Stage number to build [${stage}]
56 -h Display this help and exit
57 -V Print version information and exit
59 Some influential environment variables:
60 TMPDIR Temporary directory for sources [${TMPDIR}]
61 BTCC C compiler command [${BTCC}]
62 BTCXX C++ compiler command [${BTCXX}]
63 BTCFLAGS C compiler flags [${BTCFLAGS}]
64 BTCXXFLAGS C++ compiler flags [${BTCXXFLAGS}]
65 BTLDFLAGS Linker flags [${BTLDFLAGS}]
66 VENDOR Vendor name to reflect on the target triplet
68 Available targets from ${CWD}/targets ...
71 for name in "${CWD}/targets"/*
73 sed -e '2q;d' "$name"
74 done
75 unset -v name
76 echo ""
79 version()
81 printf '%s' \
82 "$PROGRAM 3.32
83 Copyright (C) 2014-2022 Matias Andres Fonzo.
84 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
85 This is free software: you are free to change and redistribute it.
86 There is NO WARRANTY, to the extent permitted by law.
90 warn()
92 printf '%s\n' "$@" 1>&2
95 chkstatus_or_exit()
97 status=$?
99 if test $status -ne 0
100 then
101 echo "Return status = $status" 1>&2
102 exit "${1-2}"; # If not given, defaults to 2
105 unset -v status
108 # Function to test and extract compressed files
109 unpack()
111 for file in "$@"
113 case $file in
114 *.tar)
115 tar tf "$file" > /dev/null && \
116 tar xpf "$file"
117 chkstatus_or_exit 3
119 *.tar.gz | *.tgz | *.tar.Z )
120 gzip -cd "$file" | tar tf - > /dev/null && \
121 gzip -cd "$file" | tar xpf -
122 chkstatus_or_exit 3
124 *.tar.bz2 | *.tbz2 | *.tbz )
125 bzip2 -cd "$file" | tar tf - > /dev/null && \
126 bzip2 -cd "$file" | tar xpf -
127 chkstatus_or_exit 3
129 *.tar.lz | *.tlz )
130 lzip -cd "$file" | tar tf - > /dev/null && \
131 lzip -cd "$file" | tar xpf -
132 chkstatus_or_exit 3
134 *.tar.xz | *.txz )
135 xz -cd "$file" | tar tf - > /dev/null && \
136 xz -cd "$file" | tar xpf -
137 chkstatus_or_exit 3
139 *.tar.zst | *.tzst )
140 zstd -cd "$file" | tar -tf - > /dev/null && \
141 zstd -cd "$file" | tar -xpf -
142 chkstatus_or_exit 3
144 *.zip | *.ZIP )
145 unzip -t "$file" > /dev/null && \
146 unzip "$file" > /dev/null
147 chkstatus_or_exit 3
149 *.gz)
150 gzip -t "$file" && \
151 gzip -cd "$file" > "$(basename -- "$file" .gz)"
152 chkstatus_or_exit 3
154 *.Z)
155 gzip -t "$file" && \
156 gzip -cd "$file" > "$(basename -- "$file" .Z)"
157 chkstatus_or_exit 3
159 *.bz2)
160 bzip2 -t "$file" && \
161 bzip2 -cd "$file" > "$(basename -- "$file" .bz2)"
162 chkstatus_or_exit 3
164 *.lz)
165 lzip -t "$file" && \
166 lzip -cd "$file" > "$(basename -- "$file" .lz)"
167 chkstatus_or_exit 3
169 *.xz)
170 xz -t "$file" && \
171 xz -cd "$file" > "$(basename -- "$file" .xz)"
172 chkstatus_or_exit 3
174 *.zst)
175 zstd -qt "$file" && \
176 zstd -cd "$file" > "$(basename -- "$file" .zst)"
177 chkstatus_or_exit 3
180 warn "${PROGRAM}: cannot unpack ${file}: Unsupported extension"
181 exit 1
182 esac
183 done
184 unset -v file
187 # Print a warning for good practices.
189 # Recommended practices is to set variables
190 # in front of `configure' or make(1), see:
192 # http://www.gnu.org/software/make/manual/html_node/Environment.html
193 # http://gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Defining-Variables.html
194 # http://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Setting-Output-Variables.html
196 warn_flags()
198 warn "" \
199 "WARNING: Environment variable '$1' is set." \
200 "This will be unset to avoid possible risks." \
204 ### Default values
206 BTCC="${BTCC:=gcc}"
207 BTCXX="${BTCXX:=g++}"
208 BTCFLAGS="${BTCFLAGS:=-O2}"
209 BTCXXFLAGS="${BTCXXFLAGS:=-O2}"
210 BTLDFLAGS="${BTLDFLAGS:=}"
211 opt_keep=opt_keep.off
212 stage=0
213 libSuffix=""
214 arch="$(uname -m)" || chkstatus_or_exit
215 jobs=1
216 worktree="$CWD"
217 output="${worktree}/OUTPUT.${PROGRAM}"
218 TMPDIR="${TMPDIR:=${output}/sources}"
220 # Compose vendor name adding "-" as suffix
221 test -n "$VENDOR" && VENDOR="${VENDOR}-"
223 ### Parse options
225 while getopts :ha:j:ko:s:V name
227 case $name in
229 usage
230 exit 0
233 arch="$OPTARG"
236 jobs="$OPTARG"
239 opt_keep=opt_keep
242 output="$OPTARG"
245 stage="$OPTARG"
248 version
249 exit 0
252 warn "Option '-${OPTARG}' requires an argument"
253 usage
254 exit 1
257 warn "Illegal option -- '-${OPTARG}'"
258 usage
259 exit 1
261 esac
262 done
263 shift $(( OPTIND - 1 ))
264 unset -f usage version
266 # Check for environment variables, print warning, unset in any case
268 test -n "$CC" && warn_flags CC
269 test -n "$CXX" && warn_flags CXX
270 test -n "$CFLAGS" && warn_flags CFLAGS
271 test -n "$CXXFLAGS" && warn_flags CXXFLAGS
272 test -n "$LDFLAGS" && warn_flags LDFLAGS
273 unset CC CXX CFLAGS CXXFLAGS LDFLAGS warn_flags
275 # Load target architecture-file
277 if test -f "${worktree}/targets/$arch"
278 then
279 echo "${PROGRAM}: Loading target $arch ..."
280 . "${worktree}/targets/$arch"
281 else
282 warn \
283 "${PROGRAM}: Target name not recognized -- '${arch}'" \
284 "See '$0 -h' for more information"
285 exit 1
288 # Determine the host to use.
290 # If the host and the target are the same triplet, it won't work.
291 # We are changing the host if it is really needed
293 host="$(${BTCC} -dumpmachine)" || chkstatus_or_exit
295 if test "$host" = "$target"
296 then
297 # Rename VENDOR to 'cross'. If empty, 'cross-linux' is added
298 case "${host%-*-*}" in
299 *-*)
300 host="$(echo "$host" | sed -e 's/-[^-]*/-cross/')"
303 host="$(echo "$host" | sed -e 's/-[^-]*/-cross-linux/')"
305 esac
308 # Compose variables for the physical output,
309 # printing some useful information
311 crossdir="${output}/cross/${target}"
312 rootdir="${output}/stage${stage}"
314 printf '%s\n' \
315 "BTCC: $BTCC" \
316 "BTCXX: $BTCXX" \
317 "BTCFLAGS: $BTCFLAGS" \
318 "BTCXXFLAGS: $BTCXXFLAGS" \
319 "BTLDFLAGS: $BTLDFLAGS" \
320 "Host: $host" \
321 "Target: $target" \
322 "Output directory: $output" \
323 "Cross directory: $crossdir" \
324 "Root directory: $rootdir"
326 # Remove write permission for group and other
327 umask 022
329 # Create required directories
330 mkdir -p -- "$output" "$TMPDIR"
331 chkstatus_or_exit
333 # Set default PATH, propagate variables
334 PATH="${crossdir}/bin:${PATH}"
336 export PATH VENDOR TMPDIR
338 # Main loop
339 for file in ${CWD}/stages/${stage}/${@:-??-*}
341 file="${file##*/}"
343 if test ! -f "${CWD}/stages/${stage}/$file"
344 then
345 warn "${PROGRAM}: ${stage}/${file}: No such file or stage number"
346 exit 1
348 if test ! -x "${CWD}/stages/${stage}/$file"
349 then
350 warn "${PROGRAM}: ${stage}/${file}: File not executable, dodging"
351 continue;
354 ### Stage pre-settings
356 # Create sysroot directory, recreating the symlink for the stage 0
358 if test "$stage" = 0
359 then
360 mkdir -p -- "${crossdir}/$target" || chkstatus_or_exit
362 if test ! -L "${crossdir}/${target}/usr"
363 then
364 ln -s -f . "${crossdir}/${target}/usr" || chkstatus_or_exit
367 # Ensure toolchain sanity for multilib purposes
368 case $arch in
369 aarch64* | arm* | x32 | x86_64 | i?86 | riscv* )
370 if test ! -L "${crossdir}/lib" && test -n "$libSuffix"
371 then
372 ln -s -f lib${libSuffix} "${crossdir}/lib" || chkstatus_or_exit
375 esac
378 # Create "tools" directory, recreating the symlink for the stage 1
379 if test "$stage" = 1
380 then
381 if test ! -d "${rootdir}/tools"
382 then
383 mkdir -p -- "${rootdir}/tools" || chkstatus_or_exit
386 # Check and make required symlink
387 if test ! -L /tools
388 then
389 ln -s -f "${rootdir}/tools" / || chkstatus_or_exit
393 echo "${PROGRAM}: Processing $file from stages/${stage} ..."
395 # Set trap before to run the script in order to
396 # catch the return status, exit code 2 if fails
398 trap 'chkstatus_or_exit 2' EXIT HUP INT QUIT ABRT TERM
400 # Exit immediately on any error
401 set -e
403 . "${CWD}/stages/${stage}/$file"
405 # Deactivate shell option(s)
406 set +e
408 # Reset given signals
409 trap - EXIT HUP INT QUIT ABRT TERM
411 # Delete declared directories on the cleanup() function
412 if test "$opt_keep" != opt_keep
413 then
414 if type cleanup 1> /dev/null 2> /dev/null
415 then
416 cleanup
417 chkstatus_or_exit 2
418 unset -f cleanup
422 # Back to the current working directory
423 cd -- "$CWD" || chkstatus_or_exit
424 done