@@ -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} ;
@@ -254,6 +255,19 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
254
255
// metadata of the rlib we're generating somehow.
255
256
for lib in codegen_results. crate_info . used_libraries . iter ( ) {
256
257
match lib. kind {
258
+ NativeLibKind :: Static { bundle : None | Some ( true ) , whole_archive : Some ( true ) }
259
+ if flavor == RlibFlavor :: Normal =>
260
+ {
261
+ // Don't allow mixing +bundle with +whole_archive since an rlib may contain
262
+ // multiple native libs, some of which are +whole-archive and some of which are
263
+ // -whole-archive and it isn't clear how we can currently handle such a
264
+ // situation correctly.
265
+ // See https://github.com/rust-lang/rust/issues/88085#issuecomment-901050897
266
+ sess. err (
267
+ "the linking modifiers `+bundle` and `+whole-archive` are not compatible \
268
+ with each other when generating rlibs",
269
+ ) ;
270
+ }
257
271
NativeLibKind :: Static { bundle : None | Some ( true ) , .. } => { }
258
272
NativeLibKind :: Static { bundle : Some ( false ) , .. }
259
273
| NativeLibKind :: Dylib { .. }
@@ -1222,6 +1236,7 @@ pub fn archive_search_paths(sess: &Session) -> Vec<PathBuf> {
1222
1236
sess. target_filesearch ( PathKind :: Native ) . search_path_dirs ( )
1223
1237
}
1224
1238
1239
+ #[ derive( PartialEq ) ]
1225
1240
enum RlibFlavor {
1226
1241
Normal ,
1227
1242
StaticlibBase ,
@@ -2001,7 +2016,7 @@ fn add_local_native_libraries(
2001
2016
let relevant_libs =
2002
2017
codegen_results. crate_info . used_libraries . iter ( ) . filter ( |l| relevant_lib ( sess, l) ) ;
2003
2018
2004
- let search_path = archive_search_paths ( sess ) ;
2019
+ let search_path = OnceCell :: new ( ) ;
2005
2020
let mut last = ( NativeLibKind :: Unspecified , None ) ;
2006
2021
for lib in relevant_libs {
2007
2022
let name = match lib. name {
@@ -2023,7 +2038,11 @@ fn add_local_native_libraries(
2023
2038
}
2024
2039
NativeLibKind :: Static { bundle : None | Some ( true ) , .. }
2025
2040
| NativeLibKind :: Static { whole_archive : Some ( true ) , .. } => {
2026
- cmd. link_whole_staticlib ( name, verbatim, & search_path) ;
2041
+ cmd. link_whole_staticlib (
2042
+ name,
2043
+ verbatim,
2044
+ & search_path. get_or_init ( || archive_search_paths ( sess) ) ,
2045
+ ) ;
2027
2046
}
2028
2047
NativeLibKind :: Static { .. } => cmd. link_staticlib ( name, verbatim) ,
2029
2048
NativeLibKind :: RawDylib => {
@@ -2116,6 +2135,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
2116
2135
}
2117
2136
2118
2137
let mut compiler_builtins = None ;
2138
+ let search_path = OnceCell :: new ( ) ;
2119
2139
2120
2140
for & cnum in deps. iter ( ) {
2121
2141
if group_start == Some ( cnum) {
@@ -2149,16 +2169,35 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
2149
2169
// external build system already has the native dependencies defined, and it
2150
2170
// will provide them to the linker itself.
2151
2171
if sess. opts . debugging_opts . link_native_libraries {
2152
- // Skip if this library is the same as the last.
2153
2172
let mut last = None ;
2154
2173
for lib in & codegen_results. crate_info . native_libraries [ & cnum] {
2155
- if lib. name . is_some ( )
2156
- && relevant_lib ( sess, lib)
2157
- && matches ! ( lib. kind, NativeLibKind :: Static { bundle: Some ( false ) , .. } )
2158
- && last != lib. name
2159
- {
2160
- cmd. link_staticlib ( lib. name . unwrap ( ) , lib. verbatim . unwrap_or ( false ) ) ;
2161
- last = lib. name ;
2174
+ if !relevant_lib ( sess, lib) {
2175
+ // Skip libraries if they are disabled by `#[link(cfg=...)]`
2176
+ continue ;
2177
+ }
2178
+
2179
+ // Skip if this library is the same as the last.
2180
+ if last == lib. name {
2181
+ continue ;
2182
+ }
2183
+
2184
+ if let Some ( static_lib_name) = lib. name {
2185
+ if let NativeLibKind :: Static { bundle : Some ( false ) , whole_archive } =
2186
+ lib. kind
2187
+ {
2188
+ let verbatim = lib. verbatim . unwrap_or ( false ) ;
2189
+ if whole_archive == Some ( true ) {
2190
+ cmd. link_whole_staticlib (
2191
+ static_lib_name,
2192
+ verbatim,
2193
+ search_path. get_or_init ( || archive_search_paths ( sess) ) ,
2194
+ ) ;
2195
+ } else {
2196
+ cmd. link_staticlib ( static_lib_name, verbatim) ;
2197
+ }
2198
+
2199
+ last = lib. name ;
2200
+ }
2162
2201
}
2163
2202
}
2164
2203
}
0 commit comments