Enhance toolchain
[dragora.git] / bootstrap
blob3e68b58d18b6e39ded71a84abd59041eb6386e41
1 #! /bin/sh -
3 # Builder of custom stages (cross compilers, GNU/Linux distributions)
5 # Copyright (c) 2014-2021 Matias Fonzo, <selk@dragora.org>.
7 # Licensed under the Apache License, Version 2.0 (the "License");
8 # you may not use this file except in compliance with the License.
9 # You may obtain a copy of the License at
11 # http://www.apache.org/licenses/LICENSE-2.0
13 # Unless required by applicable law or agreed to in writing, software
14 # distributed under the License is distributed on an "AS IS" BASIS,
15 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 # See the License for the specific language governing permissions and
17 # limitations under the License.
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 Targets from ${CWD}/targets/ ..."
64 for name in "${CWD}/targets"/*
66 sed -e '2q;d' "$name"
67 done
68 unset -v name
69 echo ""
72 version()
74 printf '%s' \
75 "$PROGRAM 3.27
76 Copyright (C) 2014-2021 Matias Andres Fonzo.
77 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
78 This is free software: you are free to change and redistribute it.
79 There is NO WARRANTY, to the extent permitted by law.
83 warn()
85 printf '%s\n' "$@" 1>&2
88 chkstatus_or_exit()
90 status=$?
92 if test $status -ne 0
93 then
94 echo "Return status = $status" 1>&2
95 exit "${1-2}"; # If not given, defaults to 2
98 unset -v status
101 # Function to test and extract compressed files
102 unpack()
104 for file in "$@"
106 case $file in
107 *.tar)
108 tar tf "$file" > /dev/null && \
109 tar xpf "$file"
110 chkstatus_or_exit 3
112 *.tar.gz | *.tgz | *.tar.Z )
113 gzip -cd "$file" | tar tf - > /dev/null && \
114 gzip -cd "$file" | tar xpf -
115 chkstatus_or_exit 3
117 *.tar.bz2 | *.tbz2 | *.tbz )
118 bzip2 -cd "$file" | tar tf - > /dev/null && \
119 bzip2 -cd "$file" | tar xpf -
120 chkstatus_or_exit 3
122 *.tar.lz | *.tlz )
123 lzip -cd "$file" | tar tf - > /dev/null && \
124 lzip -cd "$file" | tar xpf -
125 chkstatus_or_exit 3
127 *.tar.xz | *.txz )
128 xz -cd "$file" | tar tf - > /dev/null && \
129 xz -cd "$file" | tar xpf -
130 chkstatus_or_exit 3
132 *.zip | *.ZIP )
133 unzip -t "$file" > /dev/null && \
134 unzip "$file" > /dev/null
135 chkstatus_or_exit 3
137 *.gz)
138 gzip -t "$file" && \
139 gzip -cd "$file" > "$(basename -- "$file" .gz)"
140 chkstatus_or_exit 3
142 *.Z)
143 gzip -t "$file" && \
144 gzip -cd "$file" > "$(basename -- "$file" .Z)"
145 chkstatus_or_exit 3
147 *.bz2)
148 bzip2 -t "$file" && \
149 bzip2 -cd "$file" > "$(basename -- "$file" .bz2)"
150 chkstatus_or_exit 3
152 *.lz)
153 lzip -t "$file" && \
154 lzip -cd "$file" > "$(basename -- "$file" .lz)"
155 chkstatus_or_exit 3
157 *.xz)
158 xz -t "$file" && \
159 xz -cd "$file" > "$(basename -- "$file" .xz)"
160 chkstatus_or_exit 3
163 warn "${PROGRAM}: cannot unpack ${file}: Unsupported extension"
164 exit 1
165 esac
166 done
167 unset -v file
170 # Print a warning for good practices.
172 # Recommended practices is to set variables
173 # in front of `configure' or make(1), see:
175 # http://www.gnu.org/software/make/manual/html_node/Environment.html
176 # http://gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Defining-Variables.html
177 # http://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Setting-Output-Variables.html
179 warn_flags()
181 warn "" \
182 "WARNING: Environment variable '$1' is set." \
183 "This will be unset to avoid possible risks." \
187 ### Default values
189 BTCC="${BTCC:=cc}"
190 BTCXX="${BTCXX:=c++}"
191 BTCFLAGS="${BTCFLAGS:=-O2}"
192 BTCXXFLAGS="${BTCXXFLAGS:=-O2}"
193 BTLDFLAGS="${BTLDFLAGS:=-s}"
194 opt_keep=opt_keep.off
195 stage=0
196 libSuffix=""
197 arch="$(uname -m)" || chkstatus_or_exit
198 jobs=1
199 worktree="$CWD"
200 output=${worktree}/OUTPUT.${PROGRAM}
201 TMPDIR="${TMPDIR:=${output}/sources}"
203 # Compose vendor name adding "-" as suffix
204 test -n "$VENDOR" && VENDOR="${VENDOR}-"
206 ### Parse options
208 while getopts :ha:j:ko:s:V name
210 case $name in
212 usage
213 exit 0
216 arch="$OPTARG"
219 jobs="$OPTARG"
222 opt_keep=opt_keep
225 output="$OPTARG"
228 stage="$OPTARG"
231 version
232 exit 0
235 warn "Option '-${OPTARG}' requires an argument"
236 usage
237 exit 1
240 warn "Illegal option -- '-${OPTARG}'"
241 usage
242 exit 1
244 esac
245 done
246 shift $(( OPTIND - 1 ))
248 # Check for environment variables, print warning, unset in any case
250 test -n "$CC" && warn_flags CC
251 test -n "$CXX" && warn_flags CXX
252 test -n "$CFLAGS" && warn_flags CFLAGS
253 test -n "$CXXFLAGS" && warn_flags CXXFLAGS
254 test -n "$LDFLAGS" && warn_flags LDFLAGS
255 unset CC CXX CFLAGS CXXFLAGS LDFLAGS warn_flags
257 # Load target architecture-file
259 if test -f "${worktree}/targets/$arch"
260 then
261 echo "${PROGRAM}: Loading target $arch ..."
262 . "${worktree}/targets/$arch"
263 else
264 warn \
265 "${PROGRAM}: Target name not recognized -- '${arch}'" \
266 "See '$0 -h' for more information"
267 exit 1
270 # Determine the host to use.
272 # Set up the host if a C compiler command was exported,
273 # otherwise, a local `cc' will be used instead
275 if test -n "$BTCC"
276 then
277 host="$(${BTCC} -dumpmachine)" || chkstatus_or_exit
278 else
279 host="$(cc -dumpmachine)" || chkstatus_or_exit
282 # If the host and the target are the same triplet, it won't work.
283 # We are changing the host if it is really needed
285 if test "$host" = "$target"
286 then
287 # Rename VENDOR to 'cross'. If empty, 'cross-linux' is added
288 case "${host%-*-*}" in
289 *-*)
290 host="$(echo "$host" | sed -e 's/-[^-]*/-cross/')"
293 host="$(echo "$host" | sed -e 's/-[^-]*/-cross-linux/')"
295 esac
298 # Compose variables for the physical output,
299 # printing some useful information
301 crossdir=${output}/cross/${target}
302 rootdir=${output}/stage${stage}
304 printf '%s\n' \
305 "BTCC: $BTCC" \
306 "BTCXX: $BTCXX" \
307 "BTCFLAGS: $BTCFLAGS" \
308 "BTCXXFLAGS: $BTCXXFLAGS" \
309 "BTLDFLAGS: $BTLDFLAGS" \
310 "Host: $host" \
311 "Target: $target" \
312 "Output directory: $output" \
313 "Cross directory: $crossdir" \
314 "Root directory: $rootdir"
316 # Remove write permission for group and other
317 umask 022
319 # Create required directories
320 mkdir -p -- "$output" "$TMPDIR"
321 chkstatus_or_exit
323 # Set default PATH, propagate variables
324 PATH="${crossdir}/bin:${PATH}"
326 export PATH VENDOR TMPDIR
328 # Main loop
329 for file in ${CWD}/stages/${stage}/${@:-??-*}
331 file="${file##*/}"
333 if test ! -f "${CWD}/stages/${stage}/$file"
334 then
335 warn "${PROGRAM}: ${stage}/${file}: No such file or stage number"
336 exit 1
338 if test ! -x "${CWD}/stages/${stage}/$file"
339 then
340 warn "${PROGRAM}: ${stage}/${file}: File not executable, dodging"
341 continue;
344 ### Stage pre-settings
346 # Create sysroot directory, recreating the symlink for the stage 0
348 if test "$stage" = 0
349 then
350 mkdir -p -- "${crossdir}/$target" || chkstatus_or_exit
352 if test ! -e "${crossdir}/${target}/usr"
353 then
354 ln -sf . "${crossdir}/${target}/usr" || chkstatus_or_exit
357 # Ensure toolchain sanity for multilib purposes
358 case $arch in
359 aarch64* | arm* | i586 | *x32 | x86_64 | riscv* )
360 if test ! -e "${crossdir}/lib" && test -n "$libSuffix"
361 then
362 ln -sf lib${libSuffix} "${crossdir}/lib" || chkstatus_or_exit
365 esac
368 # Create "tools" directory, recreating the symlink for the stage 1
369 if test "$stage" = 1
370 then
371 if test ! -d "${rootdir}/tools"
372 then
373 mkdir -p -- "${rootdir}/tools" || chkstatus_or_exit
376 # Make required symlink
377 ln -sf "${rootdir}/tools" / || chkstatus_or_exit
380 echo "${PROGRAM}: Processing $file from stage $stage ..."
382 # Set trap before to run the script in order to
383 # catch the return status, exit code 2 if fails
385 trap 'chkstatus_or_exit 2' EXIT HUP INT QUIT ABRT TERM
387 # Exit immediately on any error
388 set -e
390 . "${CWD}/stages/${stage}/$file"
392 # Deactivate shell option(s)
393 set +e
395 # Reset given signals
396 trap - EXIT HUP INT QUIT ABRT TERM
398 # Delete declared directories on the cleanup() function
399 if test "$opt_keep" != opt_keep
400 then
401 if type cleanup 1> /dev/null 2> /dev/null
402 then
403 cleanup
404 chkstatus_or_exit 2
405 unset -f cleanup
409 # Back to the current working directory
410 cd -- "$CWD" || chkstatus_or_exit
411 done