According to the rust documentation, build.rustflags
should be used to pass a flag to every compiler process, even the dependencies. So we can use it to apply a sanitizer that requires a runtime (e.g., -Zsanitizer=address
). Then I add to the cargo project folder a .cargo/config
file, which only contains:
[build]
rustflags = ["-Zsanitizer=address"]
If I do it in a clean project (cargo new test
), the compilation process works (cargo build --release
). But the compilation fails as soon as I add proc-macro-error
(1.0.4) as a dependency (through Cargo.toml
). The error happens when trying to compile proc-macro-error
, after successfully compiling all its dependencies.
Generally, I observe that this happens to whatever rlib
dependency that at it's time depends on a proc-macro
. I don't know if there's an additional constraint, but I discuss the dependency tree below.
With the current nightly rust compiler (1.71.0) it gives the next error:
error[E0519]: the current crate is indistinguishable from one of its dependencies: it has the same crate-name `proc_macro_error_attr` and was compiled with the same `-C metadata` arguments. This will result in symbol conflicts between the two.
--> ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro-error-1.0.4/src/lib.rs:284:9
|
284 | pub use proc_macro_error_attr::proc_macro_error;
| ^^^^^^^^^^^^^^^^^^^^^
But if I build rustc myself the nightly version of the repository (tag 1.69.0 in the repository) and add rustc = "BUILD_DIR_BIN/rustc"
to the aforementioned .cargo/config
, I get a different error over the same source line, telling about the sanitizer runtime symbol not being defined:
error: .../test/target/release/deps/libproc_macro_error_attr-363b79ca82bc726b.so: undefined symbol: __asan_option_detect_stack_use_after_return
--> ~/.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro-error-1.0.4/src/lib.rs:284:9
|
284 | pub use proc_macro_error_attr::proc_macro_error;
| ^^^^^^^^^^^^^^^^^^^^^
For reference, if I run cargo tree
I get the next output:
test v0.1.0 (.../test)
βββ proc-macro-error v1.0.4
βββ proc-macro-error-attr v1.0.4 (proc-macro)
β βββ proc-macro2 v1.0.56
β β βββ unicode-ident v1.0.8
β βββ quote v1.0.26
β βββ proc-macro2 v1.0.56 (*)
β [build-dependencies]
β βββ version_check v0.9.4
βββ proc-macro2 v1.0.56 (*)
βββ quote v1.0.26 (*)
βββ syn v1.0.109
βββ proc-macro2 v1.0.56 (*)
βββ unicode-ident v1.0.8
[build-dependencies]
βββ version_check v0.9.4
The crate types are:
-
bin
fortest
-
proc-macro
forproc-macro-aror-attr
-
rlib
forunicode-ident
andproc-macro2
If I use any other sanitizer, I get the missing symbol problem for another runtime (e.g., __tsan_read8
for thread sanitizer). The reason I add the custom flags and compiler over .cargo/config
is because the build.rustflags
aren't used if this is done over Cargo.toml
. Still, when calling cargo build
and adding the --config
flag with the paramenters mentioned, I reproduce the same behavior as with .cargo/config
.
When looking more in detail (by using verbose output of cargo
), the exact same proc-macro2
is compiled twice but with different output directories (due to metadata) and optimization (it adds -C opt-level=3
to one of those instances).
This behavior doesn't sound right to me, let me know if I'm doing something wrong or is the expected to be like that. I haven't found any information regarding a similar issue, so I consider this to not have been discussed before. I'm happy to discuss and potentially fix the problem, but I would need to hear from someone more experienced about the root cause. Should I post this on the github issues or internals discourse?