build.sh 7.83 KB
Newer Older
1
#!/usr/bin/env bash
2 3 4 5 6 7
#
# 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/.
################################################################################
#
8 9 10 11
# 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.
12

13 14
set -e

15
cwd=$(cd $(dirname $0); pwd -P)
16 17 18 19
dist_dir="$cwd/../dist"
argsfile="$dist_dir/build_args"
source "$cwd/coreconf/nspr.sh"
source "$cwd/coreconf/sanitizers.sh"
20
GYP=${GYP:-gyp}
21

22
# Usage info
23 24
show_help()
{
25
    cat "$cwd/help.txt"
26 27
}

28 29 30 31 32 33 34 35 36 37 38 39
run_verbose()
{
    if [ "$verbose" = 1 ]; then
        echo "$@"
        exec 3>&1
    else
        exec 3>/dev/null
    fi
    "$@" 1>&3 2>&3
    exec 3>&-
}

40 41 42 43 44 45 46 47
# The prehistoric bash on Mac doesn't support @Q quoting.
# The consequences aren't that serious, unless there are odd arrangements of spaces.
if /usr/bin/env bash -c 'x=1;echo "${x@Q}"' >/dev/null 2>&1; then
    Q() { echo "${@@Q}"; }
else
    Q() { echo "$@"; }
fi

48
if [ -n "$CCC" ] && [ -z "$CXX" ]; then
49 50 51
    export CXX="$CCC"
fi

52 53
opt_build=0
build_64=0
54 55
clean=0
rebuild_gyp=0
56
rebuild_nspr=0
57 58 59
build_nspr_tests=0
run_nspr_tests=0
exit_after_nspr=0
60
target=Debug
61
verbose=0
62
fuzz=0
63 64
fuzz_tls=0
fuzz_oss=0
65
no_local_nspr=0
66
sslkeylogfile=1
67 68 69

gyp_params=(--depth="$cwd" --generator-output=".")
ninja_params=()
70

71
# Assume that the target architecture is the same as the host by default.
72
host_arch=$(python "$cwd/coreconf/detect_host_arch.py")
73 74 75 76 77 78
target_arch=$host_arch

# Assume that MSVC is wanted if this is running on windows.
platform=$(uname -s)
if [ "${platform%-*}" = "MINGW32_NT" -o "${platform%-*}" = "MINGW64_NT" ]; then
    msvc=1
79 80
fi

81
# Parse command line arguments.
82
all_args=("$@")
83
while [ $# -gt 0 ]; do
84
    case "$1" in
85 86 87 88 89 90 91 92
        --rebuild)
            if [[ ! -e "$argsfile" ]]; then
                echo "Unable to rebuild" 1>&2
                exit 2
            fi
            IFS=$'\r\n' GLOBIGNORE='*' command eval  'previous_args=($(<"$argsfile"))'
            exec /usr/bin/env bash -c "$(Q "$0")"' "$@"' "$0" "${previous_args[@]}"
            ;;
93
        -c) clean=1 ;;
94
        -cc) clean_only=1 ;;
95
        -v) ninja_params+=(-v); verbose=1 ;;
96 97 98 99 100 101 102 103 104
        -j) ninja_params+=(-j "$2"); shift ;;
        --gyp|-g) rebuild_gyp=1 ;;
        --opt|-o) opt_build=1 ;;
        -m32|--m32) target_arch=ia32; echo 'Warning: use -t instead of -m32' 1>&2 ;;
        -t|--target) target_arch="$2"; shift ;;
        --target=*) target_arch="${1#*=}" ;;
        --clang) export CC=clang; export CCC=clang++; export CXX=clang++; msvc=0 ;;
        --gcc) export CC=gcc; export CCC=g++; export CXX=g++; msvc=0 ;;
        --msvc) msvc=1 ;;
105 106
        --scan-build) enable_scanbuild  ;;
        --scan-build=?*) enable_scanbuild "${1#*=}" ;;
107 108
        --disable-tests) gyp_params+=(-Ddisable_tests=1) ;;
        --pprof) gyp_params+=(-Duse_pprof=1) ;;
109 110 111 112
        --asan) enable_sanitizer asan ;;
        --msan) enable_sanitizer msan ;;
        --ubsan) enable_ubsan ;;
        --ubsan=?*) enable_ubsan "${1#*=}" ;;
113 114 115
        --fuzz) fuzz=1 ;;
        --fuzz=oss) fuzz=1; fuzz_oss=1 ;;
        --fuzz=tls) fuzz=1; fuzz_tls=1 ;;
116 117
        --sancov) enable_sancov; gyp_params+=(-Dcoverage=1) ;;
        --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 122
        --ct-verif) gyp_params+=(-Dct_verif=1) ;;
        --nspr) nspr_clean; rebuild_nspr=1 ;;
123 124 125
        --nspr-test-build) build_nspr_tests=1 ;;
        --nspr-test-run) run_nspr_tests=1 ;;
        --nspr-only) exit_after_nspr=1 ;;
126 127
        --with-nspr=?*) set_nspr_path "${1#*=}"; no_local_nspr=1 ;;
        --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 138 139 140
    esac
    shift
done

141 142
# Set the target architecture and build type.
gyp_params+=(-Dtarget_arch="$target_arch")
143
if [ "$opt_build" = 1 ]; then
144
    target=Release
145
else
146
    target=Debug
147
fi
148

149 150
gyp_params+=(-Denable_sslkeylogfile="$sslkeylogfile")

151
# Do special setup.
152
if [ "$fuzz" = 1 ]; then
153
    source "$cwd/coreconf/fuzz.sh"
154
fi
155 156 157 158
nspr_set_flags $sanitizer_flags
if [ ! -z "$sanitizer_flags" ]; then
    gyp_params+=(-Dsanitizer_flags="$sanitizer_flags")
fi
159

160
if [ "$msvc" = 1 ]; then
161
    source "$cwd/coreconf/msvc.sh"
162 163
fi

164
# -c = clean first
165
if [ "$clean" = 1 -o "$clean_only" = 1 ]; then
166
    nspr_clean
167
    rm -rf "$cwd/out"
168
    rm -rf "$dist_dir"
169 170 171 172 173
    # -cc = only clean, don't build
    if [ "$clean_only" = 1 ]; then
        echo "Cleaned"
        exit 0
    fi
174 175
fi

176 177 178 179 180 181
# Setup build paths.
target_dir="$cwd/out/$target"
mkdir -p "$target_dir"
dist_dir=$(mkdir -p "$dist_dir"; cd "$dist_dir"; pwd -P)
gyp_params+=(-Dnss_dist_dir="$dist_dir")

182 183
# 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.
184 185 186
# 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()
187
{
188
    local newconf="$1".new oldconf="$1"
189
    shift
190
    mkdir -p $(dirname "$newconf")
191 192 193 194 195
    echo CC="$(Q "$CC")" >"$newconf"
    echo CCC="$(Q "$CCC")" >>"$newconf"
    echo CXX="$(Q "$CXX")" >>"$newconf"
    echo target_arch="$(Q "$target_arch")" >>"$newconf"
    for i in "$@"; do echo "$i"; done | sort >>"$newconf"
196 197 198 199

    # 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
200 201
}

202 203
gyp_config="$cwd/out/gyp_config"
nspr_config="$cwd/out/$target/nspr_config"
204

205
# Now check what needs to be rebuilt.
206 207 208 209
# If we don't have a build directory make sure that we rebuild.
if [ ! -d "$target_dir" ]; then
    rebuild_nspr=1
    rebuild_gyp=1
210
elif [ ! -d "$dist_dir/$target" ]; then
211
    rebuild_nspr=1
212 213
fi

214
if check_config "$nspr_config" \
215 216 217
                 nspr_cflags="$(Q "$nspr_cflags")" \
                 nspr_cxxflags="$(Q "$nspr_cxxflags")" \
                 nspr_ldflags="$(Q "$nspr_ldflags")"; then
218 219 220
    rebuild_nspr=1
fi

221
if check_config "$gyp_config" "$(Q "${gyp_params[@]}")"; then
222 223 224
    rebuild_gyp=1
fi

225
# Save the chosen target.
226 227
echo "$target" > "$dist_dir/latest"
for i in "${all_args[@]}"; do echo "$i"; done > "$argsfile"
228

229 230
# Build.
# NSPR.
231
if [[ "$rebuild_nspr" = 1 && "$no_local_nspr" = 0 ]]; then
232
    nspr_clean
233
    nspr_build
234
    mv -f "$nspr_config.new" "$nspr_config"
235
fi
236 237 238 239 240

if [ "$exit_after_nspr" = 1 ]; then
  exit 0
fi

241
# gyp.
242
if [ "$rebuild_gyp" = 1 ]; then
243 244 245
    if ! hash "$GYP" 2> /dev/null; then
        echo "Building NSS requires an installation of gyp: https://gyp.gsrc.io/" 1>&2
        exit 3
246
    fi
247
    # These extra arguments aren't used in determining whether to rebuild.
248 249
    obj_dir="$dist_dir/$target"
    gyp_params+=(-Dnss_dist_obj_dir="$obj_dir")
250 251 252
    if [ "$no_local_nspr" = 0 ]; then
        set_nspr_path "$obj_dir/include/nspr:$obj_dir/lib"
    fi
253

254
    run_verbose run_scanbuild ${GYP} -f ninja "${gyp_params[@]}" "$cwd/nss.gyp"
255

256
    mv -f "$gyp_config.new" "$gyp_config"
257
fi
258

259 260
# ninja.
if hash ninja-build 2>/dev/null; then
261
    ninja=ninja-build
262 263
elif hash ninja 2>/dev/null; then
    ninja=ninja
264
else
265 266
    echo "Building NSS requires an installation of ninja: https://ninja-build.org/" 1>&2
    exit 3
267
fi
268
run_scanbuild "$ninja" -C "$target_dir" "${ninja_params[@]}"