bootstrap 10 KB

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