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 -D*) gyp_params+=("$1") ;; 135 *) show_help; exit 2 ;; 136 esac 137 shift 138done 139 140# Set the target architecture and build type. 141gyp_params+=(-Dtarget_arch="$target_arch") 142if [ "$opt_build" = 1 ]; then 143 target=Release 144else 145 target=Debug 146fi 147 148gyp_params+=(-Denable_sslkeylogfile="$sslkeylogfile") 149 150# Do special setup. 151if [ "$fuzz" = 1 ]; then 152 source "$cwd/coreconf/fuzz.sh" 153fi 154nspr_set_flags $sanitizer_flags 155if [ ! -z "$sanitizer_flags" ]; then 156 gyp_params+=(-Dsanitizer_flags="$sanitizer_flags") 157fi 158 159if [ "$msvc" = 1 ]; then 160 source "$cwd/coreconf/msvc.sh" 161fi 162 163# -c = clean first 164if [ "$clean" = 1 -o "$clean_only" = 1 ]; then 165 nspr_clean 166 rm -rf "$cwd/out" 167 rm -rf "$dist_dir" 168 # -cc = only clean, don't build 169 if [ "$clean_only" = 1 ]; then 170 echo "Cleaned" 171 exit 0 172 fi 173fi 174 175# Setup build paths. 176target_dir="$cwd/out/$target" 177mkdir -p "$target_dir" 178dist_dir=$(mkdir -p "$dist_dir"; cd "$dist_dir"; pwd -P) 179gyp_params+=(-Dnss_dist_dir="$dist_dir") 180 181# This saves a canonical representation of arguments that we are passing to gyp 182# or the NSPR build so that we can work out if a rebuild is needed. 183# Caveat: This can fail for arguments that are position-dependent. 184# e.g., "-e 2 -f 1" and "-e 1 -f 2" canonicalize the same. 185check_config() 186{ 187 local newconf="$1".new oldconf="$1" 188 shift 189 mkdir -p $(dirname "$newconf") 190 echo CC="$(Q "$CC")" >"$newconf" 191 echo CCC="$(Q "$CCC")" >>"$newconf" 192 echo CXX="$(Q "$CXX")" >>"$newconf" 193 echo target_arch="$(Q "$target_arch")" >>"$newconf" 194 for i in "$@"; do echo "$i"; done | sort >>"$newconf" 195 196 # Note: The following diff fails if $oldconf isn't there as well, which 197 # happens if we don't have a previous successful build. 198 ! diff -q "$newconf" "$oldconf" >/dev/null 2>&1 199} 200 201gyp_config="$cwd/out/gyp_config" 202nspr_config="$cwd/out/$target/nspr_config" 203 204# Now check what needs to be rebuilt. 205# If we don't have a build directory make sure that we rebuild. 206if [ ! -d "$target_dir" ]; then 207 rebuild_nspr=1 208 rebuild_gyp=1 209elif [ ! -d "$dist_dir/$target" ]; then 210 rebuild_nspr=1 211fi 212 213if check_config "$nspr_config" \ 214 nspr_cflags="$(Q "$nspr_cflags")" \ 215 nspr_cxxflags="$(Q "$nspr_cxxflags")" \ 216 nspr_ldflags="$(Q "$nspr_ldflags")"; then 217 rebuild_nspr=1 218fi 219 220if check_config "$gyp_config" "$(Q "${gyp_params[@]}")"; then 221 rebuild_gyp=1 222fi 223 224# Save the chosen target. 225echo "$target" > "$dist_dir/latest" 226for i in "${all_args[@]}"; do echo "$i"; done > "$argsfile" 227 228# Build. 229# NSPR. 230if [[ "$rebuild_nspr" = 1 && "$no_local_nspr" = 0 ]]; then 231 nspr_clean 232 nspr_build 233 mv -f "$nspr_config.new" "$nspr_config" 234fi 235 236if [ "$exit_after_nspr" = 1 ]; then 237 exit 0 238fi 239 240# gyp. 241if [ "$rebuild_gyp" = 1 ]; then 242 if ! hash "$GYP" 2> /dev/null; then 243 echo "Building NSS requires an installation of gyp: https://gyp.gsrc.io/" 1>&2 244 exit 3 245 fi 246 # These extra arguments aren't used in determining whether to rebuild. 247 obj_dir="$dist_dir/$target" 248 gyp_params+=(-Dnss_dist_obj_dir="$obj_dir") 249 if [ "$no_local_nspr" = 0 ]; then 250 set_nspr_path "$obj_dir/include/nspr:$obj_dir/lib" 251 fi 252 253 run_verbose run_scanbuild ${GYP} -f ninja "${gyp_params[@]}" "$cwd/nss.gyp" 254 255 mv -f "$gyp_config.new" "$gyp_config" 256fi 257 258# ninja. 259if hash ninja-build 2>/dev/null; then 260 ninja=ninja-build 261elif hash ninja 2>/dev/null; then 262 ninja=ninja 263else 264 echo "Building NSS requires an installation of ninja: https://ninja-build.org/" 1>&2 265 exit 3 266fi 267run_scanbuild "$ninja" -C "$target_dir" "${ninja_params[@]}" 268