.build.zsh 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. #!/usr/bin/env zsh
  2. builtin emulate -L zsh
  3. setopt EXTENDED_GLOB
  4. setopt PUSHD_SILENT
  5. setopt ERR_EXIT
  6. setopt ERR_RETURN
  7. setopt NO_UNSET
  8. setopt PIPE_FAIL
  9. setopt NO_AUTO_PUSHD
  10. setopt NO_PUSHD_IGNORE_DUPS
  11. setopt FUNCTION_ARGZERO
  12. ## Enable for script debugging
  13. #setopt WARN_CREATE_GLOBAL
  14. #setopt WARN_NESTED_VAR
  15. #setopt XTRACE
  16. if (( ! ${+CI} )) {
  17. print -u2 -PR "%F{1} ✖︎ ${ZSH_ARGZERO:t:r} requires CI environment.%f"
  18. exit 1
  19. }
  20. autoload -Uz is-at-least && if ! is-at-least 5.9; then
  21. print -u2 -PR "%F{1}${funcstack[1]##*/}:%f Running on Zsh version %B${ZSH_VERSION}%b, but Zsh %B5.9%b is the minimum supported version. Upgrade Zsh to fix this issue."
  22. exit 1
  23. fi
  24. TRAPZERR() {
  25. print -u2 -PR "::error::%F{1} ✖︎ script execution error.%f"
  26. print -PR -e "
  27. Callstack:
  28. ${(j:\n :)funcfiletrace}
  29. "
  30. exit 2
  31. }
  32. build() {
  33. if (( ! ${+SCRIPT_HOME} )) typeset -g SCRIPT_HOME=${ZSH_ARGZERO:A:h}
  34. local host_os=${${(s:-:)ZSH_ARGZERO:t:r}[2]}
  35. local project_root=${SCRIPT_HOME:A:h:h}
  36. local buildspec_file=${project_root}/buildspec.json
  37. fpath=(${SCRIPT_HOME}/utils.zsh ${fpath})
  38. autoload -Uz log_group log_error log_output check_${host_os} setup_ccache
  39. if [[ ! -r ${buildspec_file} ]] {
  40. log_error 'Missing buildspec.json in project checkout.'
  41. return 2
  42. }
  43. local -i debug=0
  44. local target
  45. local -r -a _valid_targets=(
  46. macos-x86_64
  47. macos-arm64
  48. ubuntu-x86_64
  49. )
  50. local config='RelWithDebInfo'
  51. local -r -a _valid_configs=(Debug RelWithDebInfo Release MinSizeRel)
  52. local -i codesign=0
  53. local -i analyze=0
  54. local -a args
  55. while (( # )) {
  56. case ${1} {
  57. -t|--target|-c|--config)
  58. if (( # == 1 )) || [[ ${2:0:1} == '-' ]] {
  59. log_error "Missing value for option %B${1}%b"
  60. exit 2
  61. }
  62. ;;
  63. }
  64. case ${1} {
  65. --) shift; args+=($@); break ;;
  66. -a|--analyze) analyze=1; shift ;;
  67. -t|--target)
  68. if (( ! ${_valid_targets[(Ie)${2}]} )) {
  69. log_error "Invalid value %B${2}%b for option %B${1}%b"
  70. exit 2
  71. }
  72. target=${2}
  73. shift 2
  74. ;;
  75. -c|--config)
  76. if (( ! ${_valid_configs[(Ie)${2}]} )) {
  77. log_error "Invalid value %B${2}%b for option %B${1}%b"
  78. exit 2
  79. }
  80. config=${2}
  81. shift 2
  82. ;;
  83. -s|--codesign) codesign=1; shift ;;
  84. --debug) debug=1; shift ;;
  85. *) log_error "Unknown option: %B${1}%b"; log_output ${_usage}; exit 2 ;;
  86. }
  87. }
  88. : "${target:="${host_os}-${CPUTYPE}"}"
  89. set -- ${(@)args}
  90. check_${host_os}
  91. setup_ccache
  92. if [[ ${host_os} == ubuntu ]] {
  93. autoload -Uz setup_ubuntu && setup_ubuntu
  94. }
  95. local product_name
  96. read -r product_name <<< "$(jq -r '.name' ${buildspec_file})"
  97. pushd ${project_root}
  98. local -a cmake_args=()
  99. local -a cmake_build_args=(--build)
  100. local -a cmake_install_args=(--install)
  101. if (( debug )) cmake_args+=(--debug-output)
  102. case ${target} {
  103. macos-*)
  104. cmake_args+=(--preset 'macos-ci' -DCMAKE_OSX_ARCHITECTURES:STRING=${target##*-})
  105. typeset -gx NSUnbufferedIO=YES
  106. typeset -gx CODESIGN_IDENT="${CODESIGN_IDENT:--}"
  107. if (( codesign )) && [[ -z ${CODESIGN_TEAM} ]] {
  108. typeset -gx CODESIGN_TEAM="$(print "${CODESIGN_IDENT}" | /usr/bin/sed -En 's/.+\((.+)\)/\1/p')"
  109. }
  110. log_group "Configuring ${product_name}..."
  111. cmake -S ${project_root} ${cmake_args}
  112. log_group "Building ${product_name}..."
  113. run_xcodebuild() {
  114. if (( debug )) {
  115. xcodebuild ${@}
  116. } else {
  117. if [[ ${GITHUB_EVENT_NAME} == push ]] {
  118. xcodebuild ${@} 2>&1 | xcbeautify --renderer terminal
  119. } else {
  120. xcodebuild ${@} 2>&1 | xcbeautify --renderer github-actions
  121. }
  122. }
  123. }
  124. local -a build_args=(
  125. ONLY_ACTIVE_ARCH=NO
  126. -project obs-studio.xcodeproj
  127. -target obs-studio
  128. -destination "generic/platform=macOS,name=Any Mac"
  129. -configuration ${config}
  130. -parallelizeTargets
  131. -hideShellScriptEnvironment
  132. build
  133. )
  134. local -a archive_args=(
  135. ONLY_ACTIVE_ARCH=NO
  136. -project obs-studio.xcodeproj
  137. -scheme obs-studio
  138. -destination "generic/platform=macOS,name=Any Mac"
  139. -archivePath obs-studio.xcarchive
  140. -parallelizeTargets
  141. -hideShellScriptEnvironment
  142. archive
  143. )
  144. local -a export_args=(
  145. -exportArchive
  146. -archivePath obs-studio.xcarchive
  147. -exportOptionsPlist exportOptions.plist
  148. -exportPath ${project_root}/build_macos
  149. )
  150. local -a analyze_args=(
  151. CLANG_ANALYZER_OUTPUT=sarif
  152. CLANG_ANALYZER_OUTPUT_DIR=${project_root}/analytics
  153. -project obs-studio.xcodeproj
  154. -target obs-studio
  155. -destination "generic/platform=macOS,name=Any Mac"
  156. -configuration ${config}
  157. -parallelizeTargets
  158. -hideShellScriptEnvironment
  159. analyze
  160. )
  161. pushd build_macos
  162. if (( analyze )) {
  163. run_xcodebuild ${analyze_args}
  164. } else {
  165. if [[ ${GITHUB_EVENT_NAME} == push && ${GITHUB_REF_NAME} =~ [0-9]+.[0-9]+.[0-9]+(-(rc|beta).+)? ]] {
  166. run_xcodebuild ${archive_args}
  167. run_xcodebuild ${export_args}
  168. } else {
  169. run_xcodebuild ${build_args}
  170. rm -rf OBS.app
  171. mkdir OBS.app
  172. ditto UI/${config}/OBS.app OBS.app
  173. }
  174. }
  175. popd
  176. ;;
  177. ubuntu-*)
  178. local cmake_bin='/usr/bin/cmake'
  179. cmake_args+=(
  180. --preset ubuntu-ci
  181. -DENABLE_BROWSER:BOOL=ON
  182. -DCEF_ROOT_DIR:PATH="${project_root}/.deps/cef_binary_${CEF_VERSION}_${target//ubuntu-/linux_}"
  183. )
  184. cmake_build_args+=(build_${target%%-*} --config ${config} --parallel)
  185. cmake_install_args+=(build_${target%%-*} --prefix ${project_root}/build_${target%%-*}/install/${config})
  186. export CLICOLOR_FORCE=1
  187. log_group "Configuring ${product_name}..."
  188. ${cmake_bin} -S ${project_root} ${cmake_args}
  189. log_group "Building ${product_name}..."
  190. if (( debug )) cmake_build_args+=(--verbose)
  191. ${cmake_bin} ${cmake_build_args}
  192. log_group "Installing ${product_name}..."
  193. if (( debug )) cmake_install_args+=(--verbose)
  194. ${cmake_bin} ${cmake_install_args}
  195. ;;
  196. }
  197. popd
  198. log_group
  199. }
  200. build ${@}