bootstrap 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. #! /bin/sh -
  2. #
  3. # Builder of custom stages (cross compilers, GNU/Linux distributions)
  4. #
  5. # Copyright (c) 2014-2018 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 name
  29. CWD=$(CDPATH= cd -P -- $(dirname -- "$0") && printf "$PWD")
  30. #### Functions
  31. usage() {
  32. printf "%s\n" \
  33. "Builder of custom stages (cross compilers, GNU/Linux distributions)" \
  34. "" \
  35. "Usage: $PROGRAM [OPTION]... [FILE]..." \
  36. "" \
  37. "Defaults for the options are specified in brackets." \
  38. "" \
  39. "Options:" \
  40. " -h display this help and exit" \
  41. " -V print version information and exit" \
  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. "" \
  48. "Some influential environment variables:" \
  49. " TMPDIR temporary directory for sources [${TMPDIR}]" \
  50. " BTCC C compiler command [${BTCC}]" \
  51. " BTCXX C++ compiler command [${BTCXX}]" \
  52. " BTCFLAGS C compiler flags [${BTCFLAGS}]" \
  53. " BTCXXFLAGS C++ compiler flags [${BTCXXFLAGS}]" \
  54. " BTLDFLAGS linker flags [${BTLDFLAGS}]" \
  55. " VENDOR vendor name to reflect on the target triplet" \
  56. "" \
  57. "Supported architectures (targets):"
  58. for arch in "${CWD}/targets"/*
  59. do
  60. printf "${arch##*/} "
  61. done
  62. echo
  63. }
  64. version()
  65. {
  66. printf "%s\n" \
  67. "$PROGRAM 3.18" \
  68. "Copyright (C) 2014-2018 Matias Andres Fonzo." \
  69. "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>" \
  70. "This is free software: you are free to change and redistribute it." \
  71. "There is NO WARRANTY, to the extent permitted by law."
  72. }
  73. warn()
  74. {
  75. echo "$@" 1>&2
  76. }
  77. chkstatus_or_exit()
  78. {
  79. status=$?
  80. if test $status -ne 0
  81. then
  82. echo "Return status = $status" 1>&2
  83. exit ${1-2}; # If not given, defaults to 2
  84. fi
  85. unset status
  86. }
  87. # Function to test and extract compressed files
  88. unpack()
  89. {
  90. for file in "$@"
  91. do
  92. case $file in
  93. *.tar)
  94. tar tf "$file" > /dev/null && \
  95. tar xpf "$file"
  96. chkstatus_or_exit 3
  97. ;;
  98. *.tar.gz | *.tgz | *.tar.Z )
  99. gzip -cd "$file" | tar tf - > /dev/null && \
  100. gzip -cd "$file" | tar xpf -
  101. chkstatus_or_exit 3
  102. ;;
  103. *.tar.bz2 | *.tbz2 | *.tbz )
  104. bzip2 -cd "$file" | tar tf - > /dev/null && \
  105. bzip2 -cd "$file" | tar xpf -
  106. chkstatus_or_exit 3
  107. ;;
  108. *.tar.lz | *.tlz )
  109. lzip -cd "$file" | tar tf - > /dev/null && \
  110. lzip -cd "$file" | tar xpf -
  111. chkstatus_or_exit 3
  112. ;;
  113. *.tar.xz | *.txz )
  114. xz -cd "$file" | tar tf - > /dev/null && \
  115. xz -cd "$file" | tar xpf -
  116. chkstatus_or_exit 3
  117. ;;
  118. *.zip | *.ZIP )
  119. unzip -t "$file" > /dev/null && \
  120. unzip "$file" > /dev/null
  121. chkstatus_or_exit 3
  122. ;;
  123. *.gz)
  124. gzip -t "$file" && \
  125. gzip -cd "$file" > "$(basename -- $file .gz)"
  126. chkstatus_or_exit 3
  127. ;;
  128. *.Z)
  129. gzip -t "$file" && \
  130. gzip -cd "$file" > "$(basename -- $file .Z)"
  131. chkstatus_or_exit 3
  132. ;;
  133. *.bz2)
  134. bzip2 -t "$file" && \
  135. bzip2 -cd "$file" > "$(basename -- $file .bz2)"
  136. chkstatus_or_exit 3
  137. ;;
  138. *.lz)
  139. lzip -t "$file" && \
  140. lzip -cd "$file" > "$(basename -- $file .lz)"
  141. chkstatus_or_exit 3
  142. ;;
  143. *.xz)
  144. xz -t "$file" && \
  145. xz -cd "$file" > "$(basename -- $file .xz)"
  146. chkstatus_or_exit 3
  147. ;;
  148. *)
  149. warn "${PROGRAM}: cannot unpack ${file}: Unsupported extension"
  150. exit 1
  151. esac
  152. done
  153. unset file
  154. }
  155. # Warning for good practices.
  156. #
  157. # Recommended practices is to set variables
  158. # in front of `configure', or make(1); see:
  159. #
  160. # http://www.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. # http://www.gnu.org/software/make/manual/make.html#Environment
  163. warn_flags()
  164. {
  165. warn "WARNING: Environment variable '$1' is set." \
  166. "This will be unset to avoid possible risks." \
  167. ""
  168. }
  169. #### Default values
  170. BTCC="${BTCC:=cc}"
  171. BTCXX="${BTCXX:=c++}"
  172. BTCFLAGS="${BTCFLAGS:=-g0 -Os}"
  173. BTCXXFLAGS="${BTCXXFLAGS:=$BTCFLAGS}"
  174. BTLDFLAGS="${BTLDFLAGS:=-s}"
  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. # Check for environment variables, print warning, unset in any case
  226. test "${CC:+CC_defined}" = CC_defined && warn_flags CC
  227. test "${CXX:+CXX_defined}" = CXX_defined && warn_flags CXX
  228. test "${CFLAGS:+CFLAGS_defined}" = CFLAGS_defined && warn_flags CFLAGS
  229. test "${CXXFLAGS:+CXXFLAGS_defined}" = CXXFLAGS_defined && warn_flags CXXFLAGS
  230. test "${LDFLAGS:+LDFLAGS_defined}" = LDFLAGS_defined && warn_flags LDFLAGS
  231. unset CC CXX CFLAGS CXXFLAGS LDFLAGS warn_flags
  232. # Load target architecture-file
  233. if test -f "${worktree}/targets/$arch"
  234. then
  235. echo "${PROGRAM}: Loading target $arch ..."
  236. . "${worktree}/targets/$arch"
  237. else
  238. warn \
  239. "${PROGRAM}: Target name not recognized -- '${arch}'" \
  240. "See '$0 -h' for more information"
  241. exit 1
  242. fi
  243. # Determine the host to use.
  244. #
  245. # Set up the host if a C compiler command was exported,
  246. # otherwise, a local `cc' will be used instead
  247. if test -n "$BTCC"
  248. then
  249. host="$(${BTCC} -dumpmachine)" || chkstatus_or_exit
  250. else
  251. host="$(cc -dumpmachine)" || chkstatus_or_exit
  252. fi
  253. # If the host and the target are the same triplet, it won't work.
  254. # We are changing the host if it is really needed
  255. if test "$host" = "$target"
  256. then
  257. # Rename VENDOR to 'cross'. If empty, 'cross-linux' is added
  258. case "${host%-*-*}" in
  259. *-*)
  260. host="$(echo "$host" | sed -e 's/-[^-]*/-cross/')"
  261. ;;
  262. *)
  263. host="$(echo "$host" | sed -e 's/-[^-]*/-cross-linux/')"
  264. ;;
  265. esac
  266. fi
  267. # Compose variables for the physical output,
  268. # printing some useful information
  269. crossdir=${output}/cross/${target}
  270. rootdir=${output}/stage${stage}
  271. printf "%s\n" \
  272. "BTCC: $BTCC" \
  273. "BTCXX: $BTCXX" \
  274. "BTCFLAGS: $BTCFLAGS" \
  275. "BTCXXFLAGS: $BTCXXFLAGS" \
  276. "BTLDFLAGS: $BTLDFLAGS" \
  277. "Host: $host" \
  278. "Target: $target" \
  279. "Output directory: $output" \
  280. "Cross directory: $crossdir" \
  281. "Root directory: $rootdir"
  282. # Remove write permission for group and other
  283. umask 022
  284. # Create required directories
  285. if test ! -d "$output"
  286. then
  287. mkdir -p -- "$output" || chkstatus_or_exit
  288. fi
  289. if test ! -d "$TMPDIR"
  290. then
  291. mkdir -p -- "$TMPDIR" || chkstatus_or_exit
  292. fi
  293. # Set default PATH, propagate variables
  294. PATH="${crossdir}/bin:${PATH}"
  295. export PATH VENDOR TMPDIR
  296. # Main loop
  297. for file in "${CWD}/stages/${stage}"/${@:-??-*}
  298. do
  299. file="${file##*/}"
  300. if test ! -f "${CWD}/stages/${stage}/$file"
  301. then
  302. warn "${PROGRAM}: ${stage}/${file}: No such file or stage number"
  303. exit 1
  304. fi
  305. if test ! -x "${CWD}/stages/${stage}/$file"
  306. then
  307. warn "${PROGRAM}: ${stage}/${file}: File not executable, dodging"
  308. continue;
  309. fi
  310. #### Stage pre-settings
  311. # Create sysroot directory, recreating the symlink for the stage 0
  312. if test "$stage" = 0
  313. then
  314. mkdir -p -- "${crossdir}/$target" || chkstatus_or_exit
  315. if test ! -e "${crossdir}/${target}/usr"
  316. then
  317. ln -sf . "${crossdir}/${target}/usr" || chkstatus_or_exit
  318. fi
  319. # Ensure toolchain sanity for multilib purposes
  320. case $arch in
  321. i586 | *x32 | x86_64 )
  322. if test ! -e "${crossdir}/lib" -a -n "$libSuffix"
  323. then
  324. ln -sf lib${libSuffix} "${crossdir}/lib" || chkstatus_or_exit
  325. fi
  326. ;;
  327. esac
  328. fi
  329. # Create "tools" directory, recreating the symlink for the stage 1
  330. if test "$stage" = 1
  331. then
  332. if test ! -d "${rootdir}/tools"
  333. then
  334. mkdir -p -- "${rootdir}/tools" || chkstatus_or_exit
  335. fi
  336. # Make required symlink
  337. ln -sf "${rootdir}/tools" / || chkstatus_or_exit
  338. fi
  339. echo "${PROGRAM}: Processing $file from stage $stage ..."
  340. # Set trap before to run the script in order to
  341. # catch the return status, exit code 2 if fails
  342. trap 'chkstatus_or_exit 2' EXIT HUP INT QUIT ABRT TERM
  343. # Exit immediately on any error
  344. set -e
  345. . "${CWD}/stages/${stage}/$file"
  346. # Deactivate shell option(s)
  347. set +e
  348. # Reset given signals
  349. trap - EXIT HUP INT QUIT ABRT TERM
  350. # Delete declared directories on the cleanup() function
  351. if test "$opt_keep" != opt_keep
  352. then
  353. if type cleanup 1> /dev/null 2> /dev/null
  354. then
  355. cleanup
  356. chkstatus_or_exit 2
  357. unset cleanup
  358. fi
  359. fi
  360. # Back to the current working directory
  361. cd -- "$CWD" || chkstatus_or_exit
  362. done