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