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