build.sh 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. #!/usr/bin/env bash
  2. set -euo pipefail
  3. #
  4. # variables
  5. #
  6. RESET="\033[0m"
  7. RED="\033[0;31m"
  8. YELLOW="\033[0;33m"
  9. DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
  10. target_os_name=''
  11. ci=false
  12. use_default_binary_log=false
  13. verbosity='minimal'
  14. run_restore=''
  15. run_build=true
  16. run_pack=false
  17. run_tests=false
  18. build_all=false
  19. build_deps=true
  20. build_repo_tasks=true
  21. build_managed=''
  22. build_native=''
  23. build_nodejs=''
  24. build_java=''
  25. build_installers=''
  26. build_projects=''
  27. target_arch='x64'
  28. configuration=''
  29. if [ "$(uname)" = "Darwin" ]; then
  30. target_os_name='osx'
  31. else
  32. target_os_name='linux'
  33. fi
  34. msbuild_args=()
  35. #
  36. # Functions
  37. #
  38. __usage() {
  39. echo "Usage: $(basename "${BASH_SOURCE[0]}") [options] [[--] <Arguments>...]
  40. Arguments:
  41. <Arguments>... Arguments passed to the command. Variable number of arguments allowed.
  42. Options:
  43. --configuration|-c The build configuration (Debug, Release). Default=Debug
  44. --arch The CPU architecture to build for (x64, arm, arm64). Default=$target_arch
  45. --os-name The base runtime identifier to build for (linux, osx, linux-musl). Default=$target_os_name
  46. --[no-]restore Run restore.
  47. --[no-]build Compile projects. (Implies --no-restore)
  48. --[no-]pack Produce packages.
  49. --[no-]test Run tests.
  50. --projects A list of projects to build. (Must be an absolute path.)
  51. Globbing patterns are supported, such as \"$(pwd)/**/*.csproj\".
  52. --no-build-deps Do not build project-to-project references and only build the specified project.
  53. --no-build-repo-tasks Suppress building RepoTasks.
  54. --all Build all project types.
  55. --[no-]build-native Build native projects (C, C++).
  56. --[no-]build-managed Build managed projects (C#, F#, VB).
  57. --[no-]build-nodejs Build NodeJS projects (TypeScript, JS).
  58. --[no-]build-java Build Java projects.
  59. --[no-]build-installers Build Java projects.
  60. --ci Apply CI specific settings and environment variables.
  61. --binarylog|-bl Use a binary logger
  62. --verbosity|-v MSBuild verbosity: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic]
  63. Description:
  64. This build script installs required tools and runs an MSBuild command on this repository
  65. This script can be used to invoke various targets, such as targets to produce packages
  66. build projects, run tests, and generate code.
  67. "
  68. if [[ "${1:-}" != '--no-exit' ]]; then
  69. exit 2
  70. fi
  71. }
  72. __error() {
  73. echo -e "${RED}error: $*${RESET}" 1>&2
  74. }
  75. __warn() {
  76. echo -e "${YELLOW}warning: $*${RESET}"
  77. }
  78. #
  79. # main
  80. #
  81. while [[ $# -gt 0 ]]; do
  82. opt="$(echo "${1/#--/-}" | awk '{print tolower($0)}')"
  83. case "$opt" in
  84. -\?|-h|-help)
  85. __usage --no-exit
  86. exit 0
  87. ;;
  88. -configuration|-c)
  89. shift
  90. configuration="${1:-}"
  91. [ -z "$configuration" ] && __error "Missing value for parameter --configuration" && __usage
  92. ;;
  93. -arch)
  94. shift
  95. target_arch="${1:-}"
  96. [ -z "$target_arch" ] && __error "Missing value for parameter --arch" && __usage
  97. ;;
  98. -os-name|-osname)
  99. shift
  100. target_os_name="${1:-}"
  101. [ -z "$target_os_name" ] && __error "Missing value for parameter --os-name" && __usage
  102. ;;
  103. -restore|-r)
  104. run_restore=true
  105. ;;
  106. -no-restore|-norestore)
  107. run_restore=false
  108. ;;
  109. -build|-b)
  110. run_build=true
  111. ;;
  112. -no-build|-nobuild)
  113. run_build=false
  114. # --no-build implies --no-restore
  115. [ -z "$run_restore" ] && run_restore=false
  116. ;;
  117. -no-build-deps|-nobuilddeps)
  118. build_deps=false
  119. ;;
  120. -pack)
  121. run_pack=true
  122. ;;
  123. -no-pack|-nopack)
  124. run_pack=false
  125. ;;
  126. -test|-t)
  127. run_tests=true
  128. ;;
  129. -no-test|-notest)
  130. run_tests=false
  131. ;;
  132. -projects)
  133. shift
  134. build_projects="${1:-}"
  135. [ -z "$build_projects" ] && __error "Missing value for parameter --projects" && __usage
  136. ;;
  137. -all)
  138. build_all=true
  139. ;;
  140. -build-managed|-buildmanaged)
  141. build_managed=true
  142. ;;
  143. -no-build-managed|-nobuildmanaged)
  144. build_managed=false
  145. ;;
  146. -build-nodejs|-buildnodejs)
  147. build_nodejs=true
  148. ;;
  149. -no-build-nodejs|-nobuildnodejs)
  150. build_nodejs=false
  151. ;;
  152. -build-java|-buildjava)
  153. build_java=true
  154. ;;
  155. -no-build-java|-nobuildjava)
  156. build_java=false
  157. ;;
  158. -build-native|-buildnative)
  159. build_native=true
  160. ;;
  161. -no-build-native|-nobuildnative)
  162. build_native=false
  163. ;;
  164. -build-installers|-buildinstallers)
  165. build_installers=true
  166. ;;
  167. -no-build-installers|-nobuildinstallers)
  168. build_installers=false
  169. ;;
  170. -no-build-repo-tasks|-nobuildrepotasks)
  171. build_repo_tasks=false
  172. ;;
  173. -ci)
  174. ci=true
  175. ;;
  176. -binarylog|-bl)
  177. use_default_binary_log=true
  178. ;;
  179. -verbosity|-v)
  180. shift
  181. [ -z "${1:-}" ] && __error "Missing value for parameter --verbosity" && __usage
  182. verbosity="${1:-}"
  183. ;;
  184. *)
  185. msbuild_args[${#msbuild_args[*]}]="$1"
  186. ;;
  187. esac
  188. shift
  189. done
  190. if [ "$build_all" = true ]; then
  191. msbuild_args[${#msbuild_args[*]}]="-p:BuildAllProjects=true"
  192. elif [ ! -z "$build_projects" ]; then
  193. msbuild_args[${#msbuild_args[*]}]="-p:ProjectToBuild=$build_projects"
  194. elif [ -z "$build_managed" ] && [ -z "$build_nodejs" ] && [ -z "$build_java" ] && [ -z "$build_native" ] && [ -z "$build_installers" ]; then
  195. # This goal of this is to pick a sensible default for `build.sh` with zero arguments.
  196. # We believe the most common thing our contributors will work on is C#, so if no other build group was picked, build the C# projects.
  197. __warn "No default group of projects was specified, so building the 'managed' and its dependent subset of projects. Run ``build.sh --help`` for more details."
  198. build_managed=true
  199. fi
  200. if [ "$build_deps" = false ]; then
  201. msbuild_args[${#msbuild_args[*]}]="-p:BuildProjectReferences=false"
  202. fi
  203. if [ "$build_managed" = true ] || ([ "$build_all" = true ] && [ "$build_managed" != false ]); then
  204. if [ -z "$build_nodejs" ]; then
  205. if [ -x "$(command -v node)" ]; then
  206. __warn "Building of C# project is enabled and has dependencies on NodeJS projects. Building of NodeJS projects is enabled since node is detected on PATH."
  207. else
  208. __warn "Building of NodeJS projects is disabled since node is not detected on Path and no BuildNodeJs or NoBuildNodeJs setting is set explicitly."
  209. build_nodejs=false
  210. fi
  211. fi
  212. if [ "$build_nodejs" = false ]; then
  213. __warn "Some managed projects depend on NodeJS projects. Building NodeJS is disabled so the managed projects will fallback to using the output from previous builds. The output may not be correct or up to date."
  214. fi
  215. fi
  216. # Only set these MSBuild properties if they were explicitly set by build parameters.
  217. [ ! -z "$build_java" ] && msbuild_args[${#msbuild_args[*]}]="-p:BuildJava=$build_java"
  218. [ ! -z "$build_native" ] && msbuild_args[${#msbuild_args[*]}]="-p:BuildNative=$build_native"
  219. [ ! -z "$build_nodejs" ] && msbuild_args[${#msbuild_args[*]}]="-p:BuildNodeJS=$build_nodejs"
  220. [ ! -z "$build_managed" ] && msbuild_args[${#msbuild_args[*]}]="-p:BuildManaged=$build_managed"
  221. [ ! -z "$build_installers" ] && msbuild_args[${#msbuild_args[*]}]="-p:BuildInstallers=$build_installers"
  222. # Run restore by default unless --no-restore or --no-build was specified.
  223. [ -z "$run_restore" ] && run_restore=true
  224. msbuild_args[${#msbuild_args[*]}]="-p:Restore=$run_restore"
  225. msbuild_args[${#msbuild_args[*]}]="-p:Build=$run_build"
  226. if [ "$run_build" = false ]; then
  227. msbuild_args[${#msbuild_args[*]}]="-p:NoBuild=true"
  228. fi
  229. msbuild_args[${#msbuild_args[*]}]="-p:Pack=$run_pack"
  230. msbuild_args[${#msbuild_args[*]}]="-p:Test=$run_tests"
  231. msbuild_args[${#msbuild_args[*]}]="-p:TargetArchitecture=$target_arch"
  232. msbuild_args[${#msbuild_args[*]}]="-p:TargetOsName=$target_os_name"
  233. if [ -z "$configuration" ]; then
  234. if [ "$ci" = true ]; then
  235. configuration='Release'
  236. else
  237. configuration='Debug'
  238. fi
  239. fi
  240. msbuild_args[${#msbuild_args[*]}]="-p:Configuration=$configuration"
  241. # Set verbosity
  242. echo "Setting msbuild verbosity to $verbosity"
  243. msbuild_args[${#msbuild_args[*]}]="-verbosity:$verbosity"
  244. # Initialize global variables need to be set before the import of Arcade is imported
  245. restore=$run_restore
  246. # Disable node reuse - Workaround perpetual issues in node reuse and custom task assemblies
  247. nodeReuse=false
  248. export MSBUILDDISABLENODEREUSE=1
  249. # Our build often has warnings that we can't fix
  250. # Fixing this is tracked by https://github.com/dotnet/aspnetcore-internal/issues/601
  251. warn_as_error=false
  252. # Workaround Arcade check which asserts BinaryLog is true on CI.
  253. # We always use binlogs on CI, but we customize the name of the log file
  254. if [ "$ci" = true ]; then
  255. binary_log=true
  256. fi
  257. # increase file descriptor limit on macOS
  258. if [ "$(uname)" = "Darwin" ]; then
  259. ulimit -n 10000
  260. fi
  261. # Import Arcade
  262. . "$DIR/eng/common/tools.sh"
  263. if [ "$use_default_binary_log" = true ]; then
  264. msbuild_args[${#msbuild_args[*]}]="-bl:\"$log_dir/Build.binlog\""
  265. fi
  266. # Capture MSBuild crash logs
  267. export MSBUILDDEBUGPATH="$log_dir"
  268. # Import custom tools configuration, if present in the repo.
  269. configure_toolset_script="$eng_root/configure-toolset.sh"
  270. if [[ -a "$configure_toolset_script" ]]; then
  271. . "$configure_toolset_script"
  272. fi
  273. # Set this global property so Arcade will always initialize the toolset. The error message you get when you build on a clean machine
  274. # with -norestore is not obvious about what to do to fix it. As initialization takes very little time, we think always initializing
  275. # the toolset is a better default behavior.
  276. _tmp_restore=$restore
  277. restore=true
  278. InitializeToolset
  279. restore=$_tmp_restore=
  280. if [ "$build_repo_tasks" = true ]; then
  281. MSBuild $_InitializeToolset \
  282. -p:RepoRoot="$repo_root" \
  283. -p:Projects="$DIR/eng/tools/RepoTasks/RepoTasks.csproj" \
  284. -p:Configuration=Release \
  285. -p:Restore=$run_restore \
  286. -p:Build=true \
  287. -clp:NoSummary
  288. fi
  289. # This incantation avoids unbound variable issues if msbuild_args is empty
  290. # https://stackoverflow.com/questions/7577052/bash-empty-array-expansion-with-set-u
  291. MSBuild $_InitializeToolset -p:RepoRoot="$repo_root" ${msbuild_args[@]+"${msbuild_args[@]}"}
  292. ExitWithExitCode 0