@@ -36,6 +36,7 @@ use regex::Regex;
36
36
use tempfile:: Builder as TempFileBuilder ;
37
37
38
38
use std:: ffi:: OsString ;
39
+ use std:: lazy:: OnceCell ;
39
40
use std:: path:: { Path , PathBuf } ;
40
41
use std:: process:: { ExitStatus , Output , Stdio } ;
41
42
use std:: { ascii, char, env, fmt, fs, io, mem, str} ;
@@ -257,6 +258,19 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
257
258
// metadata of the rlib we're generating somehow.
258
259
for lib in codegen_results. crate_info . used_libraries . iter ( ) {
259
260
match lib. kind {
261
+ NativeLibKind :: Static { bundle : None | Some ( true ) , whole_archive : Some ( true ) }
262
+ if flavor == RlibFlavor :: Normal =>
263
+ {
264
+ // Don't allow mixing +bundle with +whole_archive since an rlib may contain
265
+ // multiple native libs, some of which are +whole-archive and some of which are
266
+ // -whole-archive and it isn't clear how we can currently handle such a
267
+ // situation correctly.
268
+ // See https://github.com/rust-lang/rust/issues/88085#issuecomment-901050897
269
+ sess. err (
270
+ "the linking modifiers `+bundle` and `+whole-archive` are not compatible \
271
+ with each other when generating rlibs",
272
+ ) ;
273
+ }
260
274
NativeLibKind :: Static { bundle : None | Some ( true ) , .. } => { }
261
275
NativeLibKind :: Static { bundle : Some ( false ) , .. }
262
276
| NativeLibKind :: Dylib { .. }
@@ -1255,6 +1269,7 @@ fn archive_search_paths(sess: &Session) -> Vec<PathBuf> {
1255
1269
sess. target_filesearch ( PathKind :: Native ) . search_path_dirs ( )
1256
1270
}
1257
1271
1272
+ #[ derive( PartialEq ) ]
1258
1273
enum RlibFlavor {
1259
1274
Normal ,
1260
1275
StaticlibBase ,
@@ -2034,7 +2049,7 @@ fn add_local_native_libraries(
2034
2049
let relevant_libs =
2035
2050
codegen_results. crate_info . used_libraries . iter ( ) . filter ( |l| relevant_lib ( sess, l) ) ;
2036
2051
2037
- let search_path = archive_search_paths ( sess ) ;
2052
+ let search_path = OnceCell :: new ( ) ;
2038
2053
let mut last = ( NativeLibKind :: Unspecified , None ) ;
2039
2054
for lib in relevant_libs {
2040
2055
let name = match lib. name {
@@ -2056,7 +2071,11 @@ fn add_local_native_libraries(
2056
2071
}
2057
2072
NativeLibKind :: Static { bundle : None | Some ( true ) , .. }
2058
2073
| NativeLibKind :: Static { whole_archive : Some ( true ) , .. } => {
2059
- cmd. link_whole_staticlib ( name, verbatim, & search_path) ;
2074
+ cmd. link_whole_staticlib (
2075
+ name,
2076
+ verbatim,
2077
+ & search_path. get_or_init ( || archive_search_paths ( sess) ) ,
2078
+ ) ;
2060
2079
}
2061
2080
NativeLibKind :: Static { .. } => cmd. link_staticlib ( name, verbatim) ,
2062
2081
NativeLibKind :: RawDylib => {
@@ -2149,6 +2168,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
2149
2168
}
2150
2169
2151
2170
let mut compiler_builtins = None ;
2171
+ let search_path = OnceCell :: new ( ) ;
2152
2172
2153
2173
for & cnum in deps. iter ( ) {
2154
2174
if group_start == Some ( cnum) {
@@ -2182,16 +2202,35 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
2182
2202
// external build system already has the native dependencies defined, and it
2183
2203
// will provide them to the linker itself.
2184
2204
if sess. opts . debugging_opts . link_native_libraries {
2185
- // Skip if this library is the same as the last.
2186
2205
let mut last = None ;
2187
2206
for lib in & codegen_results. crate_info . native_libraries [ & cnum] {
2188
- if lib. name . is_some ( )
2189
- && relevant_lib ( sess, lib)
2190
- && matches ! ( lib. kind, NativeLibKind :: Static { bundle: Some ( false ) , .. } )
2191
- && last != lib. name
2192
- {
2193
- cmd. link_staticlib ( lib. name . unwrap ( ) , lib. verbatim . unwrap_or ( false ) ) ;
2194
- last = lib. name ;
2207
+ if !relevant_lib ( sess, lib) {
2208
+ // Skip libraries if they are disabled by `#[link(cfg=...)]`
2209
+ continue ;
2210
+ }
2211
+
2212
+ // Skip if this library is the same as the last.
2213
+ if last == lib. name {
2214
+ continue ;
2215
+ }
2216
+
2217
+ if let Some ( static_lib_name) = lib. name {
2218
+ if let NativeLibKind :: Static { bundle : Some ( false ) , whole_archive } =
2219
+ lib. kind
2220
+ {
2221
+ let verbatim = lib. verbatim . unwrap_or ( false ) ;
2222
+ if whole_archive == Some ( true ) {
2223
+ cmd. link_whole_staticlib (
2224
+ static_lib_name,
2225
+ verbatim,
2226
+ search_path. get_or_init ( || archive_search_paths ( sess) ) ,
2227
+ ) ;
2228
+ } else {
2229
+ cmd. link_staticlib ( static_lib_name, verbatim) ;
2230
+ }
2231
+
2232
+ last = lib. name ;
2233
+ }
2195
2234
}
2196
2235
}
2197
2236
}
0 commit comments