trees 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. #!/usr/bin/env sh
  2. # SPDX-License-Identifier: GPL-3.0-or-later
  3. # SPDX-FileCopyrightText: 2022-2023 Alper Nebi Yasak <alpernebiyasak@gmail.com>
  4. # SPDX-FileCopyrightText: 2022 Ferass El Hafidi <vitali64pmemail@protonmail.com>
  5. # SPDX-FileCopyrightText: 2023-2024 Leah Rowe <leah@libreboot.org>
  6. set -u -e
  7. . "include/err.sh"
  8. . "include/option.sh"
  9. . "include/git.sh"
  10. eval "$(setvars "" xarch cfgsdir codedir config config_name xlang mode \
  11. elfdir listfile project target target_dir targets tree _f target1 \
  12. bootstrapargs autoconfargs cmakedir makeargs autogenargs)"
  13. main()
  14. {
  15. while getopts f:b:m:u:c:x:s:l:n: option; do
  16. _f="${1}"
  17. case "${1}" in
  18. -b) : ;;
  19. -u) mode="oldconfig" ;;
  20. -m) mode="menuconfig" ;;
  21. -c) mode="distclean" ;;
  22. -x) mode="crossgcc-clean" ;;
  23. -f) mode="fetch" ;;
  24. *) err "Invalid option" ;;
  25. esac
  26. shift; project="${OPTARG#src/}"; shift
  27. done
  28. [ -z "$_f" ] && err "missing flag (-m/-u/-b/-c/-x/-f/-s/-l/-n)"
  29. [ -z "$project" ] && err "project name not specified"
  30. elfdir="elf/${project}"
  31. cfgsdir="config/${project}"
  32. remkdir "${tmpgit%/*}"
  33. check_project
  34. _cmd="build_projects"
  35. [ -f "config/${project}/build.list" ] && _cmd="build_targets"
  36. $_cmd $@
  37. }
  38. build_projects()
  39. {
  40. [ $# -gt 0 ] && x_ ./update trees $_f $@
  41. [ "$mode" = "fetch" ] && eval "fetch_project_repo; return 0;"
  42. load_project_config "$cfgsdir"
  43. codedir="src/${project}"
  44. [ -d "$codedir" ] || x_ ./update trees -f "$project"
  45. [ "$mode" = "distclean" ] && mode="clean"
  46. run_make_command || return 0
  47. }
  48. build_targets()
  49. {
  50. [ "$elfdir" = "elf/coreboot" ] && \
  51. elfdir="elf/coreboot_nopayload_DO_NOT_FLASH"
  52. [ -d "$cfgsdir" ] || err "directory, $cfgsdir, does not exist"
  53. listfile="${cfgsdir}/build.list"
  54. [ -f "$listfile" ] || err "list file, $listfile, does not exist"
  55. # Build for all targets if no argument is given
  56. [ $# -gt 0 ] && target1="$1"
  57. [ "$target1" = "utils" ] && [ "$project" = "coreboot" ] && \
  58. shift 1
  59. targets=$(items "$cfgsdir") || \
  60. err "Cannot get options for $cfgsdir"
  61. [ $# -gt 0 ] && targets=$@
  62. [ -z "$mode" ] && x_ mkdir -p "$elfdir"
  63. handle_targets
  64. }
  65. handle_targets()
  66. {
  67. for x in $targets; do
  68. target="${x}"
  69. printf "Running 'make %s' for project '%s, target '%s''\n" \
  70. "$mode" "$project" "$target"
  71. x_ handle_defconfig
  72. done
  73. [ "$target1" = "utils" ] && [ "$project" = "coreboot" ] && return 0
  74. [ -z "${mode}" ] && printf "Done! Check %s/\n\n" "$elfdir"; return 0
  75. }
  76. handle_defconfig()
  77. {
  78. handle_src_tree "$target" || return 0
  79. [ "$target1" = "utils" ] && [ "$project" = "coreboot" ] && \
  80. eval "handle_coreboot_utils \"$tree\"; return 0"
  81. for y in "${target_dir}/config"/*; do
  82. [ -f "$y" ] || continue
  83. config="$y"
  84. config_name="${config#"${target_dir}/config/"}"
  85. printf "handle/make/config %s %s: handling config %s\n" \
  86. "$project" "$target" "$config_name"
  87. [ -n "$mode" ] || check_config || continue
  88. handle_makefile
  89. [ -n "$mode" ] || copy_elf
  90. done
  91. }
  92. handle_src_tree()
  93. {
  94. target_dir="${cfgsdir}/${target}"
  95. [ "$mode" = "fetch" ] && eval "fetch_project_trees; return 1;"
  96. load_project_config "$target_dir"
  97. x_ mkdir -p "${elfdir}/${target}"
  98. [ -z "$tree" ] && err "handle_src_tree $project/$tree: tree unset"
  99. codedir="src/${project}/${tree}"
  100. if [ ! -d "$codedir" ]; then
  101. if [ "$mode" = "distclean" ] || \
  102. [ "$mode" = "crossgcc-clean" ]; then
  103. printf "Directory %s missing; skipping clean\n" \
  104. "$codedir" 1>&2
  105. return 1
  106. fi
  107. x_ ./update trees -f "$project" "$target"
  108. fi
  109. [ "$target1" = "utils" ] && [ "$project" = "coreboot" ] && return 0
  110. [ -z "$mode" ] && check_cross_compiler; return 0
  111. }
  112. load_project_config()
  113. {
  114. eval "$(setvars "" xarch xlang tree bootstrapargs autoconfargs)"
  115. [ -f "${1}/target.cfg" ] || return 0
  116. . "${1}/target.cfg" || \
  117. err "load_project_config ${1}: cannot load target.cfg"; return 0
  118. }
  119. check_cross_compiler()
  120. {
  121. for _xarch in $xarch; do
  122. cbdir="src/coreboot/${tree}"
  123. [ "$project" != "coreboot" ] && cbdir="src/coreboot/default"
  124. x_ ./update trees -f coreboot ${cbdir#src/coreboot/}
  125. export PATH="${PWD}/${cbdir}/util/crossgcc/xgcc/bin:$PATH"
  126. export CROSS_COMPILE="${xarch% *}-"
  127. [ -n "${xlang}" ] && export BUILD_LANGUAGES="$xlang"
  128. [ -d "${cbdir}/util/crossgcc/xgcc/${_xarch}/" ] && continue
  129. x_ make -C "$cbdir" crossgcc-${_xarch%-*} CPUS=$(nproc)
  130. done
  131. }
  132. check_config()
  133. {
  134. [ -f "$config" ] || err "check_config: ${project}/${target}: no config"
  135. dest_dir="${elfdir}/${target}/${config_name}"
  136. # TODO: very hacky check. do it properly (based on build.list)
  137. for elftest in "${dest_dir}"/*; do
  138. [ -f "$elftest" ] || continue
  139. printf "Build already exists, so skipping build\n" 1>&2
  140. return 1
  141. done
  142. x_ mkdir -p "$dest_dir"
  143. }
  144. handle_makefile()
  145. {
  146. x_ make clean -C "$codedir"
  147. x_ cp "$config" "${codedir}/.config"
  148. [ -n "$mode" ] || make -C "$codedir" silentoldconfig || \
  149. make -C "$codedir" oldconfig || :
  150. run_make_command || err "handle_makefile $codedir: no makefile!"
  151. if [ "$mode" = "oldconfig" ] || [ "$mode" = "menuconfig" ]; then
  152. x_ cp "${codedir}/.config" "$config"
  153. fi
  154. }
  155. run_make_command()
  156. {
  157. check_cmake "$codedir"
  158. [ -z "$mode" ] && check_autoconf "$codedir"
  159. check_makefile "$codedir" || return 1
  160. [ "$project" = "coreboot" ] && [ -z "$mode" ] && x_ \
  161. printf "%s\n" "${version%%-*}" > "$codedir/.coreboot-version"
  162. make $mode -j$(nproc) $makeargs -C "$codedir" || \
  163. err "run_make $codedir: !make $mode"
  164. [ "$mode" != "clean" ] && return 0
  165. make -C "$codedir" distclean 2>/dev/null || :
  166. }
  167. check_cmake()
  168. {
  169. [ -z "${cmakedir}" ] || \
  170. check_makefile "${1}" || \
  171. cmake -B "${1}" "${1}/${cmakedir}" || \
  172. check_makefile "${1}" || \
  173. err "check_cmake ${1}: can't cmake ${cmakedir}"
  174. [ -z "${cmakedir}" ] || check_makefile "${1}" || \
  175. err "check_cmake ${1}: could not generate Makefile"
  176. return 0
  177. }
  178. check_autoconf()
  179. {
  180. (
  181. _cfgopt=""
  182. cd "${1}" || err "!cd $1"
  183. [ -f "bootstrap" ] && x_ ./bootstrap $bootstrapargs
  184. [ -f "autogen.sh" ] && x_ ./autogen.sh ${autogenargs}
  185. [ -f "configure" ] && x_ ./configure $autoconfargs; return 0
  186. ) || err "can't bootstrap project: $1"
  187. }
  188. check_makefile()
  189. {
  190. [ -f "${1}/Makefile" ] || [ -f "${1}/makefile" ] || \
  191. [ -f "${1}/GNUmakefile" ] || return 1; return 0
  192. }
  193. copy_elf()
  194. {
  195. while read -r f; do
  196. [ ! -f "${codedir}/$f" ] || \
  197. x_ cp "${codedir}/${f}" "$dest_dir"
  198. done < "$listfile"
  199. x_ make clean -C "$codedir"
  200. }
  201. main $@