qi: Allow passing compression options for tarlz(1)
[dragora.git] / bootstrap
blob3dbd97414bb37520a191cc6b4e0901dc47786525
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 Defaults for the options are specified in brackets.
45 Options:
46 -a Target architecture [${arch}]
47 -j Parallel jobs for the compiler [${jobs}]
48 -k Keep (don't delete) source directory
49 -o Output directory [${output}]
50 -s Stage number to build [${stage}]
51 -h Display this help and exit
52 -V Print version information and exit
54 Some influential environment variables:
55 TMPDIR Temporary directory for sources [${TMPDIR}]
56 BTCC C compiler command [${BTCC}]
57 BTCXX C++ compiler command [${BTCXX}]
58 BTCFLAGS C compiler flags [${BTCFLAGS}]
59 BTCXXFLAGS C++ compiler flags [${BTCXXFLAGS}]
60 BTLDFLAGS Linker flags [${BTLDFLAGS}]
61 VENDOR Vendor name to reflect on the target triplet
63 Available targets from ${CWD}/targets ...
66 for name in "${CWD}/targets"/*
68 sed -e '2q;d' "$name"
69 done
70 unset -v name
71 echo ""
74 version()
76 printf '%s' \
77 "$PROGRAM 3.31
78 Copyright (C) 2014-2022 Matias Andres Fonzo.
79 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
80 This is free software: you are free to change and redistribute it.
81 There is NO WARRANTY, to the extent permitted by law.
85 warn()
87 printf '%s\n' "$@" 1>&2
90 chkstatus_or_exit()
92 status=$?
94 if test $status -ne 0
95 then
96 echo "Return status = $status" 1>&2
97 exit "${1-2}"; # If not given, defaults to 2
100 unset -v status
103 # Function to test and extract compressed files
104 unpack()
106 for file in "$@"
108 case $file in
109 *.tar)
110 tar tf "$file" > /dev/null && \
111 tar xpf "$file"
112 chkstatus_or_exit 3
114 *.tar.gz | *.tgz | *.tar.Z )
115 gzip -cd "$file" | tar tf - > /dev/null && \
116 gzip -cd "$file" | tar xpf -
117 chkstatus_or_exit 3
119 *.tar.bz2 | *.tbz2 | *.tbz )
120 bzip2 -cd "$file" | tar tf - > /dev/null && \
121 bzip2 -cd "$file" | tar xpf -
122 chkstatus_or_exit 3
124 *.tar.lz | *.tlz )
125 lzip -cd "$file" | tar tf - > /dev/null && \
126 lzip -cd "$file" | tar xpf -
127 chkstatus_or_exit 3
129 *.tar.xz | *.txz )
130 xz -cd "$file" | tar tf - > /dev/null && \
131 xz -cd "$file" | tar xpf -
132 chkstatus_or_exit 3
134 *.zip | *.ZIP )
135 unzip -t "$file" > /dev/null && \
136 unzip "$file" > /dev/null
137 chkstatus_or_exit 3
139 *.gz)
140 gzip -t "$file" && \
141 gzip -cd "$file" > "$(basename -- "$file" .gz)"
142 chkstatus_or_exit 3
144 *.Z)
145 gzip -t "$file" && \
146 gzip -cd "$file" > "$(basename -- "$file" .Z)"
147 chkstatus_or_exit 3
149 *.bz2)
150 bzip2 -t "$file" && \
151 bzip2 -cd "$file" > "$(basename -- "$file" .bz2)"
152 chkstatus_or_exit 3
154 *.lz)
155 lzip -t "$file" && \
156 lzip -cd "$file" > "$(basename -- "$file" .lz)"
157 chkstatus_or_exit 3
159 *.xz)
160 xz -t "$file" && \
161 xz -cd "$file" > "$(basename -- "$file" .xz)"
162 chkstatus_or_exit 3
165 warn "${PROGRAM}: cannot unpack ${file}: Unsupported extension"
166 exit 1
167 esac
168 done
169 unset -v file
172 # Print a warning for good practices.
174 # Recommended practices is to set variables
175 # in front of `configure' or make(1), see:
177 # http://www.gnu.org/software/make/manual/html_node/Environment.html
178 # http://gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Defining-Variables.html
179 # http://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Setting-Output-Variables.html
181 warn_flags()
183 warn "" \
184 "WARNING: Environment variable '$1' is set." \
185 "This will be unset to avoid possible risks." \
189 ### Default values
191 BTCC="${BTCC:=gcc}"
192 BTCXX="${BTCXX:=g++}"
193 BTCFLAGS="${BTCFLAGS:=-O2}"
194 BTCXXFLAGS="${BTCXXFLAGS:=-O2}"
195 BTLDFLAGS="${BTLDFLAGS:=}"
196 opt_keep=opt_keep.off
197 stage=0
198 libSuffix=""
199 arch="$(uname -m)" || chkstatus_or_exit
200 jobs=1
201 worktree="$CWD"
202 output="${worktree}/OUTPUT.${PROGRAM}"
203 TMPDIR="${TMPDIR:=${output}/sources}"
205 # Compose vendor name adding "-" as suffix
206 test -n "$VENDOR" && VENDOR="${VENDOR}-"
208 ### Parse options
210 while getopts :ha:j:ko:s:V name
212 case $name in
214 usage
215 exit 0
218 arch="$OPTARG"
221 jobs="$OPTARG"
224 opt_keep=opt_keep
227 output="$OPTARG"
230 stage="$OPTARG"
233 version
234 exit 0
237 warn "Option '-${OPTARG}' requires an argument"
238 usage
239 exit 1
242 warn "Illegal option -- '-${OPTARG}'"
243 usage
244 exit 1
246 esac
247 done
248 shift $(( OPTIND - 1 ))
249 unset -f usage version
251 # Check for environment variables, print warning, unset in any case
253 test -n "$CC" && warn_flags CC
254 test -n "$CXX" && warn_flags CXX
255 test -n "$CFLAGS" && warn_flags CFLAGS
256 test -n "$CXXFLAGS" && warn_flags CXXFLAGS
257 test -n "$LDFLAGS" && warn_flags LDFLAGS
258 unset CC CXX CFLAGS CXXFLAGS LDFLAGS warn_flags
260 # Load target architecture-file
262 if test -f "${worktree}/targets/$arch"
263 then
264 echo "${PROGRAM}: Loading target $arch ..."
265 . "${worktree}/targets/$arch"
266 else
267 warn \
268 "${PROGRAM}: Target name not recognized -- '${arch}'" \
269 "See '$0 -h' for more information"
270 exit 1
273 # Determine the host to use.
275 # If the host and the target are the same triplet, it won't work.
276 # We are changing the host if it is really needed
278 host="$(${BTCC} -dumpmachine)" || chkstatus_or_exit
280 if test "$host" = "$target"
281 then
282 # Rename VENDOR to 'cross'. If empty, 'cross-linux' is added
283 case "${host%-*-*}" in
284 *-*)
285 host="$(echo "$host" | sed -e 's/-[^-]*/-cross/')"
288 host="$(echo "$host" | sed -e 's/-[^-]*/-cross-linux/')"
290 esac
293 # Compose variables for the physical output,
294 # printing some useful information
296 crossdir="${output}/cross/${target}"
297 rootdir="${output}/stage${stage}"
299 printf '%s\n' \
300 "BTCC: $BTCC" \
301 "BTCXX: $BTCXX" \
302 "BTCFLAGS: $BTCFLAGS" \
303 "BTCXXFLAGS: $BTCXXFLAGS" \
304 "BTLDFLAGS: $BTLDFLAGS" \
305 "Host: $host" \
306 "Target: $target" \
307 "Output directory: $output" \
308 "Cross directory: $crossdir" \
309 "Root directory: $rootdir"
311 # Remove write permission for group and other
312 umask 022
314 # Create required directories
315 mkdir -p -- "$output" "$TMPDIR"
316 chkstatus_or_exit
318 # Set default PATH, propagate variables
319 PATH="${crossdir}/bin:${PATH}"
321 export PATH VENDOR TMPDIR
323 # Main loop
324 for file in ${CWD}/stages/${stage}/${@:-??-*}
326 file="${file##*/}"
328 if test ! -f "${CWD}/stages/${stage}/$file"
329 then
330 warn "${PROGRAM}: ${stage}/${file}: No such file or stage number"
331 exit 1
333 if test ! -x "${CWD}/stages/${stage}/$file"
334 then
335 warn "${PROGRAM}: ${stage}/${file}: File not executable, dodging"
336 continue;
339 ### Stage pre-settings
341 # Create sysroot directory, recreating the symlink for the stage 0
343 if test "$stage" = 0
344 then
345 mkdir -p -- "${crossdir}/$target" || chkstatus_or_exit
347 if test ! -L "${crossdir}/${target}/usr"
348 then
349 ln -s -f . "${crossdir}/${target}/usr" || chkstatus_or_exit
352 # Ensure toolchain sanity for multilib purposes
353 case $arch in
354 aarch64* | arm* | x32 | x86_64 | i?86 | riscv* )
355 if test ! -L "${crossdir}/lib" && test -n "$libSuffix"
356 then
357 ln -s -f lib${libSuffix} "${crossdir}/lib" || chkstatus_or_exit
360 esac
363 # Create "tools" directory, recreating the symlink for the stage 1
364 if test "$stage" = 1
365 then
366 if test ! -d "${rootdir}/tools"
367 then
368 mkdir -p -- "${rootdir}/tools" || chkstatus_or_exit
371 # Check and make required symlink
372 if test ! -L /tools
373 then
374 ln -s -f "${rootdir}/tools" / || chkstatus_or_exit
378 echo "${PROGRAM}: Processing $file from stages/${stage} ..."
380 # Set trap before to run the script in order to
381 # catch the return status, exit code 2 if fails
383 trap 'chkstatus_or_exit 2' EXIT HUP INT QUIT ABRT TERM
385 # Exit immediately on any error
386 set -e
388 . "${CWD}/stages/${stage}/$file"
390 # Deactivate shell option(s)
391 set +e
393 # Reset given signals
394 trap - EXIT HUP INT QUIT ABRT TERM
396 # Delete declared directories on the cleanup() function
397 if test "$opt_keep" != opt_keep
398 then
399 if type cleanup 1> /dev/null 2> /dev/null
400 then
401 cleanup
402 chkstatus_or_exit 2
403 unset -f cleanup
407 # Back to the current working directory
408 cd -- "$CWD" || chkstatus_or_exit
409 done