general.sh 71 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013
  1. #!/bin/bash
  2. #
  3. # Copyright (c) 2015 Igor Pecovnik, igor.pecovnik@gma**.com
  4. #
  5. # This file is licensed under the terms of the GNU General Public
  6. # License version 2. This program is licensed "as is" without any
  7. # warranty of any kind, whether express or implied.
  8. # Functions:
  9. # cleaning
  10. # exit_with_error
  11. # get_package_list_hash
  12. # create_sources_list
  13. # clean_up_git
  14. # waiter_local_git
  15. # fetch_from_repo
  16. # improved_git
  17. # display_alert
  18. # fingerprint_image
  19. # distro_menu
  20. # addtorepo
  21. # repo-remove-old-packages
  22. # wait_for_package_manager
  23. # install_pkg_deb
  24. # prepare_host_basic
  25. # prepare_host
  26. # webseed
  27. # download_and_verify
  28. # show_developer_warning
  29. # show_checklist_variables
  30. # cleaning <target>
  31. #
  32. # target: what to clean
  33. # "make" - "make clean" for selected kernel and u-boot
  34. # "debs" - delete output/debs for board&branch
  35. # "ubootdebs" - delete output/debs for uboot&board&branch
  36. # "alldebs" - delete output/debs
  37. # "cache" - delete output/cache
  38. # "oldcache" - remove old output/cache
  39. # "images" - delete output/images
  40. # "sources" - delete output/sources
  41. #
  42. cleaning()
  43. {
  44. case $1 in
  45. debs) # delete ${DEB_STORAGE} for current branch and family
  46. if [[ -d "${DEB_STORAGE}" ]]; then
  47. display_alert "Cleaning ${DEB_STORAGE} for" "$BOARD $BRANCH" "info"
  48. # easier than dealing with variable expansion and escaping dashes in file names
  49. find "${DEB_STORAGE}" -name "${CHOSEN_UBOOT}_*.deb" -delete
  50. find "${DEB_STORAGE}" \( -name "${CHOSEN_KERNEL}_*.deb" -o \
  51. -name "orangepi-*.deb" -o \
  52. -name "plymouth-theme-orangepi_*.deb" -o \
  53. -name "${CHOSEN_KERNEL/image/dtb}_*.deb" -o \
  54. -name "${CHOSEN_KERNEL/image/headers}_*.deb" -o \
  55. -name "${CHOSEN_KERNEL/image/source}_*.deb" -o \
  56. -name "${CHOSEN_KERNEL/image/firmware-image}_*.deb" \) -delete
  57. [[ -n $RELEASE ]] && rm -f "${DEB_STORAGE}/${RELEASE}/${CHOSEN_ROOTFS}"_*.deb
  58. [[ -n $RELEASE ]] && rm -f "${DEB_STORAGE}/${RELEASE}/orangepi-desktop-${RELEASE}"_*.deb
  59. fi
  60. ;;
  61. ubootdebs) # delete ${DEB_STORAGE} for uboot, current branch and family
  62. if [[ -d "${DEB_STORAGE}" ]]; then
  63. display_alert "Cleaning ${DEB_STORAGE} for u-boot" "$BOARD $BRANCH" "info"
  64. # easier than dealing with variable expansion and escaping dashes in file names
  65. find "${DEB_STORAGE}" -name "${CHOSEN_UBOOT}_*.deb" -delete
  66. fi
  67. ;;
  68. extras) # delete ${DEB_STORAGE}/extra/$RELEASE for all architectures
  69. if [[ -n $RELEASE && -d ${DEB_STORAGE}/extra/$RELEASE ]]; then
  70. display_alert "Cleaning ${DEB_STORAGE}/extra for" "$RELEASE" "info"
  71. rm -rf "${DEB_STORAGE}/extra/${RELEASE}"
  72. fi
  73. ;;
  74. alldebs) # delete output/debs
  75. [[ -d "${DEB_STORAGE}" ]] && display_alert "Cleaning" "${DEB_STORAGE}" "info" && rm -rf "${DEB_STORAGE}"/*
  76. ;;
  77. cache) # delete output/cache
  78. [[ -d $EXTER/cache/rootfs ]] && display_alert "Cleaning" "rootfs cache (all)" "info" && find $EXTER/cache/rootfs -type f -delete
  79. ;;
  80. images) # delete output/images
  81. [[ -d "${DEST}"/images ]] && display_alert "Cleaning" "output/images" "info" && rm -rf "${DEST}"/images/*
  82. ;;
  83. sources) # delete output/sources and output/buildpkg
  84. [[ -d $EXTER/cache/sources ]] && display_alert "Cleaning" "sources" "info" && rm -rf $EXTER/cache/sources/* "${DEST}"/buildpkg/*
  85. ;;
  86. oldcache) # remove old `cache/rootfs` except for the newest 8 files
  87. if [[ -d $EXTER/cache/rootfs && $(ls -1 $EXTER/cache/rootfs/*.lz4 2> /dev/null | wc -l) -gt "${ROOTFS_CACHE_MAX}" ]]; then
  88. display_alert "Cleaning" "rootfs cache (old)" "info"
  89. (cd $EXTER/cache/rootfs; ls -t *.lz4 | sed -e "1,${ROOTFS_CACHE_MAX}d" | xargs -d '\n' rm -f)
  90. # Remove signatures if they are present. We use them for internal purpose
  91. (cd $EXTER/cache/rootfs; ls -t *.asc | sed -e "1,${ROOTFS_CACHE_MAX}d" | xargs -d '\n' rm -f)
  92. fi
  93. ;;
  94. esac
  95. }
  96. # exit_with_error <message> <highlight>
  97. #
  98. # a way to terminate build process
  99. # with verbose error message
  100. #
  101. exit_with_error()
  102. {
  103. local _file
  104. local _line=${BASH_LINENO[0]}
  105. local _function=${FUNCNAME[1]}
  106. local _description=$1
  107. local _highlight=$2
  108. _file=$(basename "${BASH_SOURCE[1]}")
  109. local stacktrace="$(get_extension_hook_stracktrace "${BASH_SOURCE[*]}" "${BASH_LINENO[*]}")"
  110. display_alert "ERROR in function $_function" "$stacktrace" "err"
  111. display_alert "$_description" "$_highlight" "err"
  112. display_alert "Process terminated" "" "info"
  113. if [[ "${ERROR_DEBUG_SHELL}" == "yes" ]]; then
  114. display_alert "MOUNT" "${MOUNT}" "err"
  115. display_alert "SDCARD" "${SDCARD}" "err"
  116. display_alert "Here's a shell." "debug it" "err"
  117. bash < /dev/tty || true
  118. fi
  119. # TODO: execute run_after_build here?
  120. overlayfs_wrapper "cleanup"
  121. # unlock loop device access in case of starvation
  122. exec {FD}>/var/lock/orangepi-debootstrap-losetup
  123. flock -u "${FD}"
  124. exit 255
  125. }
  126. # get_package_list_hash
  127. #
  128. # returns md5 hash for current package list and rootfs cache version
  129. get_package_list_hash()
  130. {
  131. local package_arr exclude_arr
  132. local list_content
  133. read -ra package_arr <<< "${DEBOOTSTRAP_LIST} ${PACKAGE_LIST}"
  134. read -ra exclude_arr <<< "${PACKAGE_LIST_EXCLUDE}"
  135. ( ( printf "%s\n" "${package_arr[@]}"; printf -- "-%s\n" "${exclude_arr[@]}" ) | sort -u; echo "${1}" ) \
  136. | md5sum | cut -d' ' -f 1
  137. }
  138. # create_sources_list <release> <basedir>
  139. #
  140. # <release>: buster|bullseye|bookworm|bionic|focal|jammy|noble|hirsute|sid
  141. # <basedir>: path to root directory
  142. #
  143. create_sources_list()
  144. {
  145. local release=$1
  146. local basedir=$2
  147. [[ -z $basedir ]] && exit_with_error "No basedir passed to create_sources_list"
  148. case $release in
  149. stretch|buster)
  150. cat <<-EOF > "${basedir}"/etc/apt/sources.list
  151. deb http://${DEBIAN_MIRROR} $release main contrib non-free
  152. #deb-src http://${DEBIAN_MIRROR} $release main contrib non-free
  153. deb http://${DEBIAN_MIRROR} ${release}-updates main contrib non-free
  154. #deb-src http://${DEBIAN_MIRROR} ${release}-updates main contrib non-free
  155. deb http://${DEBIAN_MIRROR} ${release}-backports main contrib non-free
  156. #deb-src http://${DEBIAN_MIRROR} ${release}-backports main contrib non-free
  157. deb http://${DEBIAN_SECURTY} ${release}/updates main contrib non-free
  158. #deb-src http://${DEBIAN_SECURTY} ${release}/updates main contrib non-free
  159. EOF
  160. ;;
  161. bullseye)
  162. cat <<-EOF > "${basedir}"/etc/apt/sources.list
  163. deb https://${DEBIAN_MIRROR} $release main contrib non-free
  164. #deb-src https://${DEBIAN_MIRROR} $release main contrib non-free
  165. deb https://${DEBIAN_MIRROR} ${release}-updates main contrib non-free
  166. #deb-src https://${DEBIAN_MIRROR} ${release}-updates main contrib non-free
  167. deb https://${DEBIAN_MIRROR} ${release}-backports main contrib non-free
  168. #deb-src https://${DEBIAN_MIRROR} ${release}-backports main contrib non-free
  169. deb https://${DEBIAN_SECURTY} ${release}-security main contrib non-free
  170. #deb-src https://${DEBIAN_SECURTY} ${release}-security main contrib non-free
  171. EOF
  172. ;;
  173. bookworm)
  174. cat <<- EOF > "${basedir}"/etc/apt/sources.list
  175. deb http://${DEBIAN_MIRROR} $release main contrib non-free non-free-firmware
  176. #deb-src http://${DEBIAN_MIRROR} $release main contrib non-free non-free-firmware
  177. deb http://${DEBIAN_MIRROR} ${release}-updates main contrib non-free non-free-firmware
  178. #deb-src http://${DEBIAN_MIRROR} ${release}-updates main contrib non-free non-free-firmware
  179. deb http://${DEBIAN_MIRROR} ${release}-backports main contrib non-free non-free-firmware
  180. #deb-src http://${DEBIAN_MIRROR} ${release}-backports main contrib non-free non-free-firmware
  181. deb http://${DEBIAN_SECURTY} ${release}-security main contrib non-free non-free-firmware
  182. #deb-src http://${DEBIAN_SECURTY} ${release}-security main contrib non-free non-free-firmware
  183. EOF
  184. ;;
  185. sid) # sid is permanent unstable development and has no such thing as updates or security
  186. cat <<- EOF > "${basedir}"/etc/apt/sources.list
  187. deb https://snapshot.debian.org/archive/debian-ports/20221225T084846Z unstable main
  188. #deb http://${DEBIAN_MIRROR} $release main contrib non-free non-free-firmware
  189. #deb-src http://${DEBIAN_MIRROR} $release main contrib non-free non-free-firmware
  190. #deb http://${DEBIAN_MIRROR} unstable main contrib non-free non-free-firmware
  191. #deb-src http://${DEBIAN_MIRROR} unstable main contrib non-free non-free-firmware
  192. EOF
  193. ;;
  194. xenial|bionic|focal|hirsute|impish|jammy|noble)
  195. cat <<-EOF > "${basedir}"/etc/apt/sources.list
  196. deb http://${UBUNTU_MIRROR} $release main restricted universe multiverse
  197. #deb-src http://${UBUNTU_MIRROR} $release main restricted universe multiverse
  198. deb http://${UBUNTU_MIRROR} ${release}-security main restricted universe multiverse
  199. #deb-src http://${UBUNTU_MIRROR} ${release}-security main restricted universe multiverse
  200. deb http://${UBUNTU_MIRROR} ${release}-updates main restricted universe multiverse
  201. #deb-src http://${UBUNTU_MIRROR} ${release}-updates main restricted universe multiverse
  202. deb http://${UBUNTU_MIRROR} ${release}-backports main restricted universe multiverse
  203. #deb-src http://${UBUNTU_MIRROR} ${release}-backports main restricted universe multiverse
  204. EOF
  205. ;;
  206. raspi)
  207. cat <<-EOF > "${basedir}"/etc/apt/sources.list
  208. deb http://${DEBIAN_MIRROR} bullseye main contrib non-free
  209. #deb-src http://${DEBIAN_MIRROR} bullseye main contrib non-free
  210. deb http://${DEBIAN_MIRROR} bullseye-updates main contrib non-free
  211. #deb-src http://${DEBIAN_MIRROR} bullseye-updates main contrib non-free
  212. deb http://${DEBIAN_MIRROR} bullseye-backports main contrib non-free
  213. #deb-src http://${DEBIAN_MIRROR} bullseye-backports main contrib non-free
  214. deb http://${DEBIAN_SECURTY} bullseye-security main contrib non-free
  215. #deb-src http://${DEBIAN_SECURTY} bullseye-security main contrib non-free
  216. EOF
  217. cat <<-EOF > "${basedir}"/etc/apt/sources.list.d/raspi.list
  218. deb http://${RASPI_MIRROR} bullseye main
  219. # Uncomment line below then 'apt-get update' to enable 'apt-get source'
  220. #deb-src http://archive.raspberrypi.org/debian/ bullseye main
  221. EOF
  222. if [ -n "$APT_PROXY" ]; then
  223. install -m 644 files/51cache "${APT_PROXY}/etc/apt/apt.conf.d/51cache"
  224. sed "${basedir}/etc/apt/apt.conf.d/51cache" -i -e "s|APT_PROXY|${APT_PROXY}|"
  225. else
  226. rm -f "${basedir}/etc/apt/apt.conf.d/51cache"
  227. fi
  228. cat ${EXTER}/packages/raspi/stage0/00-configure-apt/files/raspberrypi.gpg.key | gpg --dearmor > "${basedir}/raspberrypi-archive-stable.gpg"
  229. install -m 644 "${basedir}/raspberrypi-archive-stable.gpg" "${basedir}/etc/apt/trusted.gpg.d/"
  230. ;;
  231. esac
  232. # stage: add armbian repository and install key
  233. #if [[ $DOWNLOAD_MIRROR == "china" ]]; then
  234. # echo "deb https://mirrors.tuna.tsinghua.edu.cn/armbian $RELEASE main ${RELEASE}-utils ${RELEASE}-desktop" > "${SDCARD}"/etc/apt/sources.list.d/armbian.list
  235. #elif [[ $DOWNLOAD_MIRROR == "bfsu" ]]; then
  236. # echo "deb http://mirrors.bfsu.edu.cn/armbian $RELEASE main ${RELEASE}-utils ${RELEASE}-desktop" > "${SDCARD}"/etc/apt/sources.list.d/armbian.list
  237. #else
  238. # echo "deb http://"$([[ $BETA == yes ]] && echo "beta" || echo "apt" )".armbian.com $RELEASE main ${RELEASE}-utils ${RELEASE}-desktop" > "${SDCARD}"/etc/apt/sources.list.d/armbian.list
  239. #fi
  240. # replace local package server if defined. Suitable for development
  241. #[[ -n $LOCAL_MIRROR ]] && echo "deb http://$LOCAL_MIRROR $RELEASE main ${RELEASE}-utils ${RELEASE}-desktop" > "${SDCARD}"/etc/apt/sources.list.d/armbian.list
  242. #display_alert "Adding Armbian repository and authentication key" "/etc/apt/sources.list.d/armbian.list" "info"
  243. #cp "${EXTER}"/config/armbian.key "${SDCARD}"
  244. #chroot "${SDCARD}" /bin/bash -c "cat armbian.key | apt-key add - > /dev/null 2>&1"
  245. #rm "${SDCARD}"/armbian.key
  246. }
  247. #
  248. # This function retries Git operations to avoid failure in case remote is borked
  249. # If the git team needs to call a remote server, use this function.
  250. #
  251. improved_git()
  252. {
  253. local realgit=$(command -v git)
  254. local retries=3
  255. local delay=10
  256. local count=1
  257. while [ $count -lt $retries ]; do
  258. $realgit "$@"
  259. if [[ $? -eq 0 || -f .git/index.lock ]]; then
  260. retries=0
  261. break
  262. fi
  263. let count=$count+1
  264. sleep $delay
  265. done
  266. }
  267. clean_up_git ()
  268. {
  269. local target_dir=$1
  270. # Files that are not tracked by git and were added
  271. # when the patch was applied must be removed.
  272. git -C $target_dir clean -qdf
  273. # Return the files that are tracked by git to the initial state.
  274. git -C $target_dir checkout -qf HEAD
  275. }
  276. # used : waiter_local_git arg1='value' arg2:'value'
  277. # waiter_local_git \
  278. # url='https://github.com/megous/linux' \
  279. # name='megous' \
  280. # dir='linux-mainline/5.14' \
  281. # branch='orange-pi-5.14' \
  282. # obj=<tag|commit> or tag:$tag ...
  283. # An optional parameter for switching to a git object such as a tag, commit,
  284. # or a specific branch. The object must exist in the local repository.
  285. # This optional parameter takes precedence. If it is specified, then
  286. # the commit state corresponding to the specified git object will be extracted
  287. # to the working directory. Otherwise, the commit corresponding to the top of
  288. # the branch will be extracted.
  289. # The settings for the kernel variables of the original kernel
  290. # VAR_SHALLOW_ORIGINAL=var_origin_kernel must be in the main script
  291. # before calling the function
  292. waiter_local_git ()
  293. {
  294. for arg in $@;do
  295. case $arg in
  296. url=*|https://*|git://*) eval "local url=${arg/url=/}"
  297. ;;
  298. dir=*|/*/*/*) eval "local dir=${arg/dir=/}"
  299. ;;
  300. *=*|*:*) eval "local ${arg/:/=}"
  301. ;;
  302. esac
  303. done
  304. # Required variables cannot be empty.
  305. for var in url name dir branch; do
  306. [ "${var#*=}" == "" ] && exit_with_error "Error in configuration"
  307. done
  308. local reachability
  309. # The 'offline' variable must always be set to 'true' or 'false'
  310. if [ "$OFFLINE_WORK" == "yes" ]; then
  311. local offline=true
  312. else
  313. local offline=false
  314. fi
  315. local work_dir="$(realpath ${EXTER}/cache/sources)/$dir"
  316. mkdir -p $work_dir
  317. cd $work_dir || exit_with_error
  318. display_alert "Checking git sources" "$dir $url$name/$branch" "info"
  319. if [ "$(git rev-parse --git-dir 2>/dev/null)" != ".git" ]; then
  320. git init -q .
  321. # Run in the sub shell to avoid mixing environment variables.
  322. if [ -n "$VAR_SHALLOW_ORIGINAL" ]; then
  323. (
  324. $VAR_SHALLOW_ORIGINAL
  325. display_alert "Add original git sources" "$dir $name/$branch" "info"
  326. if [ "$(improved_git ls-remote -h $url $branch | \
  327. awk -F'/' '{if (NR == 1) print $NF}')" != "$branch" ];then
  328. display_alert "Bad $branch for $url in $VAR_SHALLOW_ORIGINAL"
  329. exit 177
  330. fi
  331. git remote add -t $branch $name $url
  332. # Handle an exception if the initial tag is the top of the branch
  333. # As v5.16 == HEAD
  334. if [ "${start_tag}.1" == "$(improved_git ls-remote -t $url ${start_tag}.1 | \
  335. awk -F'/' '{ print $NF }')" ]
  336. then
  337. improved_git fetch --shallow-exclude=$start_tag $name
  338. else
  339. improved_git fetch --depth 1 $name
  340. fi
  341. improved_git fetch --deepen=1 $name
  342. # For a shallow clone, this works quickly and saves space.
  343. git gc
  344. )
  345. [ "$?" == "177" ] && exit
  346. fi
  347. fi
  348. files_for_clean="$(git status -s | wc -l)"
  349. if [ "$files_for_clean" != "0" ];then
  350. display_alert " Cleaning .... " "$files_for_clean files"
  351. clean_up_git $work_dir
  352. fi
  353. if [ "$name" != "$(git remote show | grep $name)" ];then
  354. git remote add -t $branch $name $url
  355. fi
  356. if ! $offline; then
  357. for t_name in $(git remote show);do
  358. improved_git fetch $t_name
  359. done
  360. fi
  361. # When switching, we use the concept of only "detached branch". Therefore,
  362. # we extract the hash from the tag, the branch name, or from the hash itself.
  363. # This serves as a check of the reachability of the extraction.
  364. # We do not use variables that characterize the current state of the git,
  365. # such as `HEAD` and `FETCH_HEAD`.
  366. reachability=false
  367. for var in obj tag commit branch;do
  368. eval pval=\$$var
  369. if [ -n "$pval" ] && [ "$pval" != *HEAD ]; then
  370. case $var in
  371. obj|tag|commit) obj=$pval ;;
  372. branch) obj=${name}/$branch ;;
  373. esac
  374. if t_hash=$(git rev-parse $obj 2>/dev/null);then
  375. reachability=true
  376. break
  377. else
  378. display_alert "Variable $var=$obj unreachable for extraction"
  379. fi
  380. fi
  381. done
  382. if $reachability && [ "$t_hash" != "$(git rev-parse @ 2>/dev/null)" ];then
  383. # Switch "detached branch" as hash
  384. display_alert "Switch $obj = $t_hash"
  385. git checkout -qf $t_hash
  386. else
  387. # the working directory corresponds to the target commit,
  388. # nothing needs to be done
  389. display_alert "Up to date"
  390. fi
  391. }
  392. # fetch_from_repo <url> <directory> <ref> <ref_subdir>
  393. # <url>: remote repository URL
  394. # <directory>: local directory; subdir for branch/tag will be created
  395. # <ref>:
  396. # branch:name
  397. # tag:name
  398. # head(*)
  399. # commit:hash
  400. #
  401. # *: Implies ref_subdir=no
  402. #
  403. # <ref_subdir>: "yes" to create subdirectory for tag or branch name
  404. #
  405. fetch_from_repo()
  406. {
  407. local url=$1
  408. local dir=$2
  409. local ref=$3
  410. local ref_subdir=$4
  411. # Set GitHub mirror before anything else touches $url
  412. url=${url//'https://github.com/'/$GITHUB_SOURCE'/'}
  413. # The 'offline' variable must always be set to 'true' or 'false'
  414. if [ "$OFFLINE_WORK" == "yes" ]; then
  415. local offline=true
  416. else
  417. local offline=false
  418. fi
  419. [[ -z $ref || ( $ref != tag:* && $ref != branch:* && $ref != head && $ref != commit:* ) ]] && exit_with_error "Error in configuration"
  420. local ref_type=${ref%%:*}
  421. if [[ $ref_type == head ]]; then
  422. local ref_name=HEAD
  423. else
  424. local ref_name=${ref##*:}
  425. fi
  426. display_alert "Checking git sources" "$dir $ref_name" "info"
  427. # get default remote branch name without cloning
  428. # local ref_name=$(git ls-remote --symref $url HEAD | grep -o 'refs/heads/\S*' | sed 's%refs/heads/%%')
  429. # for git:// protocol comparing hashes of "git ls-remote -h $url" and "git ls-remote --symref $url HEAD" is needed
  430. if [[ $ref_subdir == yes ]]; then
  431. local workdir=$dir/$ref_name
  432. else
  433. local workdir=$dir
  434. fi
  435. mkdir -p "${workdir}" 2>/dev/null || \
  436. exit_with_error "No path or no write permission" "${workdir}"
  437. cd "${workdir}" || exit
  438. # check if existing remote URL for the repo or branch does not match current one
  439. # may not be supported by older git versions
  440. # Check the folder as a git repository.
  441. # Then the target URL matches the local URL.
  442. if [[ "$(git rev-parse --git-dir 2>/dev/null)" == ".git" && \
  443. "$url" != *"$(git remote get-url origin | sed 's/^.*@//' | sed 's/^.*\/\///' 2>/dev/null)" ]]; then
  444. display_alert "Remote URL does not match, removing existing local copy"
  445. rm -rf .git ./*
  446. fi
  447. if [[ "$(git rev-parse --git-dir 2>/dev/null)" != ".git" ]]; then
  448. display_alert "Creating local copy"
  449. git init -q .
  450. git remote add origin "${url}"
  451. # Here you need to upload from a new address
  452. offline=false
  453. fi
  454. local changed=false
  455. # when we work offline we simply return the sources to their original state
  456. if ! $offline; then
  457. local local_hash
  458. local_hash=$(git rev-parse @ 2>/dev/null)
  459. case $ref_type in
  460. branch)
  461. # TODO: grep refs/heads/$name
  462. local remote_hash
  463. remote_hash=$(improved_git ls-remote -h "${url}" "$ref_name" | head -1 | cut -f1)
  464. [[ -z $local_hash || "${local_hash}" != "${remote_hash}" ]] && changed=true
  465. ;;
  466. tag)
  467. local remote_hash
  468. remote_hash=$(improved_git ls-remote -t "${url}" "$ref_name" | cut -f1)
  469. if [[ -z $local_hash || "${local_hash}" != "${remote_hash}" ]]; then
  470. remote_hash=$(improved_git ls-remote -t "${url}" "$ref_name^{}" | cut -f1)
  471. [[ -z $remote_hash || "${local_hash}" != "${remote_hash}" ]] && changed=true
  472. fi
  473. ;;
  474. head)
  475. local remote_hash
  476. remote_hash=$(improved_git ls-remote "${url}" HEAD | cut -f1)
  477. [[ -z $local_hash || "${local_hash}" != "${remote_hash}" ]] && changed=true
  478. ;;
  479. commit)
  480. [[ -z $local_hash || $local_hash == "@" ]] && changed=true
  481. ;;
  482. esac
  483. fi # offline
  484. if [[ $changed == true ]]; then
  485. # remote was updated, fetch and check out updates
  486. display_alert "Fetching updates"
  487. case $ref_type in
  488. branch) improved_git fetch --depth 200 origin "${ref_name}" ;;
  489. tag) improved_git fetch --depth 200 origin tags/"${ref_name}" ;;
  490. head) improved_git fetch --depth 200 origin HEAD ;;
  491. esac
  492. # commit type needs support for older git servers that doesn't support fetching id directly
  493. if [[ $ref_type == commit ]]; then
  494. improved_git fetch --depth 200 origin "${ref_name}"
  495. # cover old type
  496. if [[ $? -ne 0 ]]; then
  497. display_alert "Commit checkout not supported on this repository. Doing full clone." "" "wrn"
  498. improved_git pull
  499. git checkout -fq "${ref_name}"
  500. display_alert "Checkout out to" "$(git --no-pager log -2 --pretty=format:"$ad%s [%an]" | head -1)" "info"
  501. else
  502. display_alert "Checking out"
  503. git checkout -f -q FETCH_HEAD
  504. git clean -qdf
  505. fi
  506. else
  507. display_alert "Checking out"
  508. git checkout -f -q FETCH_HEAD
  509. git clean -qdf
  510. fi
  511. elif [[ -n $(git status -uno --porcelain --ignore-submodules=all) ]]; then
  512. # working directory is not clean
  513. display_alert " Cleaning .... " "$(git status -s | wc -l) files"
  514. # Return the files that are tracked by git to the initial state.
  515. git checkout -f -q HEAD
  516. # Files that are not tracked by git and were added
  517. # when the patch was applied must be removed.
  518. git clean -qdf
  519. else
  520. # working directory is clean, nothing to do
  521. display_alert "Up to date"
  522. fi
  523. if [[ -f .gitmodules ]]; then
  524. display_alert "Updating submodules" "" "ext"
  525. # FML: http://stackoverflow.com/a/17692710
  526. for i in $(git config -f .gitmodules --get-regexp path | awk '{ print $2 }'); do
  527. cd "${workdir}" || exit
  528. local surl sref
  529. surl=$(git config -f .gitmodules --get "submodule.$i.url")
  530. sref=$(git config -f .gitmodules --get "submodule.$i.branch")
  531. if [[ -n $sref ]]; then
  532. sref="branch:$sref"
  533. else
  534. sref="head"
  535. fi
  536. fetch_from_repo "$surl" "$workdir/$i" "$sref"
  537. done
  538. fi
  539. } #############################################################################
  540. #--------------------------------------------------------------------------------------------------------------------------------
  541. # Let's have unique way of displaying alerts
  542. #--------------------------------------------------------------------------------------------------------------------------------
  543. display_alert()
  544. {
  545. # log function parameters to install.log
  546. [[ -n "${DEST}" ]] && echo "Displaying message: $@" >> "${DEST}"/${LOG_SUBPATH}/output.log
  547. local tmp=""
  548. [[ -n $2 ]] && tmp="[\e[0;33m $2 \x1B[0m]"
  549. case $3 in
  550. err)
  551. echo -e "[\e[0;31m error \x1B[0m] $1 $tmp"
  552. ;;
  553. wrn)
  554. echo -e "[\e[0;35m warn \x1B[0m] $1 $tmp"
  555. ;;
  556. ext)
  557. echo -e "[\e[0;32m o.k. \x1B[0m] \e[1;32m$1\x1B[0m $tmp"
  558. ;;
  559. info)
  560. echo -e "[\e[0;32m o.k. \x1B[0m] $1 $tmp"
  561. ;;
  562. *)
  563. echo -e "[\e[0;32m .... \x1B[0m] $1 $tmp"
  564. ;;
  565. esac
  566. }
  567. #--------------------------------------------------------------------------------------------------------------------------------
  568. # fingerprint_image <out_txt_file> [image_filename]
  569. # Saving build summary to the image
  570. #--------------------------------------------------------------------------------------------------------------------------------
  571. fingerprint_image()
  572. {
  573. cat <<-EOF > "${1}"
  574. --------------------------------------------------------------------------------
  575. Title: ${VENDOR} $REVISION ${BOARD^} $DISTRIBUTION $RELEASE $BRANCH
  576. Kernel: Linux $VER
  577. Build date: $(date +'%d.%m.%Y')
  578. Maintainer: $MAINTAINER <$MAINTAINERMAIL>
  579. Sources: https://github.com/orangepi-xunlong/orangepi-build
  580. Support: http://www.orangepi.org/
  581. EOF
  582. if [ -n "$2" ]; then
  583. cat <<-EOF >> "${1}"
  584. --------------------------------------------------------------------------------
  585. Partitioning configuration: $IMAGE_PARTITION_TABLE offset: $OFFSET
  586. Boot partition type: ${BOOTFS_TYPE:-(none)} ${BOOTSIZE:+"(${BOOTSIZE} MB)"}
  587. Root partition type: $ROOTFS_TYPE ${FIXED_IMAGE_SIZE:+"(${FIXED_IMAGE_SIZE} MB)"}
  588. CPU configuration: $CPUMIN - $CPUMAX with $GOVERNOR
  589. --------------------------------------------------------------------------------
  590. Verify GPG signature:
  591. gpg --verify $2.img.asc
  592. Verify image file integrity:
  593. sha256sum --check $2.img.sha
  594. Prepare SD card (four methodes):
  595. zcat $2.img.gz | pv | dd of=/dev/sdX bs=1M
  596. dd if=$2.img of=/dev/sdX bs=1M
  597. balena-etcher $2.img.gz -d /dev/sdX
  598. balena-etcher $2.img -d /dev/sdX
  599. EOF
  600. fi
  601. cat <<-EOF >> "${1}"
  602. --------------------------------------------------------------------------------
  603. $(cat "${SRC}"/LICENSE)
  604. --------------------------------------------------------------------------------
  605. EOF
  606. }
  607. #--------------------------------------------------------------------------------------------------------------------------------
  608. # Create kernel boot logo from packages/blobs/splash/logo.png and packages/blobs/splash/spinner.gif (animated)
  609. # and place to the file /lib/firmware/bootsplash
  610. #--------------------------------------------------------------------------------------------------------------------------------
  611. function boot_logo ()
  612. {
  613. display_alert "Building kernel splash logo" "$RELEASE" "info"
  614. LOGO=${EXTER}/packages/blobs/splash/logo.png
  615. LOGO_WIDTH=$(identify $LOGO | cut -d " " -f 3 | cut -d x -f 1)
  616. LOGO_HEIGHT=$(identify $LOGO | cut -d " " -f 3 | cut -d x -f 2)
  617. THROBBER=${EXTER}/packages/blobs/splash/spinner.gif
  618. THROBBER_WIDTH=$(identify $THROBBER | head -1 | cut -d " " -f 3 | cut -d x -f 1)
  619. THROBBER_HEIGHT=$(identify $THROBBER | head -1 | cut -d " " -f 3 | cut -d x -f 2)
  620. convert -alpha remove -background "#000000" $LOGO "${SDCARD}"/tmp/logo.rgb
  621. convert -alpha remove -background "#000000" $THROBBER "${SDCARD}"/tmp/throbber%02d.rgb
  622. ${EXTER}/packages/blobs/splash/bootsplash-packer \
  623. --bg_red 0x00 \
  624. --bg_green 0x00 \
  625. --bg_blue 0x00 \
  626. --frame_ms 48 \
  627. --picture \
  628. --pic_width $LOGO_WIDTH \
  629. --pic_height $LOGO_HEIGHT \
  630. --pic_position 0 \
  631. --blob "${SDCARD}"/tmp/logo.rgb \
  632. --picture \
  633. --pic_width $THROBBER_WIDTH \
  634. --pic_height $THROBBER_HEIGHT \
  635. --pic_position 0x05 \
  636. --pic_position_offset 200 \
  637. --pic_anim_type 1 \
  638. --pic_anim_loop 0 \
  639. --blob "${SDCARD}"/tmp/throbber00.rgb \
  640. --blob "${SDCARD}"/tmp/throbber01.rgb \
  641. --blob "${SDCARD}"/tmp/throbber02.rgb \
  642. --blob "${SDCARD}"/tmp/throbber03.rgb \
  643. --blob "${SDCARD}"/tmp/throbber04.rgb \
  644. --blob "${SDCARD}"/tmp/throbber05.rgb \
  645. --blob "${SDCARD}"/tmp/throbber06.rgb \
  646. --blob "${SDCARD}"/tmp/throbber07.rgb \
  647. --blob "${SDCARD}"/tmp/throbber08.rgb \
  648. --blob "${SDCARD}"/tmp/throbber09.rgb \
  649. --blob "${SDCARD}"/tmp/throbber10.rgb \
  650. --blob "${SDCARD}"/tmp/throbber11.rgb \
  651. --blob "${SDCARD}"/tmp/throbber12.rgb \
  652. --blob "${SDCARD}"/tmp/throbber13.rgb \
  653. --blob "${SDCARD}"/tmp/throbber14.rgb \
  654. --blob "${SDCARD}"/tmp/throbber15.rgb \
  655. --blob "${SDCARD}"/tmp/throbber16.rgb \
  656. --blob "${SDCARD}"/tmp/throbber17.rgb \
  657. --blob "${SDCARD}"/tmp/throbber18.rgb \
  658. --blob "${SDCARD}"/tmp/throbber19.rgb \
  659. --blob "${SDCARD}"/tmp/throbber20.rgb \
  660. --blob "${SDCARD}"/tmp/throbber21.rgb \
  661. --blob "${SDCARD}"/tmp/throbber22.rgb \
  662. --blob "${SDCARD}"/tmp/throbber23.rgb \
  663. --blob "${SDCARD}"/tmp/throbber24.rgb \
  664. --blob "${SDCARD}"/tmp/throbber25.rgb \
  665. --blob "${SDCARD}"/tmp/throbber26.rgb \
  666. --blob "${SDCARD}"/tmp/throbber27.rgb \
  667. --blob "${SDCARD}"/tmp/throbber28.rgb \
  668. --blob "${SDCARD}"/tmp/throbber29.rgb \
  669. --blob "${SDCARD}"/tmp/throbber30.rgb \
  670. --blob "${SDCARD}"/tmp/throbber31.rgb \
  671. --blob "${SDCARD}"/tmp/throbber32.rgb \
  672. --blob "${SDCARD}"/tmp/throbber33.rgb \
  673. --blob "${SDCARD}"/tmp/throbber34.rgb \
  674. --blob "${SDCARD}"/tmp/throbber35.rgb \
  675. --blob "${SDCARD}"/tmp/throbber36.rgb \
  676. --blob "${SDCARD}"/tmp/throbber37.rgb \
  677. --blob "${SDCARD}"/tmp/throbber38.rgb \
  678. --blob "${SDCARD}"/tmp/throbber39.rgb \
  679. --blob "${SDCARD}"/tmp/throbber40.rgb \
  680. --blob "${SDCARD}"/tmp/throbber41.rgb \
  681. --blob "${SDCARD}"/tmp/throbber42.rgb \
  682. --blob "${SDCARD}"/tmp/throbber43.rgb \
  683. --blob "${SDCARD}"/tmp/throbber44.rgb \
  684. --blob "${SDCARD}"/tmp/throbber45.rgb \
  685. --blob "${SDCARD}"/tmp/throbber46.rgb \
  686. --blob "${SDCARD}"/tmp/throbber47.rgb \
  687. --blob "${SDCARD}"/tmp/throbber48.rgb \
  688. --blob "${SDCARD}"/tmp/throbber49.rgb \
  689. --blob "${SDCARD}"/tmp/throbber50.rgb \
  690. --blob "${SDCARD}"/tmp/throbber51.rgb \
  691. --blob "${SDCARD}"/tmp/throbber52.rgb \
  692. --blob "${SDCARD}"/tmp/throbber53.rgb \
  693. --blob "${SDCARD}"/tmp/throbber54.rgb \
  694. --blob "${SDCARD}"/tmp/throbber55.rgb \
  695. --blob "${SDCARD}"/tmp/throbber56.rgb \
  696. --blob "${SDCARD}"/tmp/throbber57.rgb \
  697. --blob "${SDCARD}"/tmp/throbber58.rgb \
  698. --blob "${SDCARD}"/tmp/throbber59.rgb \
  699. --blob "${SDCARD}"/tmp/throbber60.rgb \
  700. --blob "${SDCARD}"/tmp/throbber61.rgb \
  701. --blob "${SDCARD}"/tmp/throbber62.rgb \
  702. --blob "${SDCARD}"/tmp/throbber63.rgb \
  703. --blob "${SDCARD}"/tmp/throbber64.rgb \
  704. --blob "${SDCARD}"/tmp/throbber65.rgb \
  705. --blob "${SDCARD}"/tmp/throbber66.rgb \
  706. --blob "${SDCARD}"/tmp/throbber67.rgb \
  707. --blob "${SDCARD}"/tmp/throbber68.rgb \
  708. --blob "${SDCARD}"/tmp/throbber69.rgb \
  709. --blob "${SDCARD}"/tmp/throbber70.rgb \
  710. --blob "${SDCARD}"/tmp/throbber71.rgb \
  711. --blob "${SDCARD}"/tmp/throbber72.rgb \
  712. --blob "${SDCARD}"/tmp/throbber73.rgb \
  713. --blob "${SDCARD}"/tmp/throbber74.rgb \
  714. "${SDCARD}"/lib/firmware/bootsplash.orangepi >/dev/null 2>&1
  715. if [[ $BOOT_LOGO == yes || $BOOT_LOGO == desktop && $BUILD_DESKTOP == yes && $RELEASE != buster ]]; then
  716. [[ -f "${SDCARD}"/boot/orangepiEnv.txt ]] && grep -q '^bootlogo' "${SDCARD}"/boot/orangepiEnv.txt && \
  717. sed -i 's/^bootlogo.*/bootlogo=true/' "${SDCARD}"/boot/orangepiEnv.txt || echo 'bootlogo=true' >> "${SDCARD}"/boot/orangepiEnv.txt
  718. [[ -f "${SDCARD}"/boot/boot.ini ]] && sed -i 's/^setenv bootlogo.*/setenv bootlogo "true"/' "${SDCARD}"/boot/boot.ini
  719. fi
  720. # enable additional services
  721. chroot "${SDCARD}" /bin/bash -c "systemctl --no-reload enable bootsplash-ask-password-console.path >/dev/null 2>&1"
  722. chroot "${SDCARD}" /bin/bash -c "systemctl --no-reload enable bootsplash-hide-when-booted.service >/dev/null 2>&1"
  723. chroot "${SDCARD}" /bin/bash -c "systemctl --no-reload enable bootsplash-show-on-shutdown.service >/dev/null 2>&1"
  724. }
  725. DISTRIBUTIONS_DESC_DIR="external/config/distributions"
  726. function distro_menu ()
  727. {
  728. # create a select menu for choosing a distribution based EXPERT status
  729. local distrib_dir="${1}"
  730. if [[ -d "${distrib_dir}" && -f "${distrib_dir}/support" ]]; then
  731. local support_level="$(cat "${distrib_dir}/support")"
  732. if [[ "${support_level}" != "supported" && $EXPERT != "yes" ]]; then
  733. :
  734. else
  735. local distro_codename="$(basename "${distrib_dir}")"
  736. local distro_fullname="$(cat "${distrib_dir}/name")"
  737. local expert_infos=""
  738. [[ $EXPERT == "yes" ]] && expert_infos="(${support_level})"
  739. if [[ "${BRANCH}" == "legacy" ]]; then
  740. DISTRIB_TYPE="${DISTRIB_TYPE_LEGACY}"
  741. [[ -z "${DISTRIB_TYPE_LEGACY}" ]] && DISTRIB_TYPE="buster bionic focal"
  742. elif [[ "${BRANCH}" == "current" ]]; then
  743. DISTRIB_TYPE="${DISTRIB_TYPE_CURRENT}"
  744. [[ -z "${DISTRIB_TYPE_CURRENT}" ]] && DISTRIB_TYPE="bullseye bookworm focal jammy noble"
  745. elif [[ "${BRANCH}" == "next" ]]; then
  746. if [[ -n "${DISTRIB_TYPE_NEXT}" ]]; then
  747. DISTRIB_TYPE="${DISTRIB_TYPE_NEXT}"
  748. else
  749. DISTRIB_TYPE="${DISTRIB_TYPE_CURRENT}"
  750. [[ -z "${DISTRIB_TYPE_CURRENT}" ]] && DISTRIB_TYPE="bullseye bookworm focal jammy noble"
  751. fi
  752. fi
  753. if [[ "${DISTRIB_TYPE}" =~ "${distro_codename}" ]]; then
  754. options+=("${distro_codename}" "${distro_fullname} ${expert_infos}")
  755. fi
  756. fi
  757. fi
  758. }
  759. function distros_options() {
  760. for distrib_dir in "${DISTRIBUTIONS_DESC_DIR}/"*; do
  761. distro_menu "${distrib_dir}"
  762. done
  763. }
  764. function set_distribution_status() {
  765. local distro_support_desc_filepath="${SRC}/${DISTRIBUTIONS_DESC_DIR}/${RELEASE}/support"
  766. if [[ ! -f "${distro_support_desc_filepath}" ]]; then
  767. exit_with_error "Distribution ${distribution_name} does not exist"
  768. else
  769. DISTRIBUTION_STATUS="$(cat "${distro_support_desc_filepath}")"
  770. fi
  771. [[ "${DISTRIBUTION_STATUS}" != "supported" ]] && [[ "${EXPERT}" != "yes" ]] && exit_with_error "Orange Pi ${RELEASE} is unsupported and, therefore, only available to experts (EXPERT=yes)"
  772. }
  773. adding_packages()
  774. {
  775. # add deb files to repository if they are not already there
  776. display_alert "Checking and adding to repository $release" "$3" "ext"
  777. for f in "${DEB_STORAGE}${2}"/*.deb
  778. do
  779. local name version arch
  780. name=$(dpkg-deb -I "${f}" | grep Package | awk '{print $2}')
  781. version=$(dpkg-deb -I "${f}" | grep Version | awk '{print $2}')
  782. arch=$(dpkg-deb -I "${f}" | grep Architecture | awk '{print $2}')
  783. # add if not already there
  784. aptly repo search -architectures="${arch}" -config="${SCRIPTPATH}config/${REPO_CONFIG}" "${1}" 'Name (% '${name}'), $Version (='${version}'), $Architecture (='${arch}')' &>/dev/null
  785. if [[ $? -ne 0 ]]; then
  786. display_alert "Adding ${1}" "$name" "info"
  787. aptly repo add -force-replace=true -config="${SCRIPTPATH}config/${REPO_CONFIG}" "${1}" "${f}" &>/dev/null
  788. fi
  789. done
  790. }
  791. addtorepo()
  792. {
  793. # create repository
  794. # parameter "remove" dumps all and creates new
  795. # parameter "delete" remove incoming directory if publishing is succesful
  796. # function: cycle trough distributions
  797. local distributions=("stretch" "bionic" "buster" "bullseye" "bookworm" "focal" "hirsute" "jammy" "noble" "sid")
  798. #local distributions=($(grep -rw config/distributions/*/ -e 'supported' | cut -d"/" -f3))
  799. local errors=0
  800. for release in "${distributions[@]}"; do
  801. local forceoverwrite=""
  802. # let's drop from publish if exits
  803. if [[ -n $(aptly publish list -config="${SCRIPTPATH}config/${REPO_CONFIG}" -raw | awk '{print $(NF)}' | grep "${release}") ]]; then
  804. aptly publish drop -config="${SCRIPTPATH}config/${REPO_CONFIG}" "${release}" > /dev/null 2>&1
  805. fi
  806. # create local repository if not exist
  807. if [[ -z $(aptly repo list -config="${SCRIPTPATH}config/${REPO_CONFIG}" -raw | awk '{print $(NF)}' | grep "${release}") ]]; then
  808. display_alert "Creating section" "main" "info"
  809. aptly repo create -config="${SCRIPTPATH}config/${REPO_CONFIG}" -distribution="${release}" -component="main" \
  810. -comment="Armbian main repository" "${release}" >/dev/null
  811. fi
  812. if [[ -z $(aptly repo list -config="${SCRIPTPATH}config/${REPO_CONFIG}" -raw | awk '{print $(NF)}' | grep "^utils") ]]; then
  813. aptly repo create -config="${SCRIPTPATH}config/${REPO_CONFIG}" -distribution="${release}" -component="utils" \
  814. -comment="Armbian utilities (backwards compatibility)" utils >/dev/null
  815. fi
  816. if [[ -z $(aptly repo list -config="${SCRIPTPATH}config/${REPO_CONFIG}" -raw | awk '{print $(NF)}' | grep "${release}-utils") ]]; then
  817. aptly repo create -config="${SCRIPTPATH}config/${REPO_CONFIG}" -distribution="${release}" -component="${release}-utils" \
  818. -comment="Armbian ${release} utilities" "${release}-utils" >/dev/null
  819. fi
  820. if [[ -z $(aptly repo list -config="${SCRIPTPATH}config/${REPO_CONFIG}" -raw | awk '{print $(NF)}' | grep "${release}-desktop") ]]; then
  821. aptly repo create -config="${SCRIPTPATH}config/${REPO_CONFIG}" -distribution="${release}" -component="${release}-desktop" \
  822. -comment="Armbian ${release} desktop" "${release}-desktop" >/dev/null
  823. fi
  824. # adding main
  825. if find "${DEB_STORAGE}"/ -maxdepth 1 -type f -name "*.deb" 2>/dev/null | grep -q .; then
  826. adding_packages "$release" "" "main"
  827. else
  828. aptly repo add -config="${SCRIPTPATH}config/${REPO_CONFIG}" "${release}" "${SCRIPTPATH}config/templates/example.deb" >/dev/null
  829. fi
  830. local COMPONENTS="main"
  831. # adding main distribution packages
  832. if find "${DEB_STORAGE}/${release}" -maxdepth 1 -type f -name "*.deb" 2>/dev/null | grep -q .; then
  833. adding_packages "${release}-utils" "/${release}" "release packages"
  834. else
  835. # workaround - add dummy package to not trigger error
  836. aptly repo add -config="${SCRIPTPATH}config/${REPO_CONFIG}" "${release}" "${SCRIPTPATH}config/templates/example.deb" >/dev/null
  837. fi
  838. # adding release-specific utils
  839. if find "${DEB_STORAGE}/extra/${release}-utils" -maxdepth 1 -type f -name "*.deb" 2>/dev/null | grep -q .; then
  840. adding_packages "${release}-utils" "/extra/${release}-utils" "release utils"
  841. else
  842. aptly repo add -config="${SCRIPTPATH}config/${REPO_CONFIG}" "${release}-utils" "${SCRIPTPATH}config/templates/example.deb" >/dev/null
  843. fi
  844. COMPONENTS="${COMPONENTS} ${release}-utils"
  845. # adding desktop
  846. if find "${DEB_STORAGE}/extra/${release}-desktop" -maxdepth 1 -type f -name "*.deb" 2>/dev/null | grep -q .; then
  847. adding_packages "${release}-desktop" "/extra/${release}-desktop" "desktop"
  848. else
  849. # workaround - add dummy package to not trigger error
  850. aptly repo add -config="${SCRIPTPATH}config/${REPO_CONFIG}" "${release}-desktop" "${SCRIPTPATH}config/templates/example.deb" >/dev/null
  851. fi
  852. COMPONENTS="${COMPONENTS} ${release}-desktop"
  853. local mainnum utilnum desknum
  854. mainnum=$(aptly repo show -with-packages -config="${SCRIPTPATH}config/${REPO_CONFIG}" "${release}" | grep "Number of packages" | awk '{print $NF}')
  855. utilnum=$(aptly repo show -with-packages -config="${SCRIPTPATH}config/${REPO_CONFIG}" "${release}-desktop" | grep "Number of packages" | awk '{print $NF}')
  856. desknum=$(aptly repo show -with-packages -config="${SCRIPTPATH}config/${REPO_CONFIG}" "${release}-utils" | grep "Number of packages" | awk '{print $NF}')
  857. if [ $mainnum -gt 0 ] && [ $utilnum -gt 0 ] && [ $desknum -gt 0 ]; then
  858. # publish
  859. aptly publish \
  860. -acquire-by-hash \
  861. -passphrase="${GPG_PASS}" \
  862. -origin="Armbian" \
  863. -label="Armbian" \
  864. -config="${SCRIPTPATH}config/${REPO_CONFIG}" \
  865. -component="${COMPONENTS// /,}" \
  866. -distribution="${release}" repo "${release}" ${COMPONENTS//main/} >/dev/null
  867. if [[ $? -ne 0 ]]; then
  868. display_alert "Publishing failed" "${release}" "err"
  869. errors=$((errors+1))
  870. exit 0
  871. fi
  872. else
  873. errors=$((errors+1))
  874. local err_txt=": All components must be present: main, utils and desktop for first build"
  875. fi
  876. done
  877. # cleanup
  878. display_alert "Cleaning repository" "${DEB_STORAGE}" "info"
  879. aptly db cleanup -config="${SCRIPTPATH}config/${REPO_CONFIG}"
  880. # display what we have
  881. echo ""
  882. display_alert "List of local repos" "local" "info"
  883. (aptly repo list -config="${SCRIPTPATH}config/${REPO_CONFIG}") | grep -E packages
  884. # remove debs if no errors found
  885. if [[ $errors -eq 0 ]]; then
  886. if [[ "$2" == "delete" ]]; then
  887. display_alert "Purging incoming debs" "all" "ext"
  888. find "${DEB_STORAGE}" -name "*.deb" -type f -delete
  889. fi
  890. else
  891. display_alert "There were some problems $err_txt" "leaving incoming directory intact" "err"
  892. fi
  893. }
  894. repo-manipulate()
  895. {
  896. # repository manipulation
  897. # "show" displays packages in each repository
  898. # "server" serve repository - useful for local diagnostics
  899. # "unique" manually select which package should be removed from all repositories
  900. # "update" search for new files in output/debs* to add them to repository
  901. # "purge" leave only last 5 versions
  902. local DISTROS=("stretch" "bionic" "buster" "bullseye" "bookworm" "focal" "hirsute" "jammy" "noble" "sid")
  903. #local DISTROS=($(grep -rw config/distributions/*/ -e 'supported' | cut -d"/" -f3))
  904. case $@ in
  905. serve)
  906. # display repository content
  907. display_alert "Serving content" "common utils" "ext"
  908. aptly serve -listen=$(ip -f inet addr | grep -Po 'inet \K[\d.]+' | grep -v 127.0.0.1 | head -1):80 -config="${SCRIPTPATH}config/${REPO_CONFIG}"
  909. exit 0
  910. ;;
  911. show)
  912. # display repository content
  913. for release in "${DISTROS[@]}"; do
  914. display_alert "Displaying repository contents for" "$release" "ext"
  915. aptly repo show -with-packages -config="${SCRIPTPATH}config/${REPO_CONFIG}" "${release}" | tail -n +7
  916. aptly repo show -with-packages -config="${SCRIPTPATH}config/${REPO_CONFIG}" "${release}-desktop" | tail -n +7
  917. done
  918. display_alert "Displaying repository contents for" "common utils" "ext"
  919. aptly repo show -with-packages -config="${SCRIPTPATH}config/${REPO_CONFIG}" utils | tail -n +7
  920. echo "done."
  921. exit 0
  922. ;;
  923. unique)
  924. # which package should be removed from all repositories
  925. IFS=$'\n'
  926. while true; do
  927. LIST=()
  928. for release in "${DISTROS[@]}"; do
  929. LIST+=( $(aptly repo show -with-packages -config="${SCRIPTPATH}config/${REPO_CONFIG}" "${release}" | tail -n +7) )
  930. LIST+=( $(aptly repo show -with-packages -config="${SCRIPTPATH}config/${REPO_CONFIG}" "${release}-desktop" | tail -n +7) )
  931. done
  932. LIST+=( $(aptly repo show -with-packages -config="${SCRIPTPATH}config/${REPO_CONFIG}" utils | tail -n +7) )
  933. LIST=( $(echo "${LIST[@]}" | tr ' ' '\n' | sort -u))
  934. new_list=()
  935. # create a human readable menu
  936. for ((n=0;n<$((${#LIST[@]}));n++));
  937. do
  938. new_list+=( "${LIST[$n]}" )
  939. new_list+=( "" )
  940. done
  941. LIST=("${new_list[@]}")
  942. LIST_LENGTH=$((${#LIST[@]}/2));
  943. exec 3>&1
  944. TARGET_VERSION=$(dialog --cancel-label "Cancel" --backtitle "BACKTITLE" --no-collapse --title "Remove packages from repositories" --clear --menu "Delete" $((9+${LIST_LENGTH})) 82 65 "${LIST[@]}" 2>&1 1>&3)
  945. exitstatus=$?;
  946. exec 3>&-
  947. if [[ $exitstatus -eq 0 ]]; then
  948. for release in "${DISTROS[@]}"; do
  949. aptly repo remove -config="${SCRIPTPATH}config/${REPO_CONFIG}" "${release}" "$TARGET_VERSION"
  950. aptly repo remove -config="${SCRIPTPATH}config/${REPO_CONFIG}" "${release}-desktop" "$TARGET_VERSION"
  951. done
  952. aptly repo remove -config="${SCRIPTPATH}config/${REPO_CONFIG}" "utils" "$TARGET_VERSION"
  953. else
  954. exit 1
  955. fi
  956. aptly db cleanup -config="${SCRIPTPATH}config/${REPO_CONFIG}" > /dev/null 2>&1
  957. done
  958. ;;
  959. update)
  960. # display full help test
  961. # run repository update
  962. addtorepo "update" ""
  963. # add a key to repo
  964. cp "${SCRIPTPATH}"config/armbian.key "${REPO_STORAGE}"/public/
  965. exit 0
  966. ;;
  967. purge)
  968. for release in "${DISTROS[@]}"; do
  969. repo-remove-old-packages "$release" "armhf" "5"
  970. repo-remove-old-packages "$release" "arm64" "5"
  971. repo-remove-old-packages "$release" "amd64" "5"
  972. repo-remove-old-packages "$release" "all" "5"
  973. aptly -config="${SCRIPTPATH}config/${REPO_CONFIG}" -passphrase="${GPG_PASS}" publish update "${release}" > /dev/null 2>&1
  974. done
  975. exit 0
  976. ;;
  977. purgeedge)
  978. for release in "${DISTROS[@]}"; do
  979. repo-remove-old-packages "$release" "armhf" "3" "edge"
  980. repo-remove-old-packages "$release" "arm64" "3" "edge"
  981. repo-remove-old-packages "$release" "amd64" "3" "edge"
  982. repo-remove-old-packages "$release" "all" "3" "edge"
  983. aptly -config="${SCRIPTPATH}config/${REPO_CONFIG}" -passphrase="${GPG_PASS}" publish update "${release}" > /dev/null 2>&1
  984. done
  985. exit 0
  986. ;;
  987. purgesource)
  988. for release in "${DISTROS[@]}"; do
  989. aptly repo remove -config="${SCRIPTPATH}config/${REPO_CONFIG}" "${release}" 'Name (% *-source*)'
  990. aptly -config="${SCRIPTPATH}config/${REPO_CONFIG}" -passphrase="${GPG_PASS}" publish update "${release}" > /dev/null 2>&1
  991. done
  992. aptly db cleanup -config="${SCRIPTPATH}config/${REPO_CONFIG}" > /dev/null 2>&1
  993. exit 0
  994. ;;
  995. *)
  996. echo -e "Usage: repository show | serve | unique | create | update | purge | purgesource\n"
  997. echo -e "\n show = display repository content"
  998. echo -e "\n serve = publish your repositories on current server over HTTP"
  999. echo -e "\n unique = manually select which package should be removed from all repositories"
  1000. echo -e "\n update = updating repository"
  1001. echo -e "\n purge = removes all but last 5 versions"
  1002. echo -e "\n purgeedge = removes all but last 3 edge versions"
  1003. echo -e "\n purgesource = removes all sources\n\n"
  1004. exit 0
  1005. ;;
  1006. esac
  1007. }
  1008. # Removes old packages in the received repo
  1009. #
  1010. # $1: Repository
  1011. # $2: Architecture
  1012. # $3: Amount of packages to keep
  1013. # $4: Additional search pattern
  1014. repo-remove-old-packages() {
  1015. local repo=$1
  1016. local arch=$2
  1017. local keep=$3
  1018. for pkg in $(aptly repo search -config="${SCRIPTPATH}config/${REPO_CONFIG}" "${repo}" "Architecture ($arch)" | grep -v "ERROR: no results" | sort -t '.' -nk4 | grep -e "$4"); do
  1019. local pkg_name
  1020. count=0
  1021. pkg_name=$(echo "${pkg}" | cut -d_ -f1)
  1022. for subpkg in $(aptly repo search -config="${SCRIPTPATH}config/${REPO_CONFIG}" "${repo}" "Name ($pkg_name)" | grep -v "ERROR: no results" | sort -rt '.' -nk4); do
  1023. ((count+=1))
  1024. if [[ $count -gt $keep ]]; then
  1025. pkg_version=$(echo "${subpkg}" | cut -d_ -f2)
  1026. aptly repo remove -config="${SCRIPTPATH}config/${REPO_CONFIG}" "${repo}" "Name ($pkg_name), Version (= $pkg_version)"
  1027. fi
  1028. done
  1029. done
  1030. }
  1031. # wait_for_package_manager
  1032. #
  1033. # * installation will break if we try to install when package manager is running
  1034. #
  1035. wait_for_package_manager()
  1036. {
  1037. # exit if package manager is running in the back
  1038. while true; do
  1039. if [[ "$(fuser /var/lib/dpkg/lock 2>/dev/null; echo $?)" != 1 && "$(fuser /var/lib/dpkg/lock-frontend 2>/dev/null; echo $?)" != 1 ]]; then
  1040. display_alert "Package manager is running in the background." "Please wait! Retrying in 30 sec" "wrn"
  1041. sleep 30
  1042. else
  1043. break
  1044. fi
  1045. done
  1046. }
  1047. # Installing debian packages in the orangepi build system.
  1048. # The function accepts four optional parameters:
  1049. # autoupdate - If the installation list is not empty then update first.
  1050. # upgrade, clean - the same name for apt
  1051. # verbose - detailed log for the function
  1052. #
  1053. # list="pkg1 pkg2 pkg3 pkgbadname pkg-1.0 | pkg-2.0 pkg5 (>= 9)"
  1054. # install_pkg_deb upgrade verbose $list
  1055. # or
  1056. # install_pkg_deb autoupdate $list
  1057. #
  1058. # If the package has a bad name, we will see it in the log file.
  1059. # If there is an LOG_OUTPUT_FILE variable and it has a value as
  1060. # the full real path to the log file, then all the information will be there.
  1061. #
  1062. # The LOG_OUTPUT_FILE variable must be defined in the calling function
  1063. # before calling the install_pkg_deb function and unset after.
  1064. #
  1065. install_pkg_deb ()
  1066. {
  1067. local list=""
  1068. local log_file
  1069. local for_install
  1070. local need_autoup=false
  1071. local need_upgrade=false
  1072. local need_clean=false
  1073. local need_verbose=false
  1074. local _line=${BASH_LINENO[0]}
  1075. local _function=${FUNCNAME[1]}
  1076. local _file=$(basename "${BASH_SOURCE[1]}")
  1077. local tmp_file=$(mktemp /tmp/install_log_XXXXX)
  1078. export DEBIAN_FRONTEND=noninteractive
  1079. list=$(
  1080. for p in $*;do
  1081. case $p in
  1082. autoupdate) need_autoup=true; continue ;;
  1083. upgrade) need_upgrade=true; continue ;;
  1084. clean) need_clean=true; continue ;;
  1085. verbose) need_verbose=true; continue ;;
  1086. \||\(*|*\)) continue ;;
  1087. esac
  1088. echo " $p"
  1089. done
  1090. )
  1091. if [ -d $(dirname $LOG_OUTPUT_FILE) ]; then
  1092. log_file=${LOG_OUTPUT_FILE}
  1093. else
  1094. log_file="${SRC}/output/${LOG_SUBPATH}/install.log"
  1095. fi
  1096. # This is necessary first when there is no apt cache.
  1097. if $need_upgrade; then
  1098. apt-get -q update || echo "apt cannot update" >>$tmp_file
  1099. apt-get -y upgrade || echo "apt cannot upgrade" >>$tmp_file
  1100. fi
  1101. # If the package is not installed, check the latest
  1102. # up-to-date version in the apt cache.
  1103. # Exclude bad package names and send a message to the log.
  1104. for_install=$(
  1105. for p in $list;do
  1106. if $(dpkg-query -W -f '${db:Status-Abbrev}' $p |& awk '/ii/{exit 1}');then
  1107. apt-cache show $p -o APT::Cache::AllVersions=no |& \
  1108. awk -v p=$p -v tmp_file=$tmp_file \
  1109. '/^Package:/{print $2} /^E:/{print "Bad package name: ",p >>tmp_file}'
  1110. fi
  1111. done
  1112. )
  1113. # This information should be logged.
  1114. if [ -s $tmp_file ]; then
  1115. echo -e "\nInstalling packages in function: $_function" "[$_file:$_line]" \
  1116. >>$log_file
  1117. echo -e "\nIncoming list:" >>$log_file
  1118. printf "%-30s %-30s %-30s %-30s\n" $list >>$log_file
  1119. echo "" >>$log_file
  1120. cat $tmp_file >>$log_file
  1121. fi
  1122. if [ -n "$for_install" ]; then
  1123. if $need_autoup; then
  1124. apt-get -q update
  1125. apt-get -y upgrade
  1126. fi
  1127. apt-get install -qq -y --no-install-recommends $for_install
  1128. echo -e "\nPackages installed:" >>$log_file
  1129. dpkg-query -W \
  1130. -f '${binary:Package;-27} ${Version;-23}\n' \
  1131. $for_install >>$log_file
  1132. fi
  1133. # We will show the status after installation all listed
  1134. if $need_verbose; then
  1135. echo -e "\nstatus after installation:" >>$log_file
  1136. dpkg-query -W \
  1137. -f '${binary:Package;-27} ${Version;-23} [ ${Status} ]\n' \
  1138. $list >>$log_file
  1139. fi
  1140. if $need_clean;then apt-get clean; fi
  1141. rm $tmp_file
  1142. }
  1143. # prepare_host_basic
  1144. #
  1145. # * installs only basic packages
  1146. #
  1147. prepare_host_basic()
  1148. {
  1149. # command:package1 package2 ...
  1150. # list of commands that are neeeded:packages where this command is
  1151. local check_pack install_pack
  1152. local checklist=(
  1153. "whiptail:whiptail"
  1154. "dialog:dialog"
  1155. "fuser:psmisc"
  1156. "getfacl:acl"
  1157. "uuid:uuid uuid-runtime"
  1158. "curl:curl"
  1159. "gpg:gnupg"
  1160. "gawk:gawk"
  1161. "git:git"
  1162. )
  1163. for check_pack in "${checklist[@]}"; do
  1164. if ! which ${check_pack%:*} >/dev/null; then local install_pack+=${check_pack#*:}" "; fi
  1165. done
  1166. if [[ -n $install_pack ]]; then
  1167. display_alert "Installing basic packages" "$install_pack"
  1168. sudo bash -c "apt-get -qq update && apt-get install -qq -y --no-install-recommends $install_pack"
  1169. fi
  1170. }
  1171. # prepare_host
  1172. #
  1173. # * checks and installs necessary packages
  1174. # * creates directory structure
  1175. # * changes system settings
  1176. #
  1177. prepare_host()
  1178. {
  1179. display_alert "Preparing" "host" "info"
  1180. # The 'offline' variable must always be set to 'true' or 'false'
  1181. if [ "$OFFLINE_WORK" == "yes" ]; then
  1182. local offline=true
  1183. else
  1184. local offline=false
  1185. fi
  1186. # wait until package manager finishes possible system maintanace
  1187. wait_for_package_manager
  1188. # fix for Locales settings
  1189. if ! grep -q "^en_US.UTF-8 UTF-8" /etc/locale.gen; then
  1190. sudo sed -i 's/# en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen
  1191. sudo locale-gen
  1192. fi
  1193. export LC_ALL="en_US.UTF-8"
  1194. # packages list for host
  1195. # NOTE: please sync any changes here with the Dockerfile and Vagrantfile
  1196. local hostdeps="acl aptly aria2 bc binfmt-support bison btrfs-progs \
  1197. build-essential ca-certificates ccache cpio cryptsetup curl \
  1198. debian-archive-keyring debian-keyring debootstrap device-tree-compiler \
  1199. dialog dirmngr dosfstools dwarves f2fs-tools fakeroot flex gawk \
  1200. gcc-arm-linux-gnueabihf gdisk gpg imagemagick jq kmod libbison-dev \
  1201. libc6-dev-armhf-cross libelf-dev libfdt-dev libfile-fcntllock-perl \
  1202. libfl-dev liblz4-tool libncurses-dev libpython2.7-dev libssl-dev \
  1203. libusb-1.0-0-dev linux-base locales lzop ncurses-base ncurses-term \
  1204. nfs-kernel-server ntpdate p7zip-full parted patchutils pigz pixz \
  1205. pkg-config pv python3-dev python3-distutils qemu-user-static rsync swig \
  1206. systemd-container u-boot-tools udev unzip uuid-dev wget whiptail zip \
  1207. zlib1g-dev gcc-riscv64-linux-gnu"
  1208. if [[ $(dpkg --print-architecture) == amd64 ]]; then
  1209. hostdeps+=" distcc lib32ncurses-dev lib32stdc++6 libc6-i386"
  1210. grep -q i386 <(dpkg --print-foreign-architectures) || dpkg --add-architecture i386
  1211. elif [[ $(dpkg --print-architecture) == arm64 ]]; then
  1212. hostdeps+=" gcc-arm-linux-gnueabi gcc-arm-none-eabi libc6 libc6-amd64-cross qemu"
  1213. else
  1214. display_alert "Please read documentation to set up proper compilation environment"
  1215. display_alert "https://www.armbian.com/using-armbian-tools/"
  1216. exit_with_error "Running this tool on non x86_64 build host is not supported"
  1217. fi
  1218. # Add support for Ubuntu 20.04, 21.04 and Mint 20.x
  1219. if [[ $HOSTRELEASE =~ ^(focal|hirsute|jammy|noble|noble|ulyana|ulyssa|bullseye|bookworm|uma)$ ]]; then
  1220. hostdeps+=" python2 python3"
  1221. ln -fs /usr/bin/python2.7 /usr/bin/python2
  1222. ln -fs /usr/bin/python2.7 /usr/bin/python
  1223. else
  1224. hostdeps+=" python libpython-dev"
  1225. fi
  1226. display_alert "Build host OS release" "${HOSTRELEASE:-(unknown)}" "info"
  1227. # Ubuntu 21.04.x (Hirsute) x86_64 is the only fully supported host OS release
  1228. # Using Docker/VirtualBox/Vagrant is the only supported way to run the build script on other Linux distributions
  1229. #
  1230. # NO_HOST_RELEASE_CHECK overrides the check for a supported host system
  1231. # Disable host OS check at your own risk. Any issues reported with unsupported releases will be closed without discussion
  1232. if [[ -z $HOSTRELEASE || "focal jammy noble" != *"$HOSTRELEASE"* ]]; then
  1233. if [[ $NO_HOST_RELEASE_CHECK == yes ]]; then
  1234. display_alert "You are running on an unsupported system" "${HOSTRELEASE:-(unknown)}" "wrn"
  1235. display_alert "Do not report any errors, warnings or other issues encountered beyond this point" "" "wrn"
  1236. else
  1237. exit_with_error "It seems you ignore documentation and run an unsupported build system: ${HOSTRELEASE:-(unknown)}"
  1238. fi
  1239. fi
  1240. if grep -qE "(Microsoft|WSL)" /proc/version; then
  1241. if [ -f /.dockerenv ]; then
  1242. display_alert "Building images using Docker on WSL2 may fail" "" "wrn"
  1243. else
  1244. exit_with_error "Windows subsystem for Linux is not a supported build environment"
  1245. fi
  1246. fi
  1247. if systemd-detect-virt -q -c; then
  1248. display_alert "Running in container" "$(systemd-detect-virt)" "info"
  1249. # disable apt-cacher unless NO_APT_CACHER=no is not specified explicitly
  1250. if [[ $NO_APT_CACHER != no ]]; then
  1251. display_alert "apt-cacher is disabled in containers, set NO_APT_CACHER=no to override" "" "wrn"
  1252. NO_APT_CACHER=yes
  1253. fi
  1254. CONTAINER_COMPAT=yes
  1255. # trying to use nested containers is not a good idea, so don't permit EXTERNAL_NEW=compile
  1256. if [[ $EXTERNAL_NEW == compile ]]; then
  1257. display_alert "EXTERNAL_NEW=compile is not available when running in container, setting to prebuilt" "" "wrn"
  1258. EXTERNAL_NEW=prebuilt
  1259. fi
  1260. SYNC_CLOCK=no
  1261. fi
  1262. # Skip verification if you are working offline
  1263. if ! $offline; then
  1264. # warning: apt-cacher-ng will fail if installed and used both on host and in
  1265. # container/chroot environment with shared network
  1266. # set NO_APT_CACHER=yes to prevent installation errors in such case
  1267. if [[ $NO_APT_CACHER != yes ]]; then hostdeps+=" apt-cacher-ng"; fi
  1268. export EXTRA_BUILD_DEPS=""
  1269. call_extension_method "add_host_dependencies" <<- 'ADD_HOST_DEPENDENCIES'
  1270. *run before installing host dependencies*
  1271. you can add packages to install, space separated, to ${EXTRA_BUILD_DEPS} here.
  1272. ADD_HOST_DEPENDENCIES
  1273. if [ -n "${EXTRA_BUILD_DEPS}" ]; then hostdeps+=" ${EXTRA_BUILD_DEPS}"; fi
  1274. display_alert "Installing build dependencies"
  1275. # don't prompt for apt cacher selection
  1276. sudo echo "apt-cacher-ng apt-cacher-ng/tunnelenable boolean false" | sudo debconf-set-selections
  1277. LOG_OUTPUT_FILE="${DEST}"/${LOG_SUBPATH}/hostdeps.log
  1278. install_pkg_deb "autoupdate $hostdeps"
  1279. unset LOG_OUTPUT_FILE
  1280. update-ccache-symlinks
  1281. export FINAL_HOST_DEPS="$hostdeps ${EXTRA_BUILD_DEPS}"
  1282. call_extension_method "host_dependencies_ready" <<- 'HOST_DEPENDENCIES_READY'
  1283. *run after all host dependencies are installed*
  1284. At this point we can read `${FINAL_HOST_DEPS}`, but changing won't have any effect.
  1285. All the dependencies, including the default/core deps and the ones added via `${EXTRA_BUILD_DEPS}`
  1286. are installed at this point. The system clock has not yet been synced.
  1287. HOST_DEPENDENCIES_READY
  1288. # sync clock
  1289. if [[ $SYNC_CLOCK != no ]]; then
  1290. display_alert "Syncing clock" "${NTP_SERVER:-pool.ntp.org}" "info"
  1291. ntpdate -s "${NTP_SERVER:-pool.ntp.org}"
  1292. fi
  1293. # create directory structure
  1294. mkdir -p $SRC/output $EXTER/cache $USERPATCHES_PATH
  1295. if [[ -n $SUDO_USER ]]; then
  1296. chgrp --quiet sudo cache output "${USERPATCHES_PATH}"
  1297. # SGID bit on cache/sources breaks kernel dpkg packaging
  1298. chmod --quiet g+w,g+s output "${USERPATCHES_PATH}"
  1299. # fix existing permissions
  1300. find "${SRC}"/output "${USERPATCHES_PATH}" -type d ! -group sudo -exec chgrp --quiet sudo {} \;
  1301. find "${SRC}"/output "${USERPATCHES_PATH}" -type d ! -perm -g+w,g+s -exec chmod --quiet g+w,g+s {} \;
  1302. fi
  1303. mkdir -p $DEST/debs/{extra,u-boot} $DEST/{config,debug,patch,images} $USERPATCHES_PATH/overlay $EXTER/cache/{debs,sources,hash} $SRC/toolchains $SRC/.tmp
  1304. # build aarch64
  1305. if [[ $(dpkg --print-architecture) == amd64 ]]; then
  1306. if [[ "${SKIP_EXTERNAL_TOOLCHAINS}" != "yes" ]]; then
  1307. # bind mount toolchain if defined
  1308. if [[ -d "${ARMBIAN_CACHE_TOOLCHAIN_PATH}" ]]; then
  1309. mountpoint -q "${SRC}"/cache/toolchain && umount -l "${SRC}"/cache/toolchain
  1310. mount --bind "${ARMBIAN_CACHE_TOOLCHAIN_PATH}" "${SRC}"/cache/toolchain
  1311. fi
  1312. display_alert "Checking for external GCC compilers" "" "info"
  1313. # download external Linaro compiler and missing special dependencies since they are needed for certain sources
  1314. local toolchains=(
  1315. "ky-toolchain-linux-glibc-x86_64-v1.0.1.tar.xz"
  1316. "gcc-linaro-aarch64-none-elf-4.8-2013.11_linux.tar.xz"
  1317. "gcc-linaro-arm-none-eabi-4.8-2014.04_linux.tar.xz"
  1318. "gcc-linaro-arm-linux-gnueabihf-4.8-2014.04_linux.tar.xz"
  1319. "gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabi.tar.xz"
  1320. "gcc-linaro-4.9.4-2017.01-x86_64_aarch64-linux-gnu.tar.xz"
  1321. "gcc-linaro-5.5.0-2017.10-x86_64_arm-linux-gnueabihf.tar.xz"
  1322. "gcc-linaro-7.4.1-2019.02-x86_64_arm-linux-gnueabi.tar.xz"
  1323. "gcc-linaro-7.4.1-2019.02-x86_64_aarch64-linux-gnu.tar.xz"
  1324. "gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf.tar.xz"
  1325. "gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu.tar.xz"
  1326. "gcc-arm-11.2-2022.02-x86_64-arm-none-linux-gnueabihf.tar.xz"
  1327. "gcc-arm-11.2-2022.02-x86_64-aarch64-none-linux-gnu.tar.xz"
  1328. )
  1329. USE_TORRENT_STATUS=${USE_TORRENT}
  1330. USE_TORRENT="no"
  1331. for toolchain in ${toolchains[@]}; do
  1332. download_and_verify "_toolchain" "${toolchain##*/}"
  1333. done
  1334. USE_TORRENT=${USE_TORRENT_STATUS}
  1335. rm -rf $SRC/toolchains/*.tar.xz*
  1336. local existing_dirs=( $(ls -1 $SRC/toolchains) )
  1337. for dir in ${existing_dirs[@]}; do
  1338. local found=no
  1339. for toolchain in ${toolchains[@]}; do
  1340. local filename=${toolchain##*/}
  1341. local dirname=${filename//.tar.xz}
  1342. [[ $dir == $dirname ]] && found=yes
  1343. done
  1344. if [[ $found == no ]]; then
  1345. display_alert "Removing obsolete toolchain" "$dir"
  1346. rm -rf $SRC/toolchains/$dir
  1347. fi
  1348. done
  1349. else
  1350. display_alert "Ignoring toolchains" "SKIP_EXTERNAL_TOOLCHAINS: ${SKIP_EXTERNAL_TOOLCHAINS}" "info"
  1351. fi
  1352. fi
  1353. fi # check offline
  1354. # enable arm binary format so that the cross-architecture chroot environment will work
  1355. if [[ $BUILD_OPT == "image" || $BUILD_OPT == "rootfs" ]]; then
  1356. modprobe -q binfmt_misc
  1357. mountpoint -q /proc/sys/fs/binfmt_misc/ || mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
  1358. if [[ "$(arch)" != "aarch64" ]]; then
  1359. test -e /proc/sys/fs/binfmt_misc/qemu-arm || update-binfmts --enable qemu-arm
  1360. test -e /proc/sys/fs/binfmt_misc/qemu-aarch64 || update-binfmts --enable qemu-aarch64
  1361. fi
  1362. fi
  1363. [[ ! -f "${USERPATCHES_PATH}"/customize-image.sh ]] && cp "${EXTER}"/config/templates/customize-image.sh.template "${USERPATCHES_PATH}"/customize-image.sh
  1364. if [[ ! -f "${USERPATCHES_PATH}"/README ]]; then
  1365. rm -f "${USERPATCHES_PATH}"/readme.txt
  1366. echo 'Please read documentation about customizing build configuration' > "${USERPATCHES_PATH}"/README
  1367. echo 'https:/www.orangepi.org' >> "${USERPATCHES_PATH}"/README
  1368. # create patches directory structure under USERPATCHES_PATH
  1369. find $EXTER/patch -maxdepth 2 -type d ! -name . | sed "s%/.*patch%/$USERPATCHES_PATH%" | xargs mkdir -p
  1370. fi
  1371. # check free space (basic)
  1372. local freespace=$(findmnt --target "${SRC}" -n -o AVAIL -b 2>/dev/null) # in bytes
  1373. if [[ -n $freespace && $(( $freespace / 1073741824 )) -lt 10 ]]; then
  1374. display_alert "Low free space left" "$(( $freespace / 1073741824 )) GiB" "wrn"
  1375. # pause here since dialog-based menu will hide this message otherwise
  1376. echo -e "Press \e[0;33m<Ctrl-C>\x1B[0m to abort compilation, \e[0;33m<Enter>\x1B[0m to ignore and continue"
  1377. read
  1378. fi
  1379. }
  1380. function webseed ()
  1381. {
  1382. # list of mirrors that host our files
  1383. unset text
  1384. # Hardcoded to EU mirrors since
  1385. local CCODE=$(curl -s redirect.armbian.com/geoip | jq '.continent.code' -r)
  1386. WEBSEED=($(curl -s https://redirect.armbian.com/mirrors | jq -r '.'${CCODE}' | .[] | values'))
  1387. # aria2 simply split chunks based on sources count not depending on download speed
  1388. # when selecting china mirrors, use only China mirror, others are very slow there
  1389. if [[ $DOWNLOAD_MIRROR == china ]]; then
  1390. WEBSEED=(
  1391. https://mirrors.tuna.tsinghua.edu.cn/armbian-releases/
  1392. )
  1393. elif [[ $DOWNLOAD_MIRROR == bfsu ]]; then
  1394. WEBSEED=(
  1395. https://mirrors.bfsu.edu.cn/armbian-releases/
  1396. )
  1397. fi
  1398. for toolchain in ${WEBSEED[@]}; do
  1399. text="${text} ${toolchain}${1}"
  1400. done
  1401. text="${text:1}"
  1402. echo "${text}"
  1403. }
  1404. download_and_verify()
  1405. {
  1406. local remotedir=$1
  1407. local filename=$2
  1408. local localdir=$SRC/toolchains
  1409. local dirname=${filename//.tar.xz}
  1410. if [[ $DOWNLOAD_MIRROR == china ]]; then
  1411. local server="https://mirrors.tuna.tsinghua.edu.cn/armbian-releases/"
  1412. elif [[ $DOWNLOAD_MIRROR == bfsu ]]; then
  1413. local server="https://mirrors.bfsu.edu.cn/armbian-releases/"
  1414. else
  1415. local server=${ARMBIAN_MIRROR}
  1416. fi
  1417. if [[ -f ${localdir}/${dirname}/.download-complete ]]; then
  1418. return
  1419. fi
  1420. if [[ ${filename} == *ky* ]]; then
  1421. server="http://www.iplaystore.cn/"
  1422. remotedir=""
  1423. fi
  1424. # switch to china mirror if US timeouts
  1425. timeout 10 curl --head --fail --silent ${server}${remotedir}/${filename} 2>&1 >/dev/null
  1426. if [[ $? -ne 7 && $? -ne 22 && $? -ne 0 ]]; then
  1427. display_alert "Timeout from $server" "retrying" "info"
  1428. server="https://mirrors.tuna.tsinghua.edu.cn/armbian-releases/"
  1429. # switch to another china mirror if tuna timeouts
  1430. timeout 10 curl --head --fail --silent ${server}${remotedir}/${filename} 2>&1 >/dev/null
  1431. if [[ $? -ne 7 && $? -ne 22 && $? -ne 0 ]]; then
  1432. display_alert "Timeout from $server" "retrying" "info"
  1433. server="https://mirrors.bfsu.edu.cn/armbian-releases/"
  1434. fi
  1435. fi
  1436. # check if file exists on remote server before running aria2 downloader
  1437. [[ ! `timeout 10 curl --head --fail --silent ${server}${remotedir}/${filename}` ]] && return
  1438. cd "${localdir}" || exit
  1439. # use local control file
  1440. if [[ -f "${EXTER}"/config/torrents/${filename}.asc ]]; then
  1441. local torrent="${EXTER}"/config/torrents/${filename}.torrent
  1442. ln -sf "${EXTER}/config/torrents/${filename}.asc" "${localdir}/${filename}.asc"
  1443. elif [[ ! `timeout 10 curl --head --fail --silent "${server}${remotedir}/${filename}.asc"` ]]; then
  1444. return
  1445. else
  1446. # download control file
  1447. local torrent=${server}$remotedir/${filename}.torrent
  1448. aria2c --download-result=hide --disable-ipv6=true --summary-interval=0 --console-log-level=error --auto-file-renaming=false \
  1449. --continue=false --allow-overwrite=true --dir="${localdir}" ${server}${remotedir}/${filename}.asc $(webseed "$remotedir/${filename}.asc") -o "${filename}.asc"
  1450. [[ $? -ne 0 ]] && display_alert "Failed to download control file" "" "wrn"
  1451. fi
  1452. # download torrent first
  1453. if [[ ${USE_TORRENT} == "yes" ]]; then
  1454. display_alert "downloading using torrent network" "$filename"
  1455. local ariatorrent="--summary-interval=0 --auto-save-interval=0 --seed-time=0 --bt-stop-timeout=120 --console-log-level=error \
  1456. --allow-overwrite=true --download-result=hide --rpc-save-upload-metadata=false --auto-file-renaming=false \
  1457. --file-allocation=trunc --continue=true ${torrent} \
  1458. --dht-file-path=$EXTER/cache/.aria2/dht.dat --disable-ipv6=true --stderr --follow-torrent=mem --dir=${localdir}"
  1459. # exception. It throws error if dht.dat file does not exists. Error suppress needed only at first download.
  1460. if [[ -f $EXTER/cache/.aria2/dht.dat ]]; then
  1461. # shellcheck disable=SC2086
  1462. aria2c ${ariatorrent}
  1463. else
  1464. # shellcheck disable=SC2035
  1465. aria2c ${ariatorrent} &> "${DEST}"/${LOG_SUBPATH}/torrent.log
  1466. fi
  1467. # mark complete
  1468. [[ $? -eq 0 ]] && touch "${localdir}/${filename}.complete"
  1469. fi
  1470. # direct download if torrent fails
  1471. if [[ ! -f "${localdir}/${filename}.complete" ]]; then
  1472. if [[ ! `timeout 10 curl --head --fail --silent ${server}${remotedir}/${filename} 2>&1 >/dev/null` ]]; then
  1473. display_alert "downloading using http(s) network" "$filename"
  1474. aria2c --download-result=hide --rpc-save-upload-metadata=false --console-log-level=error \
  1475. --dht-file-path="${SRC}"/cache/.aria2/dht.dat --disable-ipv6=true --summary-interval=0 --auto-file-renaming=false --dir="${localdir}" ${server}${remotedir}/${filename} $(webseed "${remotedir}/${filename}") -o "${filename}"
  1476. # mark complete
  1477. [[ $? -eq 0 ]] && touch "${localdir}/${filename}.complete" && echo ""
  1478. fi
  1479. fi
  1480. if [[ -f ${localdir}/${filename}.asc ]]; then
  1481. if grep -q 'BEGIN PGP SIGNATURE' "${localdir}/${filename}.asc"; then
  1482. if [[ ! -d $EXTER/cache/.gpg ]]; then
  1483. mkdir -p $EXTER/cache/.gpg
  1484. chmod 700 $EXTER/cache/.gpg
  1485. touch $EXTER/cache/.gpg/gpg.conf
  1486. chmod 600 $EXTER/cache/.gpg/gpg.conf
  1487. fi
  1488. # Verify archives with Linaro and Armbian GPG keys
  1489. if [ x"" != x"${http_proxy}" ]; then
  1490. (gpg --homedir "${EXTER}"/cache/.gpg --no-permission-warning --list-keys 8F427EAF >> "${DEST}"/${LOG_SUBPATH}/output.log 2>&1\
  1491. || gpg --homedir "${EXTER}"/cache/.gpg --no-permission-warning \
  1492. --keyserver hkp://keyserver.ubuntu.com:80 --keyserver-options http-proxy="${http_proxy}" \
  1493. --recv-keys 8F427EAF >> "${DEST}"/${LOG_SUBPATH}/output.log 2>&1)
  1494. (gpg --homedir "${EXTER}"/cache/.gpg --no-permission-warning --list-keys 9F0E78D5 >> "${DEST}"/${LOG_SUBPATH}/output.log 2>&1\
  1495. || gpg --homedir "${EXTER}"/cache/.gpg --no-permission-warning \
  1496. --keyserver hkp://keyserver.ubuntu.com:80 --keyserver-options http-proxy="${http_proxy}" \
  1497. --recv-keys 9F0E78D5 >> "${DEST}"/${LOG_SUBPATH}/output.log 2>&1)
  1498. else
  1499. (gpg --homedir "${EXTER}"/cache/.gpg --no-permission-warning --list-keys 8F427EAF >> "${DEST}"/${LOG_SUBPATH}/output.log 2>&1\
  1500. || gpg --homedir "${EXTER}"/cache/.gpg --no-permission-warning \
  1501. --keyserver hkp://keyserver.ubuntu.com:80 \
  1502. --recv-keys 8F427EAF >> "${DEST}"/${LOG_SUBPATH}/output.log 2>&1)
  1503. (gpg --homedir "${EXTER}"/cache/.gpg --no-permission-warning --list-keys 9F0E78D5 >> "${DEST}"/${LOG_SUBPATH}/output.log 2>&1\
  1504. || gpg --homedir "${EXTER}"/cache/.gpg --no-permission-warning \
  1505. --keyserver hkp://keyserver.ubuntu.com:80 \
  1506. --recv-keys 9F0E78D5 >> "${DEST}"/${LOG_SUBPATH}/output.log 2>&1)
  1507. fi
  1508. gpg --homedir "${EXTER}"/cache/.gpg --no-permission-warning --verify \
  1509. --trust-model always -q "${localdir}/${filename}.asc" >> "${DEST}"/${LOG_SUBPATH}/output.log 2>&1
  1510. [[ ${PIPESTATUS[0]} -eq 0 ]] && verified=true && display_alert "Verified" "PGP" "info"
  1511. else
  1512. md5sum -c --status "${localdir}/${filename}.asc" && verified=true && display_alert "Verified" "MD5" "info"
  1513. fi
  1514. if [[ $verified == true ]]; then
  1515. if [[ "${filename:(-6)}" == "tar.xz" ]]; then
  1516. display_alert "decompressing"
  1517. pv -p -b -r -c -N "[ .... ] ${filename}" "${filename}" | xz -dc | tar xp --xattrs --no-same-owner --overwrite
  1518. [[ $? -eq 0 ]] && touch "${localdir}/${dirname}/.download-complete"
  1519. fi
  1520. else
  1521. exit_with_error "verification failed"
  1522. fi
  1523. fi
  1524. }
  1525. show_developer_warning()
  1526. {
  1527. local temp_rc
  1528. temp_rc=$(mktemp)
  1529. cat <<-'EOF' > "${temp_rc}"
  1530. screen_color = (WHITE,RED,ON)
  1531. EOF
  1532. local warn_text="You are switching to the \Z1EXPERT MODE\Zn
  1533. This allows building experimental configurations that are provided
  1534. \Z1AS IS\Zn to developers and expert users,
  1535. \Z1WITHOUT ANY RESPONSIBILITIES\Zn from the Armbian team:
  1536. - You are using these configurations \Z1AT YOUR OWN RISK\Zn
  1537. - Bug reports related to the dev kernel, CSC, WIP and EOS boards
  1538. \Z1will be closed without a discussion\Zn
  1539. - Forum posts related to dev kernel, CSC, WIP and EOS boards
  1540. should be created in the \Z2\"Community forums\"\Zn section
  1541. "
  1542. DIALOGRC=$temp_rc dialog --title "Expert mode warning" --backtitle "${backtitle}" --colors --defaultno --no-label "I do not agree" \
  1543. --yes-label "I understand and agree" --yesno "$warn_text" "${TTY_Y}" "${TTY_X}"
  1544. [[ $? -ne 0 ]] && exit_with_error "Error switching to the expert mode"
  1545. SHOW_WARNING=no
  1546. }
  1547. # is a formatted output of the values of variables
  1548. # from the list at the place of the function call.
  1549. #
  1550. # The LOG_OUTPUT_FILE variable must be defined in the calling function
  1551. # before calling the `show_checklist_variables` function and unset after.
  1552. #
  1553. show_checklist_variables ()
  1554. {
  1555. local checklist=$*
  1556. local var pval
  1557. local log_file=${LOG_OUTPUT_FILE:-"${SRC}"/output/${LOG_SUBPATH}/trash.log}
  1558. local _line=${BASH_LINENO[0]}
  1559. local _function=${FUNCNAME[1]}
  1560. local _file=$(basename "${BASH_SOURCE[1]}")
  1561. echo -e "Show variables in function: $_function" "[$_file:$_line]\n" >>$log_file
  1562. for var in $checklist;do
  1563. eval pval=\$$var
  1564. echo -e "\n$var =:" >>$log_file
  1565. if [ $(echo "$pval" | awk -F"/" '{print NF}') -ge 4 ];then
  1566. printf "%s\n" $pval >>$log_file
  1567. else
  1568. printf "%-30s %-30s %-30s %-30s\n" $pval >>$log_file
  1569. fi
  1570. done
  1571. }
  1572. install_wiringop()
  1573. {
  1574. install_deb_chroot "$EXTER/cache/debs/${ARCH}/wiringpi-2.58-1.deb"
  1575. chroot "${SDCARD}" /bin/bash -c "apt-mark hold wiringpi" >> "${DEST}"/${LOG_SUBPATH}/install.log 2>&1
  1576. if [[ ${IGNORE_UPDATES} != yes ]]; then
  1577. fetch_from_repo "https://github.com/orangepi-xunlong/wiringOP.git" "${EXTER}/cache/sources/wiringOP" "branch:next" "yes"
  1578. fetch_from_repo "https://github.com/orangepi-xunlong/wiringOP-Python.git" "${EXTER}/cache/sources/wiringOP-Python" "branch:next" "yes"
  1579. fi
  1580. cp ${EXTER}/cache/sources/wiringOP/next ${SDCARD}/usr/src/wiringOP -rfa
  1581. cp ${EXTER}/cache/sources/wiringOP-Python/next ${SDCARD}/usr/src/wiringOP-Python -rfa
  1582. rm $SDCARD/root/*.deb >/dev/null 2>&1
  1583. }
  1584. install_310b-npu-driver()
  1585. {
  1586. local driver_path="$EXTER/cache/sources/ascend-driver"
  1587. local driver_name="Ascend-hdk-310b-npu-driver_23.0.5_linux-aarch64-opiaimax.run"
  1588. local driver=${driver_path}/${driver_name}
  1589. if [[ -f "${driver}" ]]; then
  1590. display_alert "Installing" "$driver_name" "info"
  1591. cp "${driver}" "${SDCARD}/opt/"
  1592. chmod +x "${SDCARD}/opt/Ascend-hdk-310b-npu-driver_23.0.5_linux-aarch64-opiaimax.run"
  1593. chroot "${SDCARD}" /bin/bash -c "/opt/${driver_name} --chroot --full --install-username=orangepi --install-usergroup=orangepi --install-for-all"
  1594. fi
  1595. }
  1596. install_docker() {
  1597. [[ $install_docker != yes ]] && return
  1598. display_alert "Installing" "docker" "info"
  1599. chroot "${SDCARD}" /bin/bash -c "apt-get install -y -qq apt-transport-https ca-certificates curl gnupg2 software-properties-common >/dev/null 2>&1"
  1600. case ${RELEASE} in
  1601. buster|bullseye|bookworm)
  1602. distributor_id="debian"
  1603. ;;
  1604. xenial|bionic|focal|jammy|noble)
  1605. distributor_id="ubuntu"
  1606. ;;
  1607. esac
  1608. #if [[ ${SELECTED_CONFIGURATION} == desktop ]]; then
  1609. mirror_url=https://repo.huaweicloud.com
  1610. #else
  1611. # mirror_url=https://mirrors.aliyun.com
  1612. #fi
  1613. chroot "${SDCARD}" /bin/bash -c "curl -fsSL ${mirror_url}/docker-ce/linux/${distributor_id}/gpg | apt-key add -"
  1614. echo "deb [arch=${ARCH}] ${mirror_url}/docker-ce/linux/${distributor_id} ${RELEASE} stable" > "${SDCARD}"/etc/apt/sources.list.d/docker.list
  1615. chroot "${SDCARD}" /bin/bash -c "apt-get update"
  1616. chroot "${SDCARD}" /bin/bash -c "apt-get install -y -qq docker-ce docker-ce-cli containerd.io"
  1617. chroot "${SDCARD}" /bin/bash -c "sudo groupadd docker"
  1618. run_on_sdcard "systemctl --no-reload disable docker.service"
  1619. }
  1620. #function run_after_build()
  1621. #{
  1622. # chown -R $(logname).$(logname) $BOOTSOURCEDIR
  1623. # chown -R $(logname).$(logname) $LINUXSOURCEDIR
  1624. # chown -R $(logname).$(logname) $USERPATCHES_PATH
  1625. # chown -R $(logname).$(logname) $DEST/{config,debs,debug,images,patch}
  1626. #
  1627. # if [[ $DEBUG_DEB == yes && $BUILD_OPT =~ u-boot|kernel ]]; then
  1628. #
  1629. # [[ -z $REMOTEIP ]] && exit_with_error "The remote IP address has not been set" ""
  1630. # [[ -z $PASS_ROOT ]] && PASS_ROOT="orangepi"
  1631. # [[ -z $MMC_DEV ]] && MMC_DEV="tfcard"
  1632. #
  1633. # #ssh-keygen -f "~/.ssh/known_hosts" -R ${REMOTEIP}
  1634. # local num=0
  1635. # while true;
  1636. # do
  1637. # ping ${REMOTEIP} -c 1 > /dev/null 2>&1
  1638. #
  1639. # if [[ $? == 0 ]]; then
  1640. # echo " "
  1641. # break
  1642. # fi
  1643. #
  1644. # if [[ $num == 0 ]]; then
  1645. # display_alert "${BOARD} network cannot be connected" "${REMOTEIP}" "wrn"
  1646. # ((num++))
  1647. # fi
  1648. #
  1649. # echo -e ".\c"
  1650. # done
  1651. # display_alert "${BOARD} network is connected" "${REMOTEIP}" "info"
  1652. #
  1653. # if [[ $BUILD_OPT == u-boot ]]; then
  1654. # sshpass -p ${PASS_ROOT} scp ${DEB_STORAGE}/u-boot/${CHOSEN_UBOOT}_${REVISION}_${ARCH}.deb root@${REMOTEIP}:/root
  1655. # display_alert "Uninstall deb package" "linux-u-boot-${BOARD}-${BRANCH}" "info"
  1656. # sshpass -p ${PASS_ROOT} ssh root@${REMOTEIP} "apt-get purge -y linux-u-boot-${BOARD}-${BRANCH}"
  1657. # display_alert "Install deb package" "${CHOSEN_UBOOT}_${REVISION}_${ARCH}.deb" "info"
  1658. # sshpass -p ${PASS_ROOT} ssh root@${REMOTEIP} "dpkg -i /root/${CHOSEN_UBOOT}_${REVISION}_${ARCH}.deb"
  1659. #
  1660. # if [[ $MMC_DEV == emmc ]]; then
  1661. # display_alert "Burn the U-Boot into EMMC" "" "info"
  1662. # sshpass -p ${PASS_ROOT} ssh root@${REMOTEIP} "dd bs=1k seek=8 if=/usr/lib/linux-u-boot-legacy-orangepi400_2.1.0_arm64/boot0_sdcard.fex of=/dev/mmcblk0"
  1663. # sshpass -p ${PASS_ROOT} ssh root@${REMOTEIP} "dd bs=1k seek=16400 if=/usr/lib/linux-u-boot-legacy-orangepi400_2.1.0_arm64/boot_package.fex of=/dev/mmcblk0"
  1664. # sshpass -p ${PASS_ROOT} ssh root@${REMOTEIP} "sync"
  1665. # else
  1666. # display_alert "Burn the U-Boot into TF card" "" "info"
  1667. # sshpass -p ${PASS_ROOT} ssh root@${REMOTEIP} "nand-sata-install DEBUG_UBOOT"
  1668. # sshpass -p ${PASS_ROOT} ssh root@${REMOTEIP} "sync"
  1669. # sshpass -p ${PASS_ROOT} ssh root@${REMOTEIP} "reboot"
  1670. # fi
  1671. # fi
  1672. #
  1673. # if [[ $BUILD_OPT == kernel ]]; then
  1674. # sshpass -p ${PASS_ROOT} scp ${DEB_STORAGE}/linux-image-${BRANCH}-${LINUXFAMILY}_${REVISION}_${ARCH}.deb root@${REMOTEIP}:/root
  1675. # sshpass -p ${PASS_ROOT} ssh root@${REMOTEIP} "apt-get purge -y linux-image-${BRANCH}-${LINUXFAMILY}"
  1676. # sshpass -p ${PASS_ROOT} ssh root@${REMOTEIP} "dpkg -i /root/linux-image-${BRANCH}-${LINUXFAMILY}_${REVISION}_${ARCH}.deb"
  1677. # if [[ $BRANCH == current && $BOARD =~ orangepizero2|orangepi400 ]]; then
  1678. # sshpass -p ${PASS_ROOT} scp ${LINUXSOURCEDIR}/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-*.dtb root@${REMOTEIP}:/boot/dtb/allwinner/
  1679. # fi
  1680. #
  1681. # sshpass -p ${PASS_ROOT} ssh root@${REMOTEIP} "sync"
  1682. # sshpass -p ${PASS_ROOT} ssh root@${REMOTEIP} "reboot"
  1683. # fi
  1684. # fi
  1685. #
  1686. # if [[ $DEBUG_DEB == yes && $BUILD_OPT == image ]]; then
  1687. # scp ${destimg}/*.img ${PC_NAME}@${PC_IP}:${PC_DIR}
  1688. # fi
  1689. #}