bootstrap 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. #! /bin/sh -
  2. #
  3. # Builder of custom stages (cross compilers, GNU/Linux distributions)
  4. #
  5. # Copyright (c) 2014-2021 Matias Fonzo, <selk@dragora.org>.
  6. #
  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
  10. #
  11. # http://www.apache.org/licenses/LICENSE-2.0
  12. #
  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.
  18. # EXIT STATUS
  19. # 0 = Successful completion
  20. # 1 = Minor common errors (e.g: help usage, support not available)
  21. # 2 = Command execution error
  22. # 3 = Integrity check error for compressed files
  23. PROGRAM="${0##*/}"
  24. # Override locale settings
  25. LC_ALL=C
  26. LANGUAGE=C
  27. export LC_ALL LANGUAGE
  28. # Get physical working directory (absolute path)
  29. CWD="$(CDPATH='' cd -P -- "$(dirname -- "$0")" && pwd -P)" || exit $?
  30. ### Functions
  31. usage()
  32. {
  33. printf '%s' \
  34. "Usage: $PROGRAM [OPTIONS] [FILE]...
  35. Builder of custom stages (cross compilers, GNU/Linux distributions).
  36. Defaults for the options are specified in brackets.
  37. Options:
  38. -a Target architecture [${arch}]
  39. -j Parallel jobs for the compiler [${jobs}]
  40. -k Keep (don't delete) source directory
  41. -o Output directory [${output}]
  42. -s Stage number to build [${stage}]
  43. -h Display this help and exit
  44. -V Print version information and exit
  45. Some influential environment variables:
  46. TMPDIR Temporary directory for sources [${TMPDIR}]
  47. BTCC C compiler command [${BTCC}]
  48. BTCXX C++ compiler command [${BTCXX}]
  49. BTCFLAGS C compiler flags [${BTCFLAGS}]
  50. BTCXXFLAGS C++ compiler flags [${BTCXXFLAGS}]
  51. BTLDFLAGS Linker flags [${BTLDFLAGS}]
  52. VENDOR Vendor name to reflect on the target triplet
  53. Targets from ${CWD}/targets/ ..."
  54. for name in "${CWD}/targets"/*
  55. do
  56. sed -e '2q;d' "$name"
  57. done
  58. unset -v name
  59. echo ""
  60. }
  61. version()
  62. {
  63. printf '%s' \
  64. "$PROGRAM 3.27
  65. Copyright (C) 2014-2021 Matias Andres Fonzo.
  66. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
  67. This is free software: you are free to change and redistribute it.
  68. There is NO WARRANTY, to the extent permitted by law.
  69. "
  70. }
  71. warn()
  72. {
  73. printf '%s\n' "$@" 1>&2
  74. }
  75. chkstatus_or_exit()
  76. {
  77. status=$?
  78. if test $status -ne 0
  79. then
  80. echo "Return status = $status" 1>&2
  81. exit "${1-2}"; # If not given, defaults to 2
  82. fi
  83. unset -v status
  84. }
  85. # Function to test and extract compressed files
  86. unpack()
  87. {
  88. for file in "$@"
  89. do
  90. case $file in
  91. *.tar)
  92. tar tf "$file" > /dev/null && \
  93. tar xpf "$file"
  94. chkstatus_or_exit 3
  95. ;;
  96. *.tar.gz | *.tgz | *.tar.Z )
  97. gzip -cd "$file" | tar tf - > /dev/null && \
  98. gzip -cd "$file" | tar xpf -
  99. chkstatus_or_exit 3
  100. ;;
  101. *.tar.bz2 | *.tbz2 | *.tbz )
  102. bzip2 -cd "$file" | tar tf - > /dev/null && \
  103. bzip2 -cd "$file" | tar xpf -
  104. chkstatus_or_exit 3
  105. ;;
  106. *.tar.lz | *.tlz )
  107. lzip -cd "$file" | tar tf - > /dev/null && \
  108. lzip -cd "$file" | tar xpf -
  109. chkstatus_or_exit 3
  110. ;;
  111. *.tar.xz | *.txz )
  112. xz -cd "$file" | tar tf - > /dev/null && \
  113. xz -cd "$file" | tar xpf -
  114. chkstatus_or_exit 3
  115. ;;
  116. *.zip | *.ZIP )
  117. unzip -t "$file" > /dev/null && \
  118. unzip "$file" > /dev/null
  119. chkstatus_or_exit 3
  120. ;;
  121. *.gz)
  122. gzip -t "$file" && \
  123. gzip -cd "$file" > "$(basename -- "$file" .gz)"
  124. chkstatus_or_exit 3
  125. ;;
  126. *.Z)
  127. gzip -t "$file" && \
  128. gzip -cd "$file" > "$(basename -- "$file" .Z)"
  129. chkstatus_or_exit 3
  130. ;;
  131. *.bz2)
  132. bzip2 -t "$file" && \
  133. bzip2 -cd "$file" > "$(basename -- "$file" .bz2)"
  134. chkstatus_or_exit 3
  135. ;;
  136. *.lz)
  137. lzip -t "$file" && \
  138. lzip -cd "$file" > "$(basename -- "$file" .lz)"
  139. chkstatus_or_exit 3
  140. ;;
  141. *.xz)
  142. xz -t "$file" && \
  143. xz -cd "$file" > "$(basename -- "$file" .xz)"
  144. chkstatus_or_exit 3
  145. ;;
  146. *)
  147. warn "${PROGRAM}: cannot unpack ${file}: Unsupported extension"
  148. exit 1
  149. esac
  150. done
  151. unset -v file
  152. }
  153. # Print a warning for good practices.
  154. #
  155. # Recommended practices is to set variables
  156. # in front of `configure' or make(1), see:
  157. #
  158. # http://www.gnu.org/software/make/manual/html_node/Environment.html
  159. # http://gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Defining-Variables.html
  160. # http://www.gnu.org/savannah-checkouts/gnu/autoconf/manual/autoconf-2.69/html_node/Setting-Output-Variables.html
  161. warn_flags()
  162. {
  163. warn "" \
  164. "WARNING: Environment variable '$1' is set." \
  165. "This will be unset to avoid possible risks." \
  166. ""
  167. }
  168. ### Default values
  169. BTCC="${BTCC:=cc}"
  170. BTCXX="${BTCXX:=c++}"
  171. BTCFLAGS="${BTCFLAGS:=-O2}"
  172. BTCXXFLAGS="${BTCXXFLAGS:=-O2}"
  173. BTLDFLAGS="${BTLDFLAGS:=-s}"
  174. opt_keep=opt_keep.off
  175. stage=0
  176. libSuffix=""
  177. arch="$(uname -m)" || chkstatus_or_exit
  178. jobs=1
  179. worktree="$CWD"
  180. output=${worktree}/OUTPUT.${PROGRAM}
  181. TMPDIR="${TMPDIR:=${output}/sources}"
  182. # Compose vendor name adding "-" as suffix
  183. test -n "$VENDOR" && VENDOR="${VENDOR}-"
  184. ### Parse options
  185. while getopts :ha:j:ko:s:V name
  186. do
  187. case $name in
  188. h)
  189. usage
  190. exit 0
  191. ;;
  192. a)
  193. arch="$OPTARG"
  194. ;;
  195. j)
  196. jobs="$OPTARG"
  197. ;;
  198. k)
  199. opt_keep=opt_keep
  200. ;;
  201. o)
  202. output="$OPTARG"
  203. ;;
  204. s)
  205. stage="$OPTARG"
  206. ;;
  207. V)
  208. version
  209. exit 0
  210. ;;
  211. :)
  212. warn "Option '-${OPTARG}' requires an argument"
  213. usage
  214. exit 1
  215. ;;
  216. \?)
  217. warn "Illegal option -- '-${OPTARG}'"
  218. usage
  219. exit 1
  220. ;;
  221. esac
  222. done
  223. shift $(( OPTIND - 1 ))
  224. # Check for environment variables, print warning, unset in any case
  225. test -n "$CC" && warn_flags CC
  226. test -n "$CXX" && warn_flags CXX
  227. test -n "$CFLAGS" && warn_flags CFLAGS
  228. test -n "$CXXFLAGS" && warn_flags CXXFLAGS
  229. test -n "$LDFLAGS" && warn_flags LDFLAGS
  230. unset CC CXX CFLAGS CXXFLAGS LDFLAGS warn_flags
  231. # Load target architecture-file
  232. if test -f "${worktree}/targets/$arch"
  233. then
  234. echo "${PROGRAM}: Loading target $arch ..."
  235. . "${worktree}/targets/$arch"
  236. else
  237. warn \
  238. "${PROGRAM}: Target name not recognized -- '${arch}'" \
  239. "See '$0 -h' for more information"
  240. exit 1
  241. fi
  242. # Determine the host to use.
  243. #
  244. # Set up the host if a C compiler command was exported,
  245. # otherwise, a local `cc' will be used instead
  246. if test -n "$BTCC"
  247. then
  248. host="$(${BTCC} -dumpmachine)" || chkstatus_or_exit
  249. else
  250. host="$(cc -dumpmachine)" || chkstatus_or_exit
  251. fi
  252. # If the host and the target are the same triplet, it won't work.
  253. # We are changing the host if it is really needed
  254. if test "$host" = "$target"
  255. then
  256. # Rename VENDOR to 'cross'. If empty, 'cross-linux' is added
  257. case "${host%-*-*}" in
  258. *-*)
  259. host="$(echo "$host" | sed -e 's/-[^-]*/-cross/')"
  260. ;;
  261. *)
  262. host="$(echo "$host" | sed -e 's/-[^-]*/-cross-linux/')"
  263. ;;
  264. esac
  265. fi
  266. # Compose variables for the physical output,
  267. # printing some useful information
  268. crossdir=${output}/cross/${target}
  269. rootdir=${output}/stage${stage}
  270. printf '%s\n' \
  271. "BTCC: $BTCC" \
  272. "BTCXX: $BTCXX" \
  273. "BTCFLAGS: $BTCFLAGS" \
  274. "BTCXXFLAGS: $BTCXXFLAGS" \
  275. "BTLDFLAGS: $BTLDFLAGS" \
  276. "Host: $host" \
  277. "Target: $target" \
  278. "Output directory: $output" \
  279. "Cross directory: $crossdir" \
  280. "Root directory: $rootdir"
  281. # Remove write permission for group and other
  282. umask 022
  283. # Create required directories
  284. mkdir -p -- "$output" "$TMPDIR"
  285. chkstatus_or_exit
  286. # Set default PATH, propagate variables
  287. PATH="${crossdir}/bin:${PATH}"
  288. export PATH VENDOR TMPDIR
  289. # Main loop
  290. for file in ${CWD}/stages/${stage}/${@:-??-*}
  291. do
  292. file="${file##*/}"
  293. if test ! -f "${CWD}/stages/${stage}/$file"
  294. then
  295. warn "${PROGRAM}: ${stage}/${file}: No such file or stage number"
  296. exit 1
  297. fi
  298. if test ! -x "${CWD}/stages/${stage}/$file"
  299. then
  300. warn "${PROGRAM}: ${stage}/${file}: File not executable, dodging"
  301. continue;
  302. fi
  303. ### Stage pre-settings
  304. # Create sysroot directory, recreating the symlink for the stage 0
  305. if test "$stage" = 0
  306. then
  307. mkdir -p -- "${crossdir}/$target" || chkstatus_or_exit
  308. if test ! -e "${crossdir}/${target}/usr"
  309. then
  310. ln -sf . "${crossdir}/${target}/usr" || chkstatus_or_exit
  311. fi
  312. # Ensure toolchain sanity for multilib purposes
  313. case $arch in
  314. aarch64* | arm* | i586 | *x32 | x86_64 | riscv* )
  315. if test ! -e "${crossdir}/lib" && test -n "$libSuffix"
  316. then
  317. ln -sf lib${libSuffix} "${crossdir}/lib" || chkstatus_or_exit
  318. fi
  319. ;;
  320. esac
  321. fi
  322. # Create "tools" directory, recreating the symlink for the stage 1
  323. if test "$stage" = 1
  324. then
  325. if test ! -d "${rootdir}/tools"
  326. then
  327. mkdir -p -- "${rootdir}/tools" || chkstatus_or_exit
  328. fi
  329. # Make required symlink
  330. ln -sf "${rootdir}/tools" / || chkstatus_or_exit
  331. fi
  332. echo "${PROGRAM}: Processing $file from stage $stage ..."
  333. # Set trap before to run the script in order to
  334. # catch the return status, exit code 2 if fails
  335. trap 'chkstatus_or_exit 2' EXIT HUP INT QUIT ABRT TERM
  336. # Exit immediately on any error
  337. set -e
  338. . "${CWD}/stages/${stage}/$file"
  339. # Deactivate shell option(s)
  340. set +e
  341. # Reset given signals
  342. trap - EXIT HUP INT QUIT ABRT TERM
  343. # Delete declared directories on the cleanup() function
  344. if test "$opt_keep" != opt_keep
  345. then
  346. if type cleanup 1> /dev/null 2> /dev/null
  347. then
  348. cleanup
  349. chkstatus_or_exit 2
  350. unset -f cleanup
  351. fi
  352. fi
  353. # Back to the current working directory
  354. cd -- "$CWD" || chkstatus_or_exit
  355. done