build.sh (9183B)
1 #!/usr/bin/env bash 2 # 3 # This Source Code Form is subject to the terms of the Mozilla Public 4 # License, v. 2.0. If a copy of the MPL was not distributed with this 5 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 ################################################################################ 7 # 8 # This script builds NSS with gyp and ninja. 9 # 10 # This build system is still under development. It does not yet support all 11 # the features or platforms that NSS supports. 12 13 set -e 14 15 cwd=$(cd $(dirname $0); pwd -P) 16 dist_dir="$cwd/../dist" 17 argsfile="$dist_dir/build_args" 18 source "$cwd/coreconf/nspr.sh" 19 source "$cwd/coreconf/sanitizers.sh" 20 GYP=${GYP:-gyp} 21 22 # Usage info 23 show_help() 24 { 25 cat "$cwd/help.txt" 26 } 27 28 run_verbose() 29 { 30 if [ "$verbose" = 1 ]; then 31 echo "$@" 32 exec 3>&1 33 "$@" 1>&3 2>&3 34 exec 3>&- 35 else 36 "$@" >/dev/null 37 fi 38 } 39 40 # The prehistoric bash on Mac doesn't support @Q quoting. 41 # The consequences aren't that serious, unless there are odd arrangements of spaces. 42 if /usr/bin/env bash -c 'x=1;echo "${x@Q}"' >/dev/null 2>&1; then 43 Q() { echo "${@@Q}"; } 44 else 45 Q() { echo "$@"; } 46 fi 47 48 if [ -n "$CCC" ] && [ -z "$CXX" ]; then 49 export CXX="$CCC" 50 fi 51 52 opt_build=0 53 build_64=0 54 clean=0 55 rebuild_gyp=0 56 rebuild_nspr=0 57 build_nspr_tests=0 58 run_nspr_tests=0 59 exit_after_nspr=0 60 target=Debug 61 verbose=0 62 fuzz=0 63 fuzz_tls=0 64 fuzz_oss=0 65 no_local_nspr=0 66 sslkeylogfile=1 67 68 gyp_params=(--depth="$cwd" --generator-output=".") 69 ninja_params=() 70 71 # Assume that MSVC is wanted if this is running on windows. 72 platform=$(uname -s) 73 if [ "${platform%-*}" = "MINGW32_NT" -o "${platform%-*}" = "MINGW64_NT" -o "${platform%%-*}" = "MSYS_NT" ]; then 74 msvc=1 75 fi 76 77 # Parse command line arguments. 78 all_args=("$@") 79 while [ $# -gt 0 ]; do 80 case "$1" in 81 --rebuild) 82 if [[ ! -e "$argsfile" ]]; then 83 echo "Unable to rebuild" 1>&2 84 exit 2 85 fi 86 IFS=$'\r\n' GLOBIGNORE='*' command eval 'previous_args=($(<"$argsfile"))' 87 exec /usr/bin/env bash -c "$(Q "$0")"' "$@"' "$0" "${previous_args[@]}" 88 ;; 89 -c) clean=1 ;; 90 -cc) clean_only=1 ;; 91 -v) ninja_params+=(-v); verbose=1 ;; 92 -j) ninja_params+=(-j "$2"); shift ;; 93 --gyp|-g) rebuild_gyp=1 ;; 94 --opt|-o) opt_build=1 ;; 95 -m32|--m32) target_arch=ia32; echo 'Warning: use -t instead of -m32' 1>&2 ;; 96 -t|--target) target_arch="$2"; shift ;; 97 --target=*) target_arch="${1#*=}" ;; 98 --build-tools-cc=*) build_tools_cc="${1#*=}" ;; 99 --clang) export CC=clang; export CCC=clang++; export CXX=clang++; msvc=0 ;; 100 --gcc) export CC=gcc; export CCC=g++; export CXX=g++; msvc=0 ;; 101 --msvc) msvc=1 ;; 102 --scan-build) enable_scanbuild ;; 103 --scan-build=?*) enable_scanbuild "${1#*=}" ;; 104 --disable-tests) gyp_params+=(-Ddisable_tests=1) ;; 105 --pprof) gyp_params+=(-Duse_pprof=1) ;; 106 --asan) enable_sanitizer asan ;; 107 --msan) enable_sanitizer msan ;; 108 --tsan) enable_sanitizer tsan ;; 109 --sourcecov) enable_sourcecov ;; 110 --ubsan) enable_ubsan ;; 111 --ubsan=?*) enable_ubsan "${1#*=}" ;; 112 --fuzz) fuzz=1 ;; 113 --fuzz=oss) fuzz=1; fuzz_oss=1 ;; 114 --fuzz=tls) fuzz=1; fuzz_tls=1 ;; 115 --sancov) enable_sancov; gyp_params+=(-Dcoverage=1) ;; 116 --sancov=?*) enable_sancov "${1#*=}"; gyp_params+=(-Dcoverage=1) ;; 117 --emit-llvm) gyp_params+=(-Demit_llvm=1 -Dsign_libs=0) ;; 118 --no-zdefs) gyp_params+=(-Dno_zdefs=1) ;; 119 --static) gyp_params+=(-Dstatic_libs=1) ;; 120 --ct-verif) gyp_params+=(-Dct_verif=1) ;; 121 --nspr) nspr_clean; rebuild_nspr=1 ;; 122 --nspr-test-build) build_nspr_tests=1 ;; 123 --nspr-test-run) run_nspr_tests=1 ;; 124 --nspr-only) exit_after_nspr=1 ;; 125 --with-nspr=?*) set_nspr_path "${1#*=}"; no_local_nspr=1 ;; 126 --system-nspr) set_nspr_path "/usr/include/nspr/:"; no_local_nspr=1 ;; 127 --system-sqlite) gyp_params+=(-Duse_system_sqlite=1) ;; 128 --enable-fips) gyp_params+=(-Ddisable_fips=0) ;; 129 --fips-module-id) gyp_params+=(-Dfips_module_id="$2"); shift ;; 130 --fips-module-id=?*) gyp_params+=(-Dfips_module_id="${1#*=}") ;; 131 --enable-libpkix) gyp_params+=(-Ddisable_libpkix=0) ;; 132 --mozpkix-only) gyp_params+=(-Dmozpkix_only=1 -Ddisable_tests=1 -Dsign_libs=0) ;; 133 --disable-keylog) sslkeylogfile=0 ;; 134 --enable-legacy-db) gyp_params+=(-Ddisable_dbm=0) ;; 135 --mozilla-central) gyp_params+=(-Dmozilla_central=1) ;; 136 --python) python="$2"; shift ;; 137 --python=*) python="${1#*=}" ;; 138 -D*) gyp_params+=("$1") ;; 139 *) show_help; exit 2 ;; 140 esac 141 shift 142 done 143 144 if [ "$opt_build" = 1 ] && [ "$fuzz" = 1 ]; then 145 echo "Specifiying --opt with --fuzz is not supported." >&2 146 exit 1 147 fi 148 149 if [ -n "${sanitizers["tsan"]:-}" ] && ([ "$CC" = "gcc" ] || 150 [ "$CCC" = "g++" ] || 151 [ "$CXX" = "g++" ]); then 152 echo "Specifying --tsan with gcc results in false positives whilst building NSPR." >&2 153 exit 1 154 fi 155 156 if [ -n "$python" ]; then 157 gyp_params+=(-Dpython="$python") 158 fi 159 160 if [ -z "$target_arch" ]; then 161 # Assume that the target architecture is the same as the host by default. 162 host_arch=$(${python:-python3} "$cwd/coreconf/detect_host_arch.py") 163 target_arch=$host_arch 164 fi 165 166 # Set the target architecture and build type. 167 gyp_params+=(-Dtarget_arch="$target_arch") 168 if [ "$opt_build" = 1 ]; then 169 target=Release 170 else 171 target=Debug 172 fi 173 174 # When cross-compiling, system zlib for the target architecture may not be available 175 if [[ -n "$CC" && -n "$build_tools_cc" && "$CC" != "$build_tools_cc" ]]; then 176 gyp_params+=(-Duse_system_zlib=0 -Dsign_libs=0) 177 fi 178 179 gyp_params+=(-Denable_sslkeylogfile="$sslkeylogfile") 180 181 # Do special setup. 182 if [ "$fuzz" = 1 ]; then 183 source "$cwd/coreconf/fuzz.sh" 184 fi 185 nspr_set_flags $sanitizer_flags 186 if [ ! -z "$sanitizer_flags" ]; then 187 gyp_params+=(-Dsanitizer_flags="$sanitizer_flags") 188 fi 189 190 if [ "$msvc" = 1 ]; then 191 source "$cwd/coreconf/msvc.sh" 192 fi 193 194 # -c = clean first 195 if [ "$clean" = 1 -o "$clean_only" = 1 ]; then 196 nspr_clean 197 rm -rf "$cwd/out" 198 rm -rf "$dist_dir" 199 # -cc = only clean, don't build 200 if [ "$clean_only" = 1 ]; then 201 echo "Cleaned" 202 exit 0 203 fi 204 fi 205 206 # Setup build paths. 207 target_dir="$cwd/out/$target" 208 mkdir -p "$target_dir" 209 dist_dir=$(mkdir -p "$dist_dir"; cd "$dist_dir"; pwd -P) 210 gyp_params+=(-Dnss_dist_dir="$dist_dir") 211 212 # This saves a canonical representation of arguments that we are passing to gyp 213 # or the NSPR build so that we can work out if a rebuild is needed. 214 # Caveat: This can fail for arguments that are position-dependent. 215 # e.g., "-e 2 -f 1" and "-e 1 -f 2" canonicalize the same. 216 check_config() 217 { 218 local newconf="$1".new oldconf="$1" 219 shift 220 mkdir -p $(dirname "$newconf") 221 echo CC="$(Q "$CC")" >"$newconf" 222 echo CCC="$(Q "$CCC")" >>"$newconf" 223 echo CXX="$(Q "$CXX")" >>"$newconf" 224 echo target_arch="$(Q "$target_arch")" >>"$newconf" 225 for i in "$@"; do echo "$i"; done | sort >>"$newconf" 226 227 # Note: The following diff fails if $oldconf isn't there as well, which 228 # happens if we don't have a previous successful build. 229 ! diff -q "$newconf" "$oldconf" >/dev/null 2>&1 230 } 231 232 gyp_config="$cwd/out/gyp_config" 233 nspr_config="$cwd/out/$target/nspr_config" 234 235 # Now check what needs to be rebuilt. 236 # If we don't have a build directory make sure that we rebuild. 237 if [ ! -d "$target_dir" ]; then 238 rebuild_nspr=1 239 rebuild_gyp=1 240 elif [ ! -d "$dist_dir/$target" ]; then 241 rebuild_nspr=1 242 fi 243 244 if check_config "$nspr_config" \ 245 nspr_cflags="$(Q "$nspr_cflags")" \ 246 nspr_cxxflags="$(Q "$nspr_cxxflags")" \ 247 nspr_ldflags="$(Q "$nspr_ldflags")"; then 248 rebuild_nspr=1 249 fi 250 251 if check_config "$gyp_config" "$(Q "${gyp_params[@]}")"; then 252 rebuild_gyp=1 253 fi 254 255 # Save the chosen target. 256 echo "$target" > "$dist_dir/latest" 257 for i in "${all_args[@]}"; do echo "$i"; done > "$argsfile" 258 259 # Build. 260 # NSPR. 261 if [[ "$rebuild_nspr" = 1 && "$no_local_nspr" = 0 ]]; then 262 nspr_clean 263 nspr_build 264 mv -f "$nspr_config.new" "$nspr_config" 265 fi 266 267 if [ "$exit_after_nspr" = 1 ]; then 268 exit 0 269 fi 270 271 # gyp. 272 if [ "$rebuild_gyp" = 1 ]; then 273 if ! hash "$GYP" 2> /dev/null; then 274 echo "Building NSS requires an installation of gyp: https://gyp.gsrc.io/" 1>&2 275 exit 3 276 fi 277 # These extra arguments aren't used in determining whether to rebuild. 278 obj_dir="$dist_dir/$target" 279 gyp_params+=(-Dnss_dist_obj_dir="$obj_dir") 280 if [ "$no_local_nspr" = 0 ]; then 281 set_nspr_path "$obj_dir/include/nspr:$obj_dir/lib" 282 fi 283 284 run_verbose run_scanbuild ${GYP} -f ninja "${gyp_params[@]}" "$cwd/nss.gyp" 285 286 mv -f "$gyp_config.new" "$gyp_config" 287 fi 288 289 # ninja. 290 if hash ninja-build 2>/dev/null; then 291 ninja=ninja-build 292 elif hash ninja 2>/dev/null; then 293 ninja=ninja 294 else 295 echo "Building NSS requires an installation of ninja: https://ninja-build.org/" 1>&2 296 exit 3 297 fi 298 run_scanbuild "$ninja" -C "$target_dir" "${ninja_params[@]}"