diff options
Diffstat (limited to 'security/nss/build.sh')
-rwxr-xr-x | security/nss/build.sh | 267 |
1 files changed, 138 insertions, 129 deletions
diff --git a/security/nss/build.sh b/security/nss/build.sh index 5af3d3402..2b377dec5 100755 --- a/security/nss/build.sh +++ b/security/nss/build.sh @@ -1,4 +1,10 @@ -#!/bin/bash +#!/usr/bin/env bash +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +################################################################################ +# # This script builds NSS with gyp and ninja. # # This build system is still under development. It does not yet support all @@ -6,41 +12,27 @@ set -e -source $(dirname $0)/coreconf/nspr.sh +cwd=$(cd $(dirname $0); pwd -P) +source "$cwd"/coreconf/nspr.sh +source "$cwd"/coreconf/sanitizers.sh +GYP=${GYP:-gyp} # Usage info -show_help() { -cat << EOF - -Usage: ${0##*/} [-hcgv] [-j <n>] [--test] [--fuzz] [--scan-build[=output]] - [-m32] [--opt|-o] [--asan] [--ubsan] [--sancov[=edge|bb|func]] - [--pprof] [--msan] - -This script builds NSS with gyp and ninja. - -This build system is still under development. It does not yet support all -the features or platforms that NSS supports. - -NSS build tool options: - - -h display this help and exit - -c clean before build - -g force a rebuild of gyp (and NSPR, because why not) - -j <n> run at most <n> concurrent jobs - -v verbose build - -m32 do a 32-bit build on a 64-bit system - --test ignore map files and export everything we have - --fuzz enable fuzzing mode. this always enables test builds - --scan-build run the build with scan-build (scan-build has to be in the path) - --scan-build=/out/path sets the output path for scan-build - --opt|-o do an opt build - --asan do an asan build - --ubsan do an ubsan build - --msan do an msan build - --sancov do sanitize coverage builds - --sancov=func sets coverage to function level for example - --pprof build with gperftool support -EOF +show_help() +{ + cat "$cwd"/help.txt +} + +run_verbose() +{ + if [ "$verbose" = 1 ]; then + echo "$@" + exec 3>&1 + else + exec 3>/dev/null + fi + "$@" 1>&3 2>&3 + exec 3>&- } if [ -n "$CCC" ] && [ -z "$CXX" ]; then @@ -51,154 +43,171 @@ opt_build=0 build_64=0 clean=0 rebuild_gyp=0 +rebuild_nspr=0 target=Debug verbose=0 fuzz=0 +fuzz_tls=0 +fuzz_oss=0 +no_local_nspr=0 +armhf=0 -# parse parameters to store in config -params=$(echo "$*" | perl -pe 's/-c|-v|-g|-j [0-9]*|-h//g' | perl -pe 's/^\s*(.*?)\s*$/\1/') -params=$(echo "$params $CC $CCC" | tr " " "\n" | perl -pe '/^\s*$/d') -params=$(echo "${params[*]}" | sort) - -cwd=$(cd $(dirname $0); pwd -P) -dist_dir="$cwd/../dist" +gyp_params=(--depth="$cwd" --generator-output=".") +nspr_params=() +ninja_params=() # try to guess sensible defaults -arch=$(python "$cwd/coreconf/detect_host_arch.py") +arch=$(python "$cwd"/coreconf/detect_host_arch.py) if [ "$arch" = "x64" -o "$arch" = "aarch64" ]; then build_64=1 +elif [ "$arch" = "arm" ]; then + armhf=1 fi -gyp_params=() -ninja_params=() -scanbuild=() - -enable_fuzz() -{ - fuzz=1 - nspr_sanitizer asan - nspr_sanitizer ubsan - nspr_sanitizer sancov edge - gyp_params+=(-Duse_asan=1) - gyp_params+=(-Duse_ubsan=1) - gyp_params+=(-Duse_sancov=edge) - - # Adding debug symbols even for opt builds. - nspr_opt+=(--enable-debug-symbols) -} - # parse command line arguments while [ $# -gt 0 ]; do case $1 in -c) clean=1 ;; - -g) rebuild_gyp=1 ;; + --gyp|-g) rebuild_gyp=1 ;; + --nspr) nspr_clean; rebuild_nspr=1 ;; -j) ninja_params+=(-j "$2"); shift ;; -v) ninja_params+=(-v); verbose=1 ;; --test) gyp_params+=(-Dtest_build=1) ;; - --fuzz) gyp_params+=(-Dtest_build=1 -Dfuzz=1); enable_fuzz ;; - --scan-build) scanbuild=(scan-build) ;; - --scan-build=?*) scanbuild=(scan-build -o "${1#*=}") ;; + --fuzz) fuzz=1 ;; + --fuzz=oss) fuzz=1; fuzz_oss=1 ;; + --fuzz=tls) fuzz=1; fuzz_tls=1 ;; + --scan-build) enable_scanbuild ;; + --scan-build=?*) enable_scanbuild "${1#*=}" ;; --opt|-o) opt_build=1 ;; -m32|--m32) build_64=0 ;; - --asan) gyp_params+=(-Duse_asan=1); nspr_sanitizer asan ;; - --ubsan) gyp_params+=(-Duse_ubsan=1); nspr_sanitizer ubsan ;; - --sancov) gyp_params+=(-Duse_sancov=edge); nspr_sanitizer sancov edge ;; - --sancov=?*) gyp_params+=(-Duse_sancov="${1#*=}"); nspr_sanitizer sancov "${1#*=}" ;; + --asan) enable_sanitizer asan ;; + --msan) enable_sanitizer msan ;; + --ubsan) enable_ubsan ;; + --ubsan=?*) enable_ubsan "${1#*=}" ;; + --sancov) enable_sancov ;; + --sancov=?*) enable_sancov "${1#*=}" ;; --pprof) gyp_params+=(-Duse_pprof=1) ;; - --msan) gyp_params+=(-Duse_msan=1); nspr_sanitizer msan ;; - *) show_help; exit ;; + --ct-verif) gyp_params+=(-Dct_verif=1) ;; + --disable-tests) gyp_params+=(-Ddisable_tests=1) ;; + --no-zdefs) gyp_params+=(-Dno_zdefs=1) ;; + --system-sqlite) gyp_params+=(-Duse_system_sqlite=1) ;; + --with-nspr=?*) set_nspr_path "${1#*=}"; no_local_nspr=1 ;; + --system-nspr) set_nspr_path "/usr/include/nspr/:"; no_local_nspr=1 ;; + --enable-libpkix) gyp_params+=(-Ddisable_libpkix=0) ;; + *) show_help; exit 2 ;; esac shift done -if [ "$opt_build" = "1" ]; then +if [ "$opt_build" = 1 ]; then target=Release - nspr_opt+=(--disable-debug --enable-optimize) else target=Debug fi -if [ "$build_64" == "1" ]; then - nspr_opt+=(--enable-64bit) -else +if [ "$build_64" = 1 ]; then + nspr_params+=(--enable-64bit) +elif [ ! "$armhf" = 1 ]; then gyp_params+=(-Dtarget_arch=ia32) - nspr_opt+=(--enable-x32) +fi +if [ "$fuzz" = 1 ]; then + source "$cwd"/coreconf/fuzz.sh fi -# clone fuzzing stuff -if [ "$fuzz" = "1" ]; then - [ $verbose = 0 ] && exec 3>/dev/null || exec 3>&1 +# set paths +target_dir="$cwd"/out/$target +mkdir -p "$target_dir" +dist_dir="$cwd"/../dist +dist_dir=$(mkdir -p "$dist_dir"; cd "$dist_dir"; pwd -P) +gyp_params+=(-Dnss_dist_dir="$dist_dir") - echo "[1/2] Cloning libFuzzer files ..." - $cwd/fuzz/clone_libfuzzer.sh 1>&3 2>&3 +# -c = clean first +if [ "$clean" = 1 ]; then + nspr_clean + rm -rf "$cwd"/out + rm -rf "$dist_dir" +fi - echo "[2/2] Cloning fuzzing corpus ..." - $cwd/fuzz/clone_corpus.sh 1>&3 2>&3 +# This saves a canonical representation of arguments that we are passing to gyp +# or the NSPR build so that we can work out if a rebuild is needed. +# Caveat: This can fail for arguments that are position-dependent. +# e.g., "-e 2 -f 1" and "-e 1 -f 2" canonicalize the same. +check_config() +{ + local newconf="$1".new oldconf="$1" + shift + mkdir -p $(dirname "$newconf") + echo CC="$CC" >"$newconf" + echo CCC="$CCC" >>"$newconf" + echo CXX="$CXX" >>"$newconf" + for i in "$@"; do echo $i; done | sort >>"$newconf" + + # Note: The following diff fails if $oldconf isn't there as well, which + # happens if we don't have a previous successful build. + ! diff -q "$newconf" "$oldconf" >/dev/null 2>&1 +} - exec 3>&- -fi +gyp_config="$cwd"/out/gyp_config +nspr_config="$cwd"/out/$target/nspr_config -# check if we have to rebuild gyp -if [ "$params" != "$(cat $cwd/out/config 2>/dev/null)" -o "$rebuild_gyp" == 1 -o "$clean" == 1 ]; then +# If we don't have a build directory make sure that we rebuild. +if [ ! -d "$target_dir" ]; then + rebuild_nspr=1 rebuild_gyp=1 - rm -rf "$cwd/../nspr/$target" # force NSPR to rebuild +elif [ ! -d "$dist_dir"/$target ]; then + rebuild_nspr=1 fi -# set paths -target_dir="$cwd/out/$target" +# Update NSPR ${C,CXX,LD}FLAGS. +nspr_set_flags $sanitizer_flags -# get the realpath of $dist_dir -dist_dir=$(mkdir -p $dist_dir; cd $dist_dir; pwd -P) +if check_config "$nspr_config" "${nspr_params[@]}" \ + nspr_cflags="$nspr_cflags" \ + nspr_cxxflags="$nspr_cxxflags" \ + nspr_ldflags="$nspr_ldflags"; then + rebuild_nspr=1 +fi -# get object directory -obj_dir="$dist_dir/$target" -gyp_params+=(-Dnss_dist_dir=$dist_dir) -gyp_params+=(-Dnss_dist_obj_dir=$obj_dir) -gyp_params+=(-Dnspr_lib_dir=$obj_dir/lib) -gyp_params+=(-Dnspr_include_dir=$obj_dir/include/nspr) +# Forward sanitizer flags. +if [ ! -z "$sanitizer_flags" ]; then + gyp_params+=(-Dsanitizer_flags="$sanitizer_flags") +fi -# -c = clean first -if [ "$clean" = 1 ]; then - rm -rf "$cwd/out" - rm -rf "$cwd/../nspr/$target" - rm -rf "$dist_dir" +if check_config "$gyp_config" "${gyp_params[@]}"; then + rebuild_gyp=1 fi # save the chosen target -mkdir -p $dist_dir -echo $target > $dist_dir/latest +mkdir -p "$dist_dir" +echo $target > "$dist_dir"/latest -# pass on CC and CCC -if [ "${#scanbuild[@]}" -gt 0 ]; then - if [ -n "$CC" ]; then - scanbuild+=(--use-cc="$CC") +if [[ "$rebuild_nspr" = 1 && "$no_local_nspr" = 0 ]]; then + nspr_build "${nspr_params[@]}" + mv -f "$nspr_config".new "$nspr_config" +fi +if [ "$rebuild_gyp" = 1 ]; then + if ! hash ${GYP} 2> /dev/null; then + echo "Please install gyp" 1>&2 + exit 1 fi - if [ -n "$CCC" ]; then - scanbuild+=(--use-c++="$CCC") + # These extra arguments aren't used in determining whether to rebuild. + obj_dir="$dist_dir"/$target + gyp_params+=(-Dnss_dist_obj_dir=$obj_dir) + if [ "$no_local_nspr" = 0 ]; then + set_nspr_path "$obj_dir/include/nspr:$obj_dir/lib" fi - fi - -# These steps can take a while, so don't overdo them. -# Force a redo with -g. -if [ "$rebuild_gyp" = 1 -o ! -d "$target_dir" ]; then - build_nspr $verbose - # Run gyp. - [ $verbose = 1 ] && set -v -x - "${scanbuild[@]}" gyp -f ninja "${gyp_params[@]}" --depth="$cwd" \ - --generator-output="." "$cwd/nss.gyp" - [ $verbose = 1 ] && set +v +x + run_verbose run_scanbuild ${GYP} -f ninja "${gyp_params[@]}" "$cwd"/nss.gyp - # Store used parameters for next run. - echo "$params" > "$cwd/out/config" + mv -f "$gyp_config".new "$gyp_config" fi # Run ninja. -if which ninja >/dev/null 2>&1; then - ninja=(ninja) -elif which ninja-build >/dev/null 2>&1; then - ninja=(ninja-build) +if hash ninja 2>/dev/null; then + ninja=ninja +elif hash ninja-build 2>/dev/null; then + ninja=ninja-build else echo "Please install ninja" 1>&2 exit 1 fi -"${scanbuild[@]}" $ninja -C "$target_dir" "${ninja_params[@]}" +run_scanbuild $ninja -C "$target_dir" "${ninja_params[@]}" |