tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

rust.mk (26434B)


      1 # This Source Code Form is subject to the terms of the Mozilla Public
      2 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 # You can obtain one at http://mozilla.org/MPL/2.0/.
      4 
      5 # /!\ In this file, we export multiple variables globally via make rather than
      6 # in recipes via the `env` command to avoid round-trips to msys on Windows, which
      7 # tend to break environment variable values in interesting ways.
      8 
      9 # /!\ Avoid the use of double-quotes in this file, so that the cargo
     10 # commands can be executed directly by make, without doing a round-trip
     11 # through a shell.
     12 
     13 cargo_host_flag := --target=$(RUST_HOST_TARGET)
     14 cargo_target_flag := --target=$(RUST_TARGET)
     15 
     16 # Permit users to pass flags to cargo from their mozconfigs (e.g. --color=always).
     17 cargo_build_flags = $(CARGOFLAGS)
     18 ifndef MOZ_DEBUG_RUST
     19 cargo_build_flags += --release
     20 endif
     21 
     22 # The Spidermonkey library can be built from a package tarball outside the
     23 # tree, so we want to let Cargo create lock files in this case. When built
     24 # within a tree, the Rust dependencies have been vendored in so Cargo won't
     25 # touch the lock file.
     26 ifndef JS_STANDALONE
     27 cargo_build_flags += --frozen
     28 endif
     29 
     30 cargo_build_flags += --manifest-path $(CARGO_FILE)
     31 ifdef BUILD_VERBOSE_LOG
     32 cargo_build_flags += -vv
     33 endif
     34 
     35 ifneq (,$(USE_CARGO_JSON_MESSAGE_FORMAT))
     36 cargo_build_flags += --message-format=json
     37 endif
     38 
     39 # Enable color output if original stdout was a TTY and color settings
     40 # aren't already present. This essentially restores the default behavior
     41 # of cargo when running via `mach`.
     42 ifdef MACH_STDOUT_ISATTY
     43 ifeq (,$(findstring --color,$(cargo_build_flags)))
     44 ifdef NO_ANSI
     45 cargo_build_flags += --color=never
     46 else
     47 cargo_build_flags += --color=always
     48 endif
     49 endif
     50 endif
     51 
     52 # Without -j > 1, make will not pass jobserver info down to cargo. Force
     53 # one job when requested as a special case.
     54 cargo_build_flags += $(filter -j1,$(MAKEFLAGS))
     55 
     56 # We also need to rebuild the rust stdlib so that it's instrumented. Because
     57 # build-std is still pretty experimental, we need to explicitly request
     58 # the panic_abort crate for `panic = "abort"` support.
     59 ifdef MOZ_TSAN
     60 cargo_build_flags += -Zbuild-std=std,panic_abort
     61 RUSTFLAGS += -Zsanitizer=thread
     62 endif
     63 
     64 rustflags_sancov =
     65 ifndef MOZ_TSAN
     66 ifndef FUZZING_JS_FUZZILLI
     67 ifdef LIBFUZZER
     68 # These options should match what is implicitly enabled for `clang -fsanitize=fuzzer`
     69 #   here: https://github.com/llvm/llvm-project/blob/release/13.x/clang/lib/Driver/SanitizerArgs.cpp#L422
     70 #
     71 #  -sanitizer-coverage-inline-8bit-counters      Increments 8-bit counter for every edge.
     72 #  -sanitizer-coverage-level=4                   Enable coverage for all blocks, critical edges, and indirect calls.
     73 #  -sanitizer-coverage-trace-compares            Tracing of CMP and similar instructions.
     74 #  -sanitizer-coverage-pc-table                  Create a static PC table.
     75 #
     76 # In TSan builds, we must not pass any of these, because sanitizer coverage is incompatible with TSan.
     77 rustflags_sancov += -Cpasses=sancov-module -Cllvm-args=-sanitizer-coverage-inline-8bit-counters -Cllvm-args=-sanitizer-coverage-level=4 -Cllvm-args=-sanitizer-coverage-trace-compares -Cllvm-args=-sanitizer-coverage-pc-table
     78 else
     79 ifdef AFLFUZZ
     80 # Use the same flags as afl-cc, specified here:
     81 # https://github.com/AFLplusplus/AFLplusplus/blob/4eaacfb095ac164afaaf9c10b8112f98d8ad7c2a/src/afl-cc.c#L2101
     82 #  -sanitizer-coverage-level=3                   Enable coverage for all blocks, critical edges. Implied by clang as default.
     83 #  -sanitizer-coverage-pc-table                  Create a static PC table.
     84 #  -sanitizer-coverage-trace-pc-guard            Adds guard_variable (uint32_t) to every edge
     85 rustflags_sancov += -Cpasses=sancov-module -Cllvm-args=-sanitizer-coverage-level=3  -Cllvm-args=-sanitizer-coverage-pc-table -Cllvm-args=-sanitizer-coverage-trace-pc-guard
     86 endif
     87 endif
     88 endif
     89 endif
     90 
     91 # These flags are passed via `cargo rustc` and only apply to the final rustc
     92 # invocation (i.e., only the top-level crate, not its dependencies).
     93 cargo_rustc_flags = $(CARGO_RUSTCFLAGS)
     94 ifndef DEVELOPER_OPTIONS
     95 ifndef MOZ_DEBUG_RUST
     96 # Enable link-time optimization for release builds, but not when linking
     97 # gkrust_gtest. And not when doing cross-language LTO.
     98 ifndef MOZ_LTO_RUST_CROSS
     99 # Never enable when sancov is enabled to work around https://github.com/rust-lang/rust/issues/90300.
    100 ifndef rustflags_sancov
    101 # Never enable when coverage is enabled to work around https://github.com/rust-lang/rust/issues/90045.
    102 ifndef MOZ_CODE_COVERAGE
    103 ifeq (,$(findstring gkrust_gtest,$(RUST_LIBRARY_FILE)))
    104 cargo_rustc_flags += -Clto$(if $(filter full,$(MOZ_LTO_RUST_CROSS)),=fat)
    105 endif
    106 # We need -Cembed-bitcode=yes for all crates when using -Clto.
    107 RUSTFLAGS += -Cembed-bitcode=yes
    108 endif
    109 endif
    110 endif
    111 endif
    112 endif
    113 
    114 ifdef CARGO_INCREMENTAL
    115 export CARGO_INCREMENTAL
    116 endif
    117 
    118 rustflags_neon =
    119 ifeq (neon,$(MOZ_FPU))
    120 ifneq (,$(filter thumbv7neon-,$(RUST_TARGET)))
    121 # Enable neon and disable restriction to 16 FPU registers when neon is enabled
    122 # but we're not using a thumbv7neon target, where it's already the default.
    123 # (CPUs with neon have 32 FPU registers available)
    124 rustflags_neon += -C target_feature=+neon,-d16
    125 endif
    126 endif
    127 
    128 rustflags_override = $(MOZ_RUST_DEFAULT_FLAGS) $(rustflags_neon)
    129 
    130 ifdef DEVELOPER_OPTIONS
    131 # By default the Rust compiler will perform a limited kind of ThinLTO on each
    132 # crate. For local builds this additional optimization is not worth the
    133 # increase in compile time so we opt out of it.
    134 rustflags_override += -Clto=off
    135 endif
    136 
    137 ifdef MOZ_USING_SCCACHE
    138 export RUSTC_WRAPPER=$(CCACHE)
    139 endif
    140 
    141 ifndef CROSS_COMPILE
    142 ifdef MOZ_TSAN
    143 PASS_ONLY_BASE_CFLAGS_TO_RUST=1
    144 else
    145 ifneq (,$(MOZ_ASAN)$(MOZ_UBSAN))
    146 ifneq ($(OS_ARCH), Linux)
    147 PASS_ONLY_BASE_CFLAGS_TO_RUST=1
    148 endif # !Linux
    149 endif # MOZ_ASAN || MOZ_UBSAN
    150 endif # MOZ_TSAN
    151 endif # !CROSS_COMPILE
    152 
    153 ifeq (WINNT,$(HOST_OS_ARCH))
    154 ifdef MOZ_CODE_COVERAGE
    155 PASS_ONLY_BASE_CFLAGS_TO_RUST=1
    156 endif # MOZ_CODE_COVERAGE
    157 endif # WINNT
    158 
    159 ifeq (WINNT,$(HOST_OS_ARCH))
    160 # //?/ is the long path prefix which seems to confuse make, so we remove it
    161 # (things should work without it).
    162 normalize_sep = $(patsubst //?/%,%,$(subst \,/,$(1)))
    163 else
    164 normalize_sep = $(1)
    165 endif
    166 
    167 # We start with host variables because the rust host and the rust target might be the same,
    168 # in which case we want the latter to take priority.
    169 
    170 # We're passing these for consumption by the `cc` crate, which doesn't use the same
    171 # convention as cargo itself:
    172 # https://github.com/alexcrichton/cc-rs/blob/baa71c0e298d9ad7ac30f0ad78f20b4b3b3a8fb2/src/lib.rs#L1715
    173 rust_host_cc_env_name := $(subst -,_,$(RUST_HOST_TARGET))
    174 
    175 # HOST_CC/HOST_CXX/CC/CXX usually contain base flags for e.g. the build target.
    176 # We want to pass those through CFLAGS_*/CXXFLAGS_* instead, so that they end up
    177 # after whatever cc-rs adds to the compiler command line, so that they win.
    178 # Ideally, we'd use CRATE_CC_NO_DEFAULTS=1, but that causes other problems at the
    179 # moment.
    180 export CC_$(rust_host_cc_env_name)=$(filter-out $(HOST_CC_BASE_FLAGS),$(HOST_CC))
    181 export CXX_$(rust_host_cc_env_name)=$(filter-out $(HOST_CXX_BASE_FLAGS),$(HOST_CXX))
    182 export AR_$(rust_host_cc_env_name)=$(HOST_AR)
    183 
    184 rust_cc_env_name := $(subst -,_,$(RUST_TARGET))
    185 
    186 export CC_$(rust_cc_env_name)=$(filter-out $(CC_BASE_FLAGS),$(CC))
    187 export CXX_$(rust_cc_env_name)=$(filter-out $(CXX_BASE_FLAGS),$(CXX))
    188 export AR_$(rust_cc_env_name)=$(AR)
    189 
    190 ifeq (WINNT,$(HOST_OS_ARCH))
    191 HOST_CC_BASE_FLAGS += -DUNICODE
    192 HOST_CXX_BASE_FLAGS += -DUNICODE
    193 endif
    194 ifeq (WINNT,$(OS_ARCH))
    195 CC_BASE_FLAGS += -DUNICODE
    196 CXX_BASE_FLAGS += -DUNICODE
    197 endif
    198 
    199 ifneq (1,$(PASS_ONLY_BASE_CFLAGS_TO_RUST))
    200 export CFLAGS_$(rust_host_cc_env_name)=$(HOST_CC_BASE_FLAGS) $(COMPUTED_HOST_CFLAGS)
    201 export CXXFLAGS_$(rust_host_cc_env_name)=$(HOST_CXX_BASE_FLAGS) $(COMPUTED_HOST_CXXFLAGS)
    202 # We exclude -fprofile-generate from the PGO flags because on non-cross compiles,
    203 # that affects build scripts, and they fail to link because the linker flags are
    204 # not adequate, and also, we don't want to run instrumented build scripts.
    205 # The cc crate will fill in for those flags anyways, but we do need the PGO and
    206 # LTO flags to fill in for what the cc crate doesn't handle
    207 # (e.g. -pgo-temporal-instrumentation)
    208 # We can't use LTO flags with GCC, though: https://github.com/rust-lang/rust/issues/138681
    209 ifneq (,$(filter clang%,$(CC_TYPE)))
    210 RUST_LTO_CFLAGS=$(MOZ_LTO_CFLAGS)
    211 endif
    212 export CFLAGS_$(rust_cc_env_name)=$(CC_BASE_FLAGS) $(RUST_LTO_CFLAGS) $(COMPUTED_CFLAGS) $(filter-out -fprofile-generate%,$(PGO_CFLAGS))
    213 export CXXFLAGS_$(rust_cc_env_name)=$(CXX_BASE_FLAGS) $(RUST_LTO_CFLAGS) $(COMPUTED_CXXFLAGS) $(filter-out -fprofile-generate%,$(PGO_CFLAGS))
    214 else
    215 # Because cargo doesn't allow to distinguish builds happening for build
    216 # scripts/procedural macros vs. those happening for the rust target,
    217 # we can't blindly pass all our flags down for cc-rs to use them, because of the
    218 # side effects they can have on what otherwise should be host builds.
    219 # So for sanitizer and coverage builds, we only pass the base compiler flags.
    220 # This means C code built by rust is not going to be covered by sanitizers
    221 # and coverage. But at least we control what compiler is being used,
    222 # rather than relying on cc-rs guesses, which, sometimes fail us.
    223 # -fno-sized-deallocation is important, though, as -fsized-deallocation may be the
    224 # compiler default and we don't want it to be used
    225 # (see build/moz.configure/flags.configure). Likewise with -fno-aligned-new.
    226 export CFLAGS_$(rust_host_cc_env_name)=$(HOST_CC_BASE_FLAGS)
    227 export CXXFLAGS_$(rust_host_cc_env_name)=$(HOST_CXX_BASE_FLAGS)
    228 export CFLAGS_$(rust_cc_env_name)=$(CC_BASE_FLAGS)
    229 export CXXFLAGS_$(rust_cc_env_name)=$(CXX_BASE_FLAGS) $(filter -fno-aligned-new -fno-sized-deallocation,$(COMPUTED_CXXFLAGS))
    230 endif
    231 
    232 # When host == target, cargo will compile build scripts with sanitizers enabled
    233 # if sanitizers are enabled, which may randomly fail when they execute
    234 # because of https://github.com/google/sanitizers/issues/1322.
    235 # Work around by disabling __tls_get_addr interception (bug 1635327).
    236 ifeq ($(RUST_TARGET),$(RUST_HOST_TARGET))
    237 define sanitizer_options
    238 ifdef MOZ_$1
    239 export $1_OPTIONS:=$$($1_OPTIONS:%=%:)intercept_tls_get_addr=0
    240 endif
    241 endef
    242 $(foreach san,ASAN TSAN UBSAN,$(eval $(call sanitizer_options,$(san))))
    243 endif
    244 
    245 # Force the target down to all bindgen callers, even those that may not
    246 # read BINDGEN_SYSTEM_FLAGS some way or another.
    247 export BINDGEN_EXTRA_CLANG_ARGS:=$(filter --target=%,$(BINDGEN_SYSTEM_FLAGS))
    248 export CARGO_TARGET_DIR
    249 export RUSTFLAGS
    250 export RUSTC
    251 export RUSTDOC
    252 export RUSTDOCFLAGS
    253 export RUSTFMT
    254 export LIBCLANG_PATH=$(MOZ_LIBCLANG_PATH)
    255 export CLANG_PATH=$(MOZ_CLANG_PATH)
    256 export PKG_CONFIG
    257 export PKG_CONFIG_ALLOW_CROSS=1
    258 export PKG_CONFIG_PATH
    259 ifneq (,$(PKG_CONFIG_SYSROOT_DIR))
    260 export PKG_CONFIG_SYSROOT_DIR
    261 endif
    262 ifneq (,$(PKG_CONFIG_LIBDIR))
    263 export PKG_CONFIG_LIBDIR
    264 endif
    265 export RUST_BACKTRACE=full
    266 export MOZ_TOPOBJDIR=$(topobjdir)
    267 export MOZ_FOLD_LIBS
    268 export PYTHON3
    269 export CARGO_PROFILE_RELEASE_OPT_LEVEL
    270 export CARGO_PROFILE_DEV_OPT_LEVEL
    271 
    272 # Set COREAUDIO_SDK_PATH for third_party/rust/coreaudio-sys/build.rs
    273 ifeq ($(OS_ARCH), Darwin)
    274 ifdef MACOS_SDK_DIR
    275 export COREAUDIO_SDK_PATH=$(MACOS_SDK_DIR)
    276 endif
    277 ifdef IPHONEOS_SDK_DIR
    278 export COREAUDIO_SDK_PATH=$(IPHONEOS_SDK_DIR)
    279 # export for build/macosx/xcrun
    280 export IPHONEOS_SDK_DIR
    281 PATH := $(topsrcdir)/build/macosx:$(PATH)
    282 endif
    283 endif
    284 # Use the same prefix as set through modules/zlib/src/mozzconf.h
    285 # for libz-rs-sys, since we still use the headers from there.
    286 export LIBZ_RS_SYS_PREFIX=MOZ_Z_
    287 
    288 ifndef RUSTC_BOOTSTRAP
    289 RUSTC_BOOTSTRAP := mozglue_static,qcms
    290 ifdef MOZ_RUST_SIMD
    291 RUSTC_BOOTSTRAP := $(RUSTC_BOOTSTRAP),encoding_rs,any_all_workaround
    292 endif
    293 export RUSTC_BOOTSTRAP
    294 endif
    295 
    296 target_rust_ltoable := force-cargo-library-build $(ADD_RUST_LTOABLE)
    297 target_rust_nonltoable := force-cargo-test-run force-cargo-program-build
    298 
    299 ifdef MOZ_PGO_RUST
    300 ifdef MOZ_PROFILE_GENERATE
    301 rust_pgo_flags := -C profile-generate=$(topobjdir)
    302 ifeq (1,$(words $(filter 5.% 6.% 7.% 8.% 9.% 10.% 11.%,$(CC_VERSION) $(RUSTC_LLVM_VERSION))))
    303 # Disable value profiling when:
    304 # (RUSTC_LLVM_VERSION < 12 and CC_VERSION >= 12) or (RUSTC_LLVM_VERSION >= 12 and CC_VERSION < 12)
    305 rust_pgo_flags += -C llvm-args=--disable-vp=true
    306 endif
    307 # The C compiler may be passed extra llvm flags for PGO that we also want to pass to rust as well.
    308 # In PROFILE_GEN_CFLAGS, they look like "-mllvm foo", and we want "-C llvm-args=foo", so first turn
    309 # "-mllvm foo" into "-mllvm:foo" so that it becomes a unique argument, that we can then filter for,
    310 # excluding other flags, and then turn into the right string.
    311 rust_pgo_flags += $(patsubst -mllvm:%,-C llvm-args=%,$(filter -mllvm:%,$(subst -mllvm ,-mllvm:,$(PROFILE_GEN_CFLAGS))))
    312 else # MOZ_PROFILE_USE
    313 rust_pgo_flags := -C profile-use=$(PGO_PROFILE_PATH)
    314 endif
    315 endif
    316 
    317 # Work around https://github.com/rust-lang/rust/issues/112480
    318 ifdef MOZ_DEBUG_RUST
    319 ifneq (,$(filter i686-pc-windows-%,$(RUST_TARGET)))
    320 RUSTFLAGS += -Zmir-enable-passes=-CheckAlignment
    321 RUSTC_BOOTSTRAP := 1
    322 endif
    323 endif
    324 
    325 ifeq (WINNT_clang,$(OS_ARCH)_$(CC_TYPE))
    326 RUSTFLAGS += -C dlltool=$(LLVM_DLLTOOL)
    327 endif
    328 
    329 $(target_rust_ltoable): RUSTFLAGS:=$(rustflags_override) $(rustflags_sancov) $(RUSTFLAGS) $(rust_pgo_flags) \
    330 							$(if $(MOZ_LTO_RUST_CROSS),\
    331 							    -Clinker-plugin-lto \
    332 								,)
    333 $(target_rust_nonltoable): RUSTFLAGS:=$(rustflags_override) $(rustflags_sancov) $(RUSTFLAGS)
    334 
    335 TARGET_RECIPES := $(target_rust_ltoable) $(target_rust_nonltoable)
    336 
    337 HOST_RECIPES := \
    338  $(foreach a,library program,$(foreach b,build check udeps clippy,force-cargo-host-$(a)-$(b)))
    339 
    340 $(HOST_RECIPES): RUSTFLAGS:=$(rustflags_override)
    341 
    342 # If this is a release build we want rustc to generate one codegen unit per
    343 # crate. This results in better optimization and less code duplication at the
    344 # cost of longer compile times.
    345 ifndef DEVELOPER_OPTIONS
    346 $(TARGET_RECIPES) $(HOST_RECIPES): RUSTFLAGS += -C codegen-units=1
    347 endif
    348 
    349 # We use the + prefix to pass down the jobserver fds to cargo, but we
    350 # don't use the prefix when make -n is used, so that cargo doesn't run
    351 # in that case)
    352 define RUN_CARGO_INNER
    353 $(if $(findstring n,$(filter-out --%, $(MAKEFLAGS))),,+)$(CARGO) $(1) $(cargo_build_flags) $(CARGO_EXTRA_FLAGS) $(cargo_extra_cli_flags)
    354 endef
    355 
    356 ifdef CARGO_CONTINUE_ON_ERROR
    357 define RUN_CARGO
    358 -$(RUN_CARGO_INNER)
    359 endef
    360 else
    361 define RUN_CARGO
    362 $(RUN_CARGO_INNER)
    363 endef
    364 endif
    365 
    366 # This function is intended to be called by:
    367 #
    368 #   $(call CARGO_BUILD,EXTRA_ENV_VAR1=X EXTRA_ENV_VAR2=Y ...)
    369 #
    370 # but, given the idiosyncracies of make, can also be called without arguments:
    371 #
    372 #   $(call CARGO_BUILD)
    373 define CARGO_BUILD
    374 $(call RUN_CARGO,rustc$(if $(BUILDSTATUS), --timings)$(if $(findstring k,$(filter-out --%, $(MAKEFLAGS))), --keep-going))
    375 endef
    376 
    377 cargo_host_linker_env_var := CARGO_TARGET_$(call varize,$(RUST_HOST_TARGET))_LINKER
    378 cargo_linker_env_var := CARGO_TARGET_$(call varize,$(RUST_TARGET))_LINKER
    379 
    380 export MOZ_CLANG_NEWER_THAN_RUSTC_LLVM
    381 export MOZ_CARGO_WRAP_LDFLAGS
    382 export MOZ_CARGO_WRAP_LD
    383 export MOZ_CARGO_WRAP_LD_CXX
    384 export MOZ_CARGO_WRAP_HOST_LDFLAGS
    385 export MOZ_CARGO_WRAP_HOST_LD
    386 export MOZ_CARGO_WRAP_HOST_LD_CXX
    387 # Exporting from make always exports a value. Setting a value per-recipe
    388 # would export an empty value for the host recipes. When not doing a
    389 # cross-compile, the --target for those is the same, and cargo will use
    390 # CARGO_TARGET_*_LINKER for its linker, so we always pass the
    391 # cargo-linker wrapper, and fill MOZ_CARGO_WRAP_{HOST_,}LD* more or less
    392 # appropriately for all recipes.
    393 ifeq (WINNT,$(HOST_OS_ARCH))
    394 # Use .bat wrapping on Windows hosts, and shell wrapping on other hosts.
    395 # Like for CC/C*FLAGS, we want the target values to trump the host values when
    396 # both variables are the same.
    397 export $(cargo_host_linker_env_var):=$(topsrcdir)/build/cargo-host-linker.bat
    398 export $(cargo_linker_env_var):=$(topsrcdir)/build/cargo-linker.bat
    399 WRAP_HOST_LINKER_LIBPATHS:=$(HOST_LINKER_LIBPATHS_BAT)
    400 else
    401 export $(cargo_host_linker_env_var):=$(topsrcdir)/build/cargo-host-linker
    402 export $(cargo_linker_env_var):=$(topsrcdir)/build/cargo-linker
    403 WRAP_HOST_LINKER_LIBPATHS:=$(HOST_LINKER_LIBPATHS)
    404 endif
    405 
    406 # Cargo needs the same linker flags as the C/C++ compiler,
    407 # but not the final libraries. Filter those out because they
    408 # cause problems on macOS 10.7; see bug 1365993 for details.
    409 # Also, we don't want to pass PGO flags until cargo supports them.
    410 # Finally, we also remove the -Wl,--build-id=uuid flag when it's in
    411 # the LDFLAGS. The flag was chosen over the default (build-id=sha1)
    412 # in developer builds, because for libxul, it's faster. But it's also
    413 # non-deterministic. So when the rust compiler produces procedural
    414 # macros as libraries, they're not reproducible. Those procedural
    415 # macros then end up as dependencies of other crates, and their
    416 # non-reproducibility leads to sccache transitively having cache
    417 # misses.
    418 $(TARGET_RECIPES): MOZ_CARGO_WRAP_LDFLAGS:=$(filter-out -fsanitize=cfi% -framework Cocoa -lobjc AudioToolbox ExceptionHandling -fprofile-% -Wl$(COMMA)--build-id=uuid,$(LDFLAGS))
    419 
    420 # When building with sanitizer, rustc links its own runtime, which conflicts
    421 # with the one that passing -fsanitize=* to the linker would add.
    422 # Ideally, we'd always do this filtering, but because the flags may also apply
    423 # to build scripts because cargo doesn't allow the distinction, we only filter
    424 # when building programs, except when using thread sanitizer where we filter
    425 # everywhere.
    426 ifneq (,$(filter -Zsanitizer=%,$(RUSTFLAGS)))
    427 $(if $(filter -Zsanitizer=thread,$(RUSTFLAGS)),$(TARGET_RECIPES),force-cargo-program-build): MOZ_CARGO_WRAP_LDFLAGS:=$(filter-out -fsanitize=%,$(MOZ_CARGO_WRAP_LDFLAGS))
    428 endif
    429 
    430 # Rustc assumes that *-windows-gnu targets build with mingw-gcc and manually
    431 # add runtime libraries that don't exist with mingw-clang. We created dummy
    432 # libraries in $(topobjdir)/build/win32, but that's not enough, because some
    433 # of the wanted symbols that come from these libraries are available in a
    434 # different library, that we add manually. We also need to avoid rustc
    435 # passing -nodefaultlibs to clang so that it adds clang_rt.
    436 ifeq (WINNT_clang,$(OS_ARCH)_$(CC_TYPE))
    437 force-cargo-program-build: MOZ_CARGO_WRAP_LDFLAGS+=-L$(topobjdir)/build/win32 -lunwind
    438 force-cargo-program-build: CARGO_RUSTCFLAGS += -C default-linker-libraries=yes
    439 endif
    440 
    441 # Rustc passes -nodefaultlibs to the linker (clang) on mac, which prevents
    442 # clang from adding the necessary sanitizer runtimes when building with
    443 # C/C++ sanitizer but without rust sanitizer.
    444 ifeq (Darwin,$(OS_ARCH))
    445 ifeq (,$(filter -Zsanitizer=%,$(RUSTFLAGS)))
    446 ifneq (,$(filter -fsanitize=%,$(LDFLAGS)))
    447 $(TARGET_RECIPES): RUSTFLAGS += -C default-linker-libraries=yes
    448 endif
    449 endif
    450 endif
    451 
    452 $(HOST_RECIPES): MOZ_CARGO_WRAP_LDFLAGS:=$(HOST_LDFLAGS) $(WRAP_HOST_LINKER_LIBPATHS)
    453 $(TARGET_RECIPES) $(HOST_RECIPES): MOZ_CARGO_WRAP_HOST_LDFLAGS:=$(HOST_LDFLAGS) $(WRAP_HOST_LINKER_LIBPATHS)
    454 
    455 ifeq (,$(filter clang-cl,$(CC_TYPE)))
    456 $(TARGET_RECIPES): MOZ_CARGO_WRAP_LD:=$(CC)
    457 $(TARGET_RECIPES): MOZ_CARGO_WRAP_LD_CXX:=$(CXX)
    458 else
    459 $(TARGET_RECIPES): MOZ_CARGO_WRAP_LD:=$(LINKER)
    460 $(TARGET_RECIPES): MOZ_CARGO_WRAP_LD_CXX:=$(LINKER)
    461 endif
    462 
    463 ifeq (,$(filter clang-cl,$(HOST_CC_TYPE)))
    464 $(HOST_RECIPES): MOZ_CARGO_WRAP_LD:=$(HOST_CC)
    465 $(HOST_RECIPES): MOZ_CARGO_WRAP_LD_CXX:=$(HOST_CXX)
    466 $(TARGET_RECIPES) $(HOST_RECIPES): MOZ_CARGO_WRAP_HOST_LD:=$(HOST_CC)
    467 $(TARGET_RECIPES) $(HOST_RECIPES): MOZ_CARGO_WRAP_HOST_LD_CXX:=$(HOST_CXX)
    468 else
    469 $(HOST_RECIPES): MOZ_CARGO_WRAP_LD:=$(HOST_LINKER)
    470 $(HOST_RECIPES): MOZ_CARGO_WRAP_LD_CXX:=$(HOST_LINKER)
    471 $(TARGET_RECIPES) $(HOST_RECIPES): MOZ_CARGO_WRAP_HOST_LD:=$(HOST_LINKER)
    472 $(TARGET_RECIPES) $(HOST_RECIPES): MOZ_CARGO_WRAP_HOST_LD_CXX:=$(HOST_LINKER)
    473 endif
    474 
    475 define make_default_rule
    476 $(1):
    477 
    478 endef
    479 
    480 # make_cargo_rule(target, real-target [, extra-deps])
    481 # Generates a rule suitable to rebuild $(target) only if its dependencies are
    482 # obsolete.
    483 # It relies on the fact that upon build, cargo generates a dependency file named
    484 # `$(target).d'. Unfortunately the lhs of the rule has an absolute path,
    485 # so we extract it under the name $(target)_deps below.
    486 #
    487 # If the dependencies are empty, the file was not created so we force a rebuild.
    488 # Otherwise we add it to the dependency list.
    489 #
    490 # The actual rule is a bit tricky. The `+' prefix allow for recursive parallel
    491 # make, and it's skipped (`:') if we already triggered a rebuild as part of the
    492 # dependency chain.
    493 #
    494 # Another tricky thing: some dependencies may contain escaped spaces, and they
    495 # need to be preserved, but $(foreach) splits on spaces, so we replace escaped
    496 # spaces with some unlikely string for the foreach, and replace them back in the
    497 # loop itself.
    498 define make_cargo_rule
    499 $(notdir $(1))_deps := $$(call normalize_sep,$$(wordlist 2, 10000000, $$(if $$(wildcard $(basename $(1)).d),$$(shell cat $(basename $(1)).d))))
    500 $(1): $(CARGO_FILE) $(3) $(topsrcdir)/Cargo.lock $$(if $$($(notdir $(1))_deps),$$($(notdir $(1))_deps),$(2))
    501 $$(REPORT_BUILD)
    502 $$(if $$($(notdir $(1))_deps),+$(MAKE) $(2),:)
    503 
    504 $$(foreach dep, $$(subst \ ,_^_^_^_,$$($(notdir $(1))_deps)),$$(eval $$(call make_default_rule,$$(subst _^_^_^_,\ ,$$(dep)))))
    505 endef
    506 
    507 ifdef RUST_LIBRARY_FILE
    508 
    509 rust_features_flag := --features '$(if $(RUST_LIBRARY_FEATURES),$(RUST_LIBRARY_FEATURES) )mozilla-central-workspace-hack'
    510 
    511 ifeq (WASI,$(OS_ARCH))
    512 # The rust wasi target defaults to statically link the wasi crt, but when we
    513 # build static libraries from rust and link them with C/C++ code, we also link
    514 # a wasi crt, which may conflict with rust's.
    515 force-cargo-library-build: CARGO_RUSTCFLAGS += -C target-feature=-crt-static
    516 endif
    517 
    518 # Assume any system libraries rustc links against are already in the target's LIBS.
    519 #
    520 # We need to run cargo unconditionally, because cargo is the only thing that
    521 # has full visibility into how changes in Rust sources might affect the final
    522 # build.
    523 force-cargo-library-build:
    524 $(call BUILDSTATUS,START_Rust $(notdir $(RUST_LIBRARY_FILE)))
    525 $(call CARGO_BUILD) --lib $(cargo_target_flag) $(rust_features_flag) -- $(cargo_rustc_flags)
    526 $(call BUILDSTATUS,END_Rust $(notdir $(RUST_LIBRARY_FILE)))
    527 # When we are building in --enable-release mode; we add an additional check to confirm
    528 # that we are not importing any networking-related functions in rust code. This reduces
    529 # the chance of proxy bypasses originating from rust code.
    530 # The check only works when rust code is built with -Clto but without MOZ_LTO_RUST_CROSS.
    531 # Sanitizers and sancov also fail because compiler-rt hooks network functions.
    532 ifndef MOZ_PROFILE_GENERATE
    533 ifeq ($(OS_ARCH), Linux)
    534 ifeq (,$(rustflags_sancov)$(MOZ_ASAN)$(MOZ_TSAN)$(MOZ_UBSAN))
    535 ifndef MOZ_LTO_RUST_CROSS
    536 ifneq (,$(filter -Clto,$(cargo_rustc_flags)))
    537 $(call py_action,check_binary $(@F),--networking $(RUST_LIBRARY_FILE))
    538 endif
    539 endif
    540 endif
    541 endif
    542 endif
    543 
    544 $(eval $(call make_cargo_rule,$(RUST_LIBRARY_FILE),force-cargo-library-build))
    545 
    546 SUGGEST_INSTALL_ON_FAILURE = (ret=$$?; if [ $$ret = 101 ]; then echo If $1 is not installed, install it using: cargo install $1; fi; exit $$ret)
    547 
    548 ifndef CARGO_NO_AUTO_ARG
    549 force-cargo-library-%:
    550 $(call RUN_CARGO,$*) --lib $(cargo_target_flag) $(rust_features_flag) || $(call SUGGEST_INSTALL_ON_FAILURE,cargo-$*)
    551 else
    552 force-cargo-library-%:
    553 $(call RUN_CARGO,$*) || $(call SUGGEST_INSTALL_ON_FAILURE,cargo-$*)
    554 endif
    555 
    556 else
    557 force-cargo-library-%:
    558 @true
    559 
    560 endif # RUST_LIBRARY_FILE
    561 
    562 ifdef RUST_TESTS
    563 
    564 rust_test_options := $(foreach test,$(RUST_TESTS),-p $(test))
    565 
    566 rust_test_features_flag := --features '$(if $(RUST_TEST_FEATURES),$(RUST_TEST_FEATURES) )mozilla-central-workspace-hack'
    567 
    568 # Don't stop at the first failure. We want to list all failures together.
    569 rust_test_flag := --no-fail-fast
    570 
    571 force-cargo-test-run:
    572 $(call RUN_CARGO,test $(cargo_target_flag) $(rust_test_flag) $(rust_test_options) $(rust_test_features_flag))
    573 
    574 endif # RUST_TESTS
    575 
    576 ifdef HOST_RUST_LIBRARY_FILE
    577 
    578 host_rust_features_flag := --features '$(if $(HOST_RUST_LIBRARY_FEATURES),$(HOST_RUST_LIBRARY_FEATURES) )mozilla-central-workspace-hack'
    579 
    580 force-cargo-host-library-build:
    581 $(call BUILDSTATUS,START_Rust $(notdir $(HOST_RUST_LIBRARY_FILE)))
    582 $(call CARGO_BUILD) --lib $(cargo_host_flag) $(host_rust_features_flag)
    583 $(call BUILDSTATUS,END_Rust $(notdir $(HOST_RUST_LIBRARY_FILE)))
    584 
    585 $(eval $(call make_cargo_rule,$(HOST_RUST_LIBRARY_FILE),force-cargo-host-library-build))
    586 
    587 ifndef CARGO_NO_AUTO_ARG
    588 force-cargo-host-library-%:
    589 $(call RUN_CARGO,$*) --lib $(cargo_host_flag) $(host_rust_features_flag)
    590 else
    591 force-cargo-host-library-%:
    592 $(call RUN_CARGO,$*) --lib $(filter-out --release $(cargo_host_flag)) $(host_rust_features_flag)
    593 endif
    594 
    595 else
    596 force-cargo-host-library-%:
    597 @true
    598 endif # HOST_RUST_LIBRARY_FILE
    599 
    600 ifdef RUST_PROGRAMS
    601 
    602 program_features_flag := --features mozilla-central-workspace-hack
    603 
    604 force-cargo-program-build: $(call resfile,module)
    605 $(call BUILDSTATUS,START_Rust $(RUST_CARGO_PROGRAMS))
    606 $(call CARGO_BUILD) $(addprefix --bin ,$(RUST_CARGO_PROGRAMS)) $(cargo_target_flag) $(program_features_flag) -- $(addprefix -C link-arg=$(CURDIR)/,$(call resfile,module)) $(CARGO_RUSTCFLAGS)
    607 $(call BUILDSTATUS,END_Rust $(RUST_CARGO_PROGRAMS))
    608 
    609 $(foreach RUST_PROGRAM,$(RUST_PROGRAMS), $(eval $(call make_cargo_rule,$(RUST_PROGRAM),force-cargo-program-build,$(call resfile,module))))
    610 
    611 ifndef CARGO_NO_AUTO_ARG
    612 force-cargo-program-%:
    613 $(call RUN_CARGO,$*) $(addprefix --bin ,$(RUST_CARGO_PROGRAMS)) $(cargo_target_flag) $(program_features_flag)
    614 else
    615 force-cargo-program-%:
    616 $(call RUN_CARGO,$*)
    617 endif
    618 
    619 else
    620 force-cargo-program-%:
    621 @true
    622 endif # RUST_PROGRAMS
    623 ifdef HOST_RUST_PROGRAMS
    624 
    625 host_program_features_flag := --features mozilla-central-workspace-hack
    626 
    627 force-cargo-host-program-build:
    628 $(call BUILDSTATUS,START_Rust $(HOST_RUST_CARGO_PROGRAMS))
    629 $(call CARGO_BUILD) $(addprefix --bin ,$(HOST_RUST_CARGO_PROGRAMS)) $(cargo_host_flag) $(host_program_features_flag)
    630 $(call BUILDSTATUS,END_Rust $(HOST_RUST_CARGO_PROGRAMS))
    631 
    632 $(foreach HOST_RUST_PROGRAM,$(HOST_RUST_PROGRAMS), $(eval $(call make_cargo_rule,$(HOST_RUST_PROGRAM),force-cargo-host-program-build)))
    633 
    634 ifndef CARGO_NO_AUTO_ARG
    635 force-cargo-host-program-%:
    636 $(call BUILDSTATUS,START_Rust $(HOST_RUST_CARGO_PROGRAMS))
    637 $(call RUN_CARGO,$*) $(addprefix --bin ,$(HOST_RUST_CARGO_PROGRAMS)) $(cargo_host_flag) $(host_program_features_flag)
    638 $(call BUILDSTATUS,END_Rust $(HOST_RUST_CARGO_PROGRAMS))
    639 else
    640 force-cargo-host-program-%:
    641 $(call RUN_CARGO,$*) $(addprefix --bin ,$(HOST_RUST_CARGO_PROGRAMS)) $(filter-out --release $(cargo_target_flag))
    642 endif
    643 
    644 else
    645 force-cargo-host-program-%:
    646 @true
    647 
    648 endif # HOST_RUST_PROGRAMS