2
0

build-pkg.sh 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. #!/bin/sh
  2. # Copyright (C) 2018-2025 Nick Peng ([email protected])
  3. CURR_DIR=$(cd $(dirname $0);pwd)
  4. WORKDIR=$CURR_DIR/target
  5. VER="`date +"1.%Y.%m.%d-%H%M"`"
  6. CODE_DIR="$CURR_DIR/.."
  7. IS_BUILD_SMARTDNS=1
  8. OUTPUTDIR=$CURR_DIR
  9. SMARTDNS_WEBUI_URL="https://github.com/pymumu/smartdns-webui/archive/refs/heads/main.zip"
  10. SMARTDNS_WEBUI_SOURCE="$WORKDIR/smartdns-webui"
  11. SMARTDNS_STATIC_DIR="$WORKDIR/smartdns-static"
  12. SMARTDNS_WITH_LIBS=0
  13. MAKE_NJOBS=1
  14. export CC
  15. export STRIP
  16. export WORKDIR
  17. WITH_UI=0
  18. showhelp()
  19. {
  20. echo "Usage: $0 [OPTION]"
  21. echo "Options:"
  22. echo " --platform [luci|luci-compat|debian|openwrt|optware|linux] build for platform. "
  23. echo " --arch [all|armhf|arm64|x86-64|...] build for architecture, e.g. "
  24. echo " --cross-tool [cross-tool] cross compiler, e.g. mips-openwrt-linux-"
  25. echo " --with-ui build with smartdns-ui plugin."
  26. echo ""
  27. echo "Advance Options:"
  28. echo " --static static link smartdns"
  29. echo " --only-package only package, not build source"
  30. echo " --filearch [arch] output file arch, default: equal --arch"
  31. echo " --outputdir [dir] output package to specific directory"
  32. echo " "
  33. echo "Example:"
  34. echo " build luci:"
  35. echo " $0 --platform luci"
  36. echo " build luci:"
  37. echo " $0 --platform luci-compat"
  38. echo " build debian:"
  39. echo " $0 --platform debian --arch x86-64"
  40. echo " build raspbian pi:"
  41. echo " $0 --platform debian --arch arm64 --with-ui"
  42. echo " build optware mips:"
  43. echo " $0 --platform optware --arch mipsbig"
  44. echo " build openwrt mips:"
  45. echo " $0 --platform openwrt --arch mips"
  46. echo " build generic linux:"
  47. echo " $0 --platform linux --arch x86-64 --with-ui"
  48. }
  49. init_env()
  50. {
  51. if [ -z "$CC" ]; then
  52. CC=gcc
  53. fi
  54. MAKE_NJOBS=$(grep processor /proc/cpuinfo | wc -l 2>/dev/null || echo 1)
  55. export MAKE_NJOBS
  56. mkdir -p $WORKDIR
  57. if [ $? -ne 0 ]; then
  58. echo "create work directory failed"
  59. return 1
  60. fi
  61. if [ "$STATIC" = "yes" ] && [ $WITH_UI -eq 1 ]; then
  62. SMARTDNS_WITH_LIBS=1
  63. fi
  64. check_cc="`echo "$CC" | grep -E "(\-gcc|\-cc)"`"
  65. if [ ! -z "$check_cc" ]; then
  66. TARGET_ARCH="`$CC -dumpmachine`"
  67. echo "target arch: $TARGET_ARCH"
  68. fi
  69. if [ $SMARTDNS_WITH_LIBS -eq 1 ]; then
  70. case "$TARGET_ARCH" in
  71. *arm*)
  72. NEED_UPDATE_ARM_CP15=1
  73. echo "Update arm cp15"
  74. ;;
  75. *)
  76. ;;
  77. esac
  78. LINKER_NAME=`$CC -Xlinker -v 2>&1 | grep -oP '(?<=-dynamic-linker )[^ ]+'`
  79. if [ -z "$LINKER_NAME" ]; then
  80. echo "get linker name failed"
  81. return 1
  82. fi
  83. LINKER_NAME=`basename $LINKER_NAME`
  84. LINKER_SYSROOT="`$CC --print-sysroot`"
  85. export BINDGEN_EXTRA_CLANG_ARGS="--sysroot=$LINKER_SYSROOT"
  86. echo "linker name: $LINKER_NAME"
  87. fi
  88. }
  89. copy_smartdns_libs()
  90. {
  91. SMARTDNS_BIN="$CODE_DIR/src/smartdns"
  92. copy_libs_recursive $SMARTDNS_BIN
  93. if [ $? -ne 0 ]; then
  94. echo "copy libs failed"
  95. return 1
  96. fi
  97. LIB_WEBUI_SO="$CODE_DIR/plugin/smartdns-ui/target/smartdns_ui.so"
  98. copy_libs_recursive $LIB_WEBUI_SO
  99. if [ $? -ne 0 ]; then
  100. echo "copy libs failed"
  101. return 1
  102. fi
  103. }
  104. copy_libs_recursive()
  105. {
  106. local lib=$1
  107. local lib_path=`$CC -print-file-name=$lib`
  108. if [ -z "$lib_path" ]; then
  109. return 0
  110. fi
  111. if [ -e $SMARTDNS_STATIC_DIR/lib/$lib ]; then
  112. return 0
  113. fi
  114. local tmp_path="`echo "$lib_path" | grep "libc.so"`"
  115. if [ ! -z "$tmp_path" ]; then
  116. LIBC_PATH="$tmp_path"
  117. fi
  118. if [ "$lib" != "$SMARTDNS_BIN" ]; then
  119. echo "copy $lib_path to $SMARTDNS_STATIC_DIR/lib"
  120. cp $lib_path $SMARTDNS_STATIC_DIR/lib
  121. if [ $? -ne 0 ]; then
  122. echo "copy $lib failed"
  123. return 1
  124. fi
  125. fi
  126. local shared_libs="`objdump -p $lib_path | grep NEEDED | awk '{print $2}'`"
  127. for sub_lib in $shared_libs; do
  128. copy_libs_recursive $sub_lib
  129. if [ $? -ne 0 ]; then
  130. return 1
  131. fi
  132. done
  133. return 0
  134. }
  135. copy_linker()
  136. {
  137. LINK_PATH=`$CC -print-file-name=$LINKER_NAME`
  138. SYM_LINKER_NAME=`readlink -f $LINK_PATH`
  139. echo "linker: $LINK_PATH"
  140. echo "sym linker: $SYM_LINKER_NAME"
  141. echo "libc: $LIBC_PATH"
  142. if [ "$SYM_LINKER_NAME" = "$LIBC_PATH" ]; then
  143. ln -f -s $(basename $LIBC_PATH) $SMARTDNS_STATIC_DIR/lib/$(basename $LINKER_NAME)
  144. else
  145. cp $LINK_PATH $SMARTDNS_STATIC_DIR/lib -af
  146. if [ $? -ne 0 ]; then
  147. echo "copy $lib failed"
  148. return 1
  149. fi
  150. SYM_LINKER_NAME=`readlink $SMARTDNS_STATIC_DIR/lib/$LINKER_NAME`
  151. if [ ! -e $SMARTDNS_STATIC_DIR/lib/$SYM_LINKER_NAME ]; then
  152. SYM_LINKER_NAME=`basename $SYM_LINKER_NAME`
  153. ln -f -s $SYM_LINKER_NAME $SMARTDNS_STATIC_DIR/lib/$LINKER_NAME
  154. fi
  155. fi
  156. ln -f -s ${LINKER_NAME} ${SMARTDNS_STATIC_DIR}/lib/ld-linux.so
  157. if [ $? -ne 0 ]; then
  158. echo "copy $lib failed"
  159. return 1
  160. fi
  161. return 0
  162. }
  163. build_smartdns()
  164. {
  165. MAKE_WITH_UI=""
  166. if [ $WITH_UI -eq 1 ]; then
  167. MAKE_WITH_UI="WITH_UI=1"
  168. fi
  169. if [ "$PLATFORM" = "luci" ]; then
  170. return 0
  171. fi
  172. make -C $CODE_DIR clean $MAKE_ARGS
  173. if [ $SMARTDNS_WITH_LIBS -eq 1 ]; then
  174. LINK_LDFLAGS='-Wl,-dynamic-linker,'lib/$(echo $LINKER_NAME)' -Wl,-rpath,\$$ORIGIN:\$$ORIGIN/lib'
  175. export LDFLAGS="$LDFLAGS $LINK_LDFLAGS"
  176. echo "LDFLAGS: $LDFLAGS"
  177. RUSTFLAGS='-C link-arg=-Wl,-rpath,$$ORIGIN'
  178. echo "Building smartdns with specific linker..."
  179. unset STATIC
  180. fi
  181. RUSTFLAGS="$RUSTFLAGS" make -C $CODE_DIR $MAKE_WITH_UI all -j$MAKE_NJOBS VER=$VER $MAKE_ARGS
  182. if [ $? -ne 0 ]; then
  183. echo "make smartdns failed"
  184. exit 1
  185. fi
  186. $STRIP -d $CODE_DIR/src/smartdns >/dev/null 2>&1
  187. rm -fr $SMARTDNS_STATIC_DIR
  188. if [ $SMARTDNS_WITH_LIBS -eq 0 ]; then
  189. return 0;
  190. fi
  191. echo "copy smartdns binary to $SMARTDNS_STATIC_DIR"
  192. mkdir -p $SMARTDNS_STATIC_DIR/lib
  193. if [ $? -ne 0 ]; then
  194. echo "create target directory failed"
  195. return 1
  196. fi
  197. cp $CODE_DIR/src/smartdns $SMARTDNS_STATIC_DIR/
  198. if [ $? -ne 0 ]; then
  199. echo "copy smartdns binary failed"
  200. return 1
  201. fi
  202. cp $CURR_DIR/run-smartdns $SMARTDNS_STATIC_DIR
  203. chmod +x $SMARTDNS_STATIC_DIR/run-smartdns
  204. if [ "$NEED_UPDATE_ARM_CP15" = "1" ]; then
  205. sed -i 's/NEED_CHECK_ARM_CP15=0/NEED_CHECK_ARM_CP15=1/' $SMARTDNS_STATIC_DIR/run-smartdns
  206. if [ $? -ne 0 ]; then
  207. echo "sed run-smartdns failed"
  208. return 1
  209. fi
  210. fi
  211. copy_smartdns_libs
  212. if [ $? -ne 0 ]; then
  213. echo "copy smartdns libs failed"
  214. return 1
  215. fi
  216. rm $SMARTDNS_STATIC_DIR/lib/smartdns_ui.so >/dev/null 2>&1
  217. copy_linker
  218. if [ $? -ne 0 ]; then
  219. echo "copy linker failed"
  220. return 1
  221. fi
  222. return 0
  223. }
  224. build_webpages()
  225. {
  226. if [ ! -f "$WORKDIR/smartdns-webui.zip" ]; then
  227. echo "smartdns-webui source not found, downloading..."
  228. wget -O $WORKDIR/smartdns-webui.zip $SMARTDNS_WEBUI_URL
  229. if [ $? -ne 0 ]; then
  230. echo "Failed to download smartdns-webui source at $SMARTDNS_WEBUI_URL"
  231. return 1
  232. fi
  233. fi
  234. if [ ! -d "$SMARTDNS_WEBUI_SOURCE" ]; then
  235. echo "smartdns-webui source not found, unzipping..."
  236. unzip -q $WORKDIR/smartdns-webui.zip -d $WORKDIR
  237. if [ $? -ne 0 ]; then
  238. echo "Failed to unzip smartdns-webui source."
  239. return 1
  240. fi
  241. mv $WORKDIR/smartdns-webui-main $SMARTDNS_WEBUI_SOURCE
  242. if [ $? -ne 0 ]; then
  243. echo "Failed to rename smartdns-webui directory."
  244. return 1
  245. fi
  246. fi
  247. if [ ! -d "$SMARTDNS_WEBUI_SOURCE" ]; then
  248. echo "smartdns-webui source not found."
  249. return 1
  250. fi
  251. if [ ! -f "$SMARTDNS_WEBUI_SOURCE/package.json" ]; then
  252. echo "smartdns-webui source is not valid."
  253. return 1
  254. fi
  255. if [ -f "$SMARTDNS_WEBUI_SOURCE/out/index.html" ]; then
  256. echo "smartdns-webui already built, skipping build."
  257. return 0
  258. fi
  259. echo "Building smartdns-webui..."
  260. npm install --prefix $SMARTDNS_WEBUI_SOURCE
  261. if [ $? -ne 0 ]; then
  262. echo "Failed to install smartdns-webui dependencies."
  263. return 1
  264. fi
  265. npm run build --prefix $SMARTDNS_WEBUI_SOURCE
  266. if [ $? -ne 0 ]; then
  267. echo "Failed to build smartdns-webui."
  268. return 1
  269. fi
  270. echo "smartdns-webui build completed."
  271. return 0
  272. }
  273. build()
  274. {
  275. echo "build package for $PLATFORM"
  276. if [ $IS_BUILD_SMARTDNS -eq 1 ]; then
  277. build_smartdns
  278. if [ $? -ne 0 ]; then
  279. return 1
  280. fi
  281. fi
  282. WITH_UI_ARGS=""
  283. if [ $WITH_UI -eq 1 ] && [ "$PLATFORM" != "luci" ]; then
  284. build_webpages
  285. if [ $? -ne 0 ]; then
  286. echo "build smartdns-ui failed"
  287. return 1
  288. fi
  289. WITH_UI_ARGS="--with-ui"
  290. fi
  291. chmod +x $CODE_DIR/package/$PLATFORM/make.sh
  292. $CODE_DIR/package/$PLATFORM/make.sh -o $CURR_DIR --arch $ARCH --ver $VER --filearch $FILEARCH $WITH_UI_ARGS -o $OUTPUTDIR
  293. if [ $? -ne 0 ]; then
  294. echo "build package for $PLATFORM failed"
  295. return 1
  296. fi
  297. echo "build package for $PLATFORM success."
  298. return 0
  299. }
  300. main()
  301. {
  302. OPTS=`getopt -o o:h --long arch:,filearch:,ver:,platform:,cross-tool:,with-nftables,static,only-package,with-ui,outputdir: \
  303. -n "" -- "$@"`
  304. if [ "$#" -le "1" ]; then
  305. showhelp
  306. exit 1
  307. fi
  308. if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
  309. # Note the quotes around `$TEMP': they are essential!
  310. eval set -- "$OPTS"
  311. while true; do
  312. case "$1" in
  313. --arch)
  314. ARCH="$2"
  315. shift 2;;
  316. --filearch)
  317. FILEARCH="$2"
  318. shift 2;;
  319. --platform)
  320. PLATFORM="$2"
  321. shift 2;;
  322. --cross-tool)
  323. CROSS_TOOL="$2"
  324. shift 2;;
  325. --static)
  326. export STATIC="yes"
  327. shift 1;;
  328. --only-package)
  329. IS_BUILD_SMARTDNS=0
  330. shift 1;;
  331. --outputdir)
  332. OUTPUTDIR="$2"
  333. shift 2;;
  334. --with-ui)
  335. WITH_UI=1
  336. shift 1;;
  337. --ver)
  338. VER="$2"
  339. shift 2;;
  340. -h | --help )
  341. showhelp
  342. return 0
  343. shift ;;
  344. -- ) shift; break ;;
  345. * ) break ;;
  346. esac
  347. done
  348. if [ -z "$PLATFORM" ]; then
  349. echo "please input platform"
  350. echo "run $0 -h for help."
  351. return 1
  352. fi
  353. if [ "$PLATFORM" = "luci" ]; then
  354. ARCH="all"
  355. fi
  356. if [ -z "$ARCH" ]; then
  357. echo "please input arch."
  358. echo "run $0 -h for help."
  359. return 1
  360. fi
  361. if [ -z "$FILEARCH" ]; then
  362. FILEARCH="$ARCH"
  363. fi
  364. if [ -z "$OUTPUTDIR" ]; then
  365. OUTPUTDIR=$CURR_DIR
  366. fi
  367. if [ ! -z "$CROSS_TOOL" ]; then
  368. CC="${CROSS_TOOL}gcc"
  369. STRIP="${CROSS_TOOL}strip"
  370. fi
  371. if [ -z "$CC" ]; then
  372. CC="gcc"
  373. fi
  374. if [ -z "$STRIP" ]; then
  375. if [ ! -z "`echo $CC | grep '\-gcc'`" ]; then
  376. STRIP="`echo "$CC" | sed 's/-gcc\$/-strip/g'`"
  377. else
  378. STRIP="strip"
  379. fi
  380. fi
  381. if [ ! -e "`which $CC`" ]; then
  382. echo "Cannot find compiler $CC"
  383. return 1
  384. fi
  385. init_env
  386. build
  387. }
  388. main $@
  389. exit $?