@@ -36,6 +36,29 @@ impl RustcArgs {
3636 }
3737 result
3838 }
39+
40+ /// Normally `rustc` uses a C compiler such as `cc` or `clang` as linker,
41+ /// and arguments to the actual linker need to be passed prefixed with `-Wl,`.
42+ /// But it is possible to configure Cargo and rustc to call a linker directly,
43+ /// and the breakage it causes is subtle enough that people just roll with it
44+ /// and complain when cargo-auditable doesn't support this configuration:
45+ /// <https://github.com/rust-secure-code/cargo-auditable/issues/202>
46+ ///
47+ /// This function can tell you if a bare linker is in use
48+ /// and whether you need to prepend `-Wl,` or not.
49+ ///
50+ /// Such setups are exceptionally rare and frankly it's a misconfiguration
51+ /// that will break more than just `cargo auditable`, but I am feeling generous.
52+ pub fn bare_linker ( & self ) -> bool {
53+ let linker_flag = self . codegen . iter ( ) . find ( |s| s. starts_with ( "linker=" ) ) ;
54+ if let Some ( linker_flag) = linker_flag {
55+ let linker = linker_flag. strip_prefix ( "linker=" ) . unwrap ( ) ;
56+ if linker. ends_with ( "ld" ) {
57+ return true ;
58+ }
59+ }
60+ false
61+ }
3962}
4063
4164impl RustcArgs {
@@ -149,11 +172,7 @@ mod tests {
149172
150173 #[ test]
151174 fn multiple_emit_values ( ) {
152- let raw_rustc_args = vec ! [
153- "--emit=dep-info,link" ,
154- "--emit" ,
155- "llvm-bc" ,
156- ] ;
175+ let raw_rustc_args = vec ! [ "--emit=dep-info,link" , "--emit" , "llvm-bc" ] ;
157176 let raw_rustc_args: Vec < OsString > = raw_rustc_args. into_iter ( ) . map ( |s| s. into ( ) ) . collect ( ) ;
158177 let mut args = RustcArgs :: from_vec ( raw_rustc_args) . unwrap ( ) ;
159178
@@ -166,13 +185,18 @@ mod tests {
166185 assert_eq ! ( args. emit, expected)
167186 }
168187
188+ #[ test]
189+ fn detect_bare_linker ( ) {
190+ let raw_rustc_args = vec ! [ "-C" , "linker=rust-lld" ] ;
191+ let raw_rustc_args: Vec < OsString > = raw_rustc_args. into_iter ( ) . map ( |s| s. into ( ) ) . collect ( ) ;
192+ let mut args = RustcArgs :: from_vec ( raw_rustc_args) . unwrap ( ) ;
193+
194+ assert ! ( args. bare_linker( ) ) ;
195+ }
196+
169197 #[ test]
170198 fn multiple_codegen_options ( ) {
171- let raw_rustc_args = vec ! [
172- "-Clinker=clang" ,
173- "-C" ,
174- "link-arg=-fuse-ld=/usr/bin/mold" ,
175- ] ;
199+ let raw_rustc_args = vec ! [ "-Clinker=clang" , "-C" , "link-arg=-fuse-ld=/usr/bin/mold" ] ;
176200 let raw_rustc_args: Vec < OsString > = raw_rustc_args. into_iter ( ) . map ( |s| s. into ( ) ) . collect ( ) ;
177201 let mut args = RustcArgs :: from_vec ( raw_rustc_args) . unwrap ( ) ;
178202
@@ -182,6 +206,8 @@ mod tests {
182206 args. codegen . sort ( ) ;
183207 expected. sort ( ) ;
184208
185- assert_eq ! ( args. codegen, expected)
209+ assert_eq ! ( args. codegen, expected) ;
210+
211+ assert ! ( !args. bare_linker( ) ) ;
186212 }
187213}
0 commit comments