bootstrap 11 KB

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