diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index 0d2aa483d3d4a..bad58d0a8a0a1 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -1,44 +1,16 @@ +use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::memmap::Mmap; use rustc_session::cstore::DllImport; use rustc_session::Session; +use rustc_span::symbol::Symbol; +use object::read::archive::ArchiveFile; + +use std::fmt::Display; +use std::fs::File; use std::io; use std::path::{Path, PathBuf}; -pub(super) fn find_library( - name: &str, - verbatim: bool, - search_paths: &[PathBuf], - sess: &Session, -) -> PathBuf { - // On Windows, static libraries sometimes show up as libfoo.a and other - // times show up as foo.lib - let oslibname = if verbatim { - name.to_string() - } else { - format!("{}{}{}", sess.target.staticlib_prefix, name, sess.target.staticlib_suffix) - }; - let unixlibname = format!("lib{}.a", name); - - for path in search_paths { - debug!("looking for {} inside {:?}", name, path); - let test = path.join(&oslibname); - if test.exists() { - return test; - } - if oslibname != unixlibname { - let test = path.join(&unixlibname); - if test.exists() { - return test; - } - } - } - sess.fatal(&format!( - "could not find native static library `{}`, \ - perhaps an -L flag is missing?", - name - )); -} - pub trait ArchiveBuilderBuilder { fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box + 'a>; @@ -54,6 +26,36 @@ pub trait ArchiveBuilderBuilder { dll_imports: &[DllImport], tmpdir: &Path, ) -> PathBuf; + + fn extract_bundled_libs( + &self, + rlib: &Path, + outdir: &Path, + bundled_lib_file_names: &FxHashSet, + ) -> Result<(), String> { + let message = |msg: &str, e: &dyn Display| format!("{} '{}': {}", msg, &rlib.display(), e); + let archive_map = unsafe { + Mmap::map(File::open(rlib).map_err(|e| message("failed to open file", &e))?) + .map_err(|e| message("failed to mmap file", &e))? + }; + let archive = ArchiveFile::parse(&*archive_map) + .map_err(|e| message("failed to parse archive", &e))?; + + for entry in archive.members() { + let entry = entry.map_err(|e| message("failed to read entry", &e))?; + let data = entry + .data(&*archive_map) + .map_err(|e| message("failed to get data from archive member", &e))?; + let name = std::str::from_utf8(entry.name()) + .map_err(|e| message("failed to convert name", &e))?; + if !bundled_lib_file_names.contains(&Symbol::intern(name)) { + continue; // We need to extract only native libraries. + } + std::fs::write(&outdir.join(&name), data) + .map_err(|e| message("failed to write file", &e))?; + } + Ok(()) + } } pub trait ArchiveBuilder<'a> { diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index a3fed88cc4baa..61c5cff0d43fd 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1,11 +1,13 @@ use rustc_arena::TypedArena; use rustc_ast::CRATE_NODE_ID; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{ErrorGuaranteed, Handler}; use rustc_fs_util::fix_windows_verbatim_for_gcc; use rustc_hir::def_id::CrateNum; +use rustc_metadata::find_native_static_library; use rustc_metadata::fs::{emit_metadata, METADATA_FILENAME}; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::SymbolExportKind; @@ -24,7 +26,7 @@ use rustc_target::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault}; use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo}; use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target}; -use super::archive::{find_library, ArchiveBuilder, ArchiveBuilderBuilder}; +use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; use super::command::Command; use super::linker::{self, Linker}; use super::metadata::{create_rmeta_file, MetadataPosition}; @@ -307,6 +309,9 @@ fn link_rlib<'a>( } } + // Used if packed_bundled_libs flag enabled. + let mut packed_bundled_libs = Vec::new(); + // Note that in this loop we are ignoring the value of `lib.cfg`. That is, // we may not be configured to actually include a static library if we're // adding it here. That's because later when we consume this rlib we'll @@ -325,6 +330,8 @@ fn link_rlib<'a>( // metadata of the rlib we're generating somehow. for lib in codegen_results.crate_info.used_libraries.iter() { match lib.kind { + NativeLibKind::Static { bundle: None | Some(true), whole_archive: Some(true) } + if flavor == RlibFlavor::Normal && sess.opts.unstable_opts.packed_bundled_libs => {} NativeLibKind::Static { bundle: None | Some(true), whole_archive: Some(true) } if flavor == RlibFlavor::Normal => { @@ -348,7 +355,16 @@ fn link_rlib<'a>( } if let Some(name) = lib.name { let location = - find_library(name.as_str(), lib.verbatim.unwrap_or(false), &lib_search_paths, sess); + find_native_static_library(name.as_str(), lib.verbatim, &lib_search_paths, sess); + if sess.opts.unstable_opts.packed_bundled_libs && flavor == RlibFlavor::Normal { + packed_bundled_libs.push(find_native_static_library( + lib.filename.unwrap().as_str(), + Some(true), + &lib_search_paths, + sess, + )); + continue; + } ab.add_archive(&location, Box::new(|_| false)).unwrap_or_else(|e| { sess.fatal(&format!( "failed to add native library {}: {}", @@ -403,6 +419,12 @@ fn link_rlib<'a>( ab.add_file(&trailing_metadata); } + // Add all bundled static native library dependencies. + // Archives added to the end of .rlib archive, see comment above for the reason. + for lib in packed_bundled_libs { + ab.add_file(&lib) + } + return Ok(ab); } @@ -2350,7 +2372,15 @@ fn add_upstream_rust_crates<'a>( let src = &codegen_results.crate_info.used_crate_source[&cnum]; match data[cnum.as_usize() - 1] { _ if codegen_results.crate_info.profiler_runtime == Some(cnum) => { - add_static_crate(cmd, sess, archive_builder_builder, codegen_results, tmpdir, cnum); + add_static_crate( + cmd, + sess, + archive_builder_builder, + codegen_results, + tmpdir, + cnum, + &Default::default(), + ); } // compiler-builtins are always placed last to ensure that they're // linked correctly. @@ -2360,7 +2390,23 @@ fn add_upstream_rust_crates<'a>( } Linkage::NotLinked | Linkage::IncludedFromDylib => {} Linkage::Static => { - add_static_crate(cmd, sess, archive_builder_builder, codegen_results, tmpdir, cnum); + let bundled_libs = if sess.opts.unstable_opts.packed_bundled_libs { + codegen_results.crate_info.native_libraries[&cnum] + .iter() + .filter_map(|lib| lib.filename) + .collect::>() + } else { + Default::default() + }; + add_static_crate( + cmd, + sess, + archive_builder_builder, + codegen_results, + tmpdir, + cnum, + &bundled_libs, + ); // Link static native libs with "-bundle" modifier only if the crate they originate from // is being linked statically to the current crate. If it's linked dynamically @@ -2371,6 +2417,14 @@ fn add_upstream_rust_crates<'a>( // external build system already has the native dependencies defined, and it // will provide them to the linker itself. if sess.opts.unstable_opts.link_native_libraries { + if sess.opts.unstable_opts.packed_bundled_libs { + // If rlib contains native libs as archives, unpack them to tmpdir. + let rlib = &src.rlib.as_ref().unwrap().0; + archive_builder_builder + .extract_bundled_libs(rlib, tmpdir, &bundled_libs) + .unwrap_or_else(|e| sess.fatal(e)); + } + let mut last = (None, NativeLibKind::Unspecified, None); for lib in &codegen_results.crate_info.native_libraries[&cnum] { let Some(name) = lib.name else { @@ -2420,10 +2474,17 @@ fn add_upstream_rust_crates<'a>( | NativeLibKind::Framework { .. } | NativeLibKind::Unspecified | NativeLibKind::RawDylib => {} - NativeLibKind::Static { - bundle: Some(true) | None, - whole_archive: _, - } => {} + NativeLibKind::Static { bundle: Some(true) | None, whole_archive } => { + if sess.opts.unstable_opts.packed_bundled_libs { + // If rlib contains native libs as archives, they are unpacked to tmpdir. + let path = tmpdir.join(lib.filename.unwrap().as_str()); + if whole_archive == Some(true) { + cmd.link_whole_rlib(&path); + } else { + cmd.link_rlib(&path); + } + } + } } } } @@ -2438,7 +2499,15 @@ fn add_upstream_rust_crates<'a>( // was already "included" in a dylib (e.g., `libstd` when `-C prefer-dynamic` // is used) if let Some(cnum) = compiler_builtins { - add_static_crate(cmd, sess, archive_builder_builder, codegen_results, tmpdir, cnum); + add_static_crate( + cmd, + sess, + archive_builder_builder, + codegen_results, + tmpdir, + cnum, + &Default::default(), + ); } // Converts a library file-stem into a cc -l argument @@ -2471,6 +2540,7 @@ fn add_upstream_rust_crates<'a>( codegen_results: &CodegenResults, tmpdir: &Path, cnum: CrateNum, + bundled_lib_file_names: &FxHashSet, ) { let src = &codegen_results.crate_info.used_crate_source[&cnum]; let cratepath = &src.rlib.as_ref().unwrap().0; @@ -2499,6 +2569,7 @@ fn add_upstream_rust_crates<'a>( let dst = tmpdir.join(cratepath.file_name().unwrap()); let name = cratepath.file_name().unwrap().to_str().unwrap(); let name = &name[3..name.len() - 5]; // chop off lib/.rlib + let bundled_lib_file_names = bundled_lib_file_names.clone(); sess.prof.generic_activity_with_arg("link_altering_rlib", name).run(|| { let canonical_name = name.replace('-', "_"); @@ -2532,6 +2603,15 @@ fn add_upstream_rust_crates<'a>( let skip_because_lto = upstream_rust_objects_already_included && is_rust_object && is_builtins; + // We skip native libraries because: + // 1. This native libraries won't be used from the generated rlib, + // so we can throw them away to avoid the copying work. + // 2. We can't allow it to be a single remaining entry in archive + // as some linkers may complain on that. + if bundled_lib_file_names.contains(&Symbol::intern(f)) { + return true; + } + if skip_because_cfg_say_so || skip_because_lto { return true; } diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 949a356fce1fc..e505543b27ca7 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1,4 +1,3 @@ -use super::archive; use super::command::Command; use super::symbol_export; use rustc_span::symbol::sym; @@ -11,6 +10,7 @@ use std::path::{Path, PathBuf}; use std::{env, mem, str}; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; +use rustc_metadata::find_native_static_library; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo, SymbolExportKind}; use rustc_middle::ty::TyCtxt; @@ -514,7 +514,7 @@ impl<'a> Linker for GccLinker<'a> { // -force_load is the macOS equivalent of --whole-archive, but it // involves passing the full path to the library to link. self.linker_arg("-force_load"); - let lib = archive::find_library(lib, verbatim, search_path, &self.sess); + let lib = find_native_static_library(lib, Some(verbatim), search_path, &self.sess); self.linker_arg(&lib); } } diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 52da7abcac54e..4ea75dba47120 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -112,6 +112,7 @@ bitflags::bitflags! { pub struct NativeLib { pub kind: NativeLibKind, pub name: Option, + pub filename: Option, pub cfg: Option, pub verbatim: Option, pub dll_imports: Vec, @@ -121,6 +122,7 @@ impl From<&cstore::NativeLib> for NativeLib { fn from(lib: &cstore::NativeLib) -> Self { NativeLib { kind: lib.kind, + filename: lib.filename, name: lib.name, cfg: lib.cfg.clone(), verbatim: lib.verbatim, diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl index 00067a1bf6ad7..d27100c56aff5 100644 --- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl +++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl @@ -162,6 +162,9 @@ metadata_no_transitive_needs_dep = metadata_failed_write_error = failed to write {$filename}: {$err} +metadata_missing_native_library = + could not find native static library `{$libname}`, perhaps an -L flag is missing? + metadata_failed_create_tempdir = couldn't create a temp dir: {$err} diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 5df5ab3ddc032..c7615a5775e33 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -765,6 +765,7 @@ fn test_unstable_options_tracking_hash() { tracked!(no_profiler_runtime, true); tracked!(oom, OomStrategy::Panic); tracked!(osx_rpath_install_name, true); + tracked!(packed_bundled_libs, true); tracked!(panic_abort_tests, true); tracked!(panic_in_drop, PanicStrategy::Abort); tracked!(pick_stable_methods_before_any_unstable, false); diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 1406ee914afab..7d63fad324006 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -369,6 +369,12 @@ pub struct FailedWriteError { pub err: Error, } +#[derive(SessionDiagnostic)] +#[diag(metadata::missing_native_library)] +pub struct MissingNativeLibrary<'a> { + pub libname: &'a str, +} + #[derive(SessionDiagnostic)] #[diag(metadata::failed_create_tempdir)] pub struct FailedCreateTempdir { diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index 8e0291fc3ad18..57c5ec2f28c65 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -44,4 +44,5 @@ pub mod fs; pub mod locator; pub use fs::{emit_metadata, METADATA_FILENAME}; +pub use native_libs::find_native_static_library; pub use rmeta::{encode_metadata, EncodedMetadata, METADATA_HEADER}; diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 3acabc4e69ce6..cc33ad07db605 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -4,8 +4,10 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_middle::ty::{List, ParamEnv, ParamEnvAnd, Ty, TyCtxt}; +use rustc_session::config::CrateType; use rustc_session::cstore::{DllCallingConvention, DllImport, NativeLib, PeImportNameType}; use rustc_session::parse::feature_err; +use rustc_session::search_paths::PathKind; use rustc_session::utils::NativeLibKind; use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; @@ -16,13 +18,66 @@ use crate::errors::{ FrameworkOnlyWindows, ImportNameTypeForm, ImportNameTypeRaw, ImportNameTypeX86, IncompatibleWasmLink, InvalidLinkModifier, LibFrameworkApple, LinkCfgForm, LinkCfgSinglePredicate, LinkFrameworkApple, LinkKindForm, LinkModifiersForm, LinkNameForm, - LinkOrdinalRawDylib, LinkRequiresName, MultipleCfgs, MultipleImportNameType, - MultipleKindsInLink, MultipleLinkModifiers, MultipleModifiers, MultipleNamesInLink, - MultipleRenamings, MultipleWasmImport, NoLinkModOverride, RawDylibNoNul, RenamingNoLink, - UnexpectedLinkArg, UnknownImportNameType, UnknownLinkKind, UnknownLinkModifier, UnsupportedAbi, - UnsupportedAbiI686, WasmImportForm, WholeArchiveNeedsStatic, + LinkOrdinalRawDylib, LinkRequiresName, MissingNativeLibrary, MultipleCfgs, + MultipleImportNameType, MultipleKindsInLink, MultipleLinkModifiers, MultipleModifiers, + MultipleNamesInLink, MultipleRenamings, MultipleWasmImport, NoLinkModOverride, RawDylibNoNul, + RenamingNoLink, UnexpectedLinkArg, UnknownImportNameType, UnknownLinkKind, UnknownLinkModifier, + UnsupportedAbi, UnsupportedAbiI686, WasmImportForm, WholeArchiveNeedsStatic, }; +use std::path::PathBuf; + +pub fn find_native_static_library( + name: &str, + verbatim: Option, + search_paths: &[PathBuf], + sess: &Session, +) -> PathBuf { + let verbatim = verbatim.unwrap_or(false); + // On Windows, static libraries sometimes show up as libfoo.a and other + // times show up as foo.lib + let oslibname = if verbatim { + name.to_string() + } else { + format!("{}{}{}", sess.target.staticlib_prefix, name, sess.target.staticlib_suffix) + }; + let unixlibname = format!("lib{}.a", name); + + for path in search_paths { + let test = path.join(&oslibname); + if test.exists() { + return test; + } + if oslibname != unixlibname { + let test = path.join(&unixlibname); + if test.exists() { + return test; + } + } + } + sess.emit_fatal(MissingNativeLibrary { libname: name }); +} + +fn find_bundled_library( + name: Option, + verbatim: Option, + kind: NativeLibKind, + sess: &Session, +) -> Option { + if sess.opts.unstable_opts.packed_bundled_libs && + sess.crate_types().iter().any(|ct| ct == &CrateType::Rlib || ct == &CrateType::Staticlib) && + let NativeLibKind::Static { bundle: Some(true) | None, .. } = kind { + find_native_static_library( + name.unwrap().as_str(), + verbatim, + &sess.target_filesearch(PathKind::Native).search_path_dirs(), + sess, + ).file_name().and_then(|s| s.to_str()).map(Symbol::intern) + } else { + None + } +} + pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec { let mut collector = Collector { tcx, libs: Vec::new() }; for id in tcx.hir().items() { @@ -341,9 +396,14 @@ impl<'tcx> Collector<'tcx> { Vec::new() } }; + + let name = name.map(|(name, _)| name); + let kind = kind.unwrap_or(NativeLibKind::Unspecified); + let filename = find_bundled_library(name, verbatim, kind, sess); self.libs.push(NativeLib { - name: name.map(|(name, _)| name), - kind: kind.unwrap_or(NativeLibKind::Unspecified), + name, + filename, + kind, cfg, foreign_module: Some(it.def_id.to_def_id()), wasm_import_module: wasm_import_module.map(|(name, _)| name), @@ -423,8 +483,13 @@ impl<'tcx> Collector<'tcx> { if existing.is_empty() { // Add if not found let new_name: Option<&str> = passed_lib.new_name.as_deref(); + let name = Some(Symbol::intern(new_name.unwrap_or(&passed_lib.name))); + let sess = self.tcx.sess; + let filename = + find_bundled_library(name, passed_lib.verbatim, passed_lib.kind, sess); self.libs.push(NativeLib { - name: Some(Symbol::intern(new_name.unwrap_or(&passed_lib.name))), + name, + filename, kind: passed_lib.kind, cfg: None, foreign_module: None, diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs index 11ef75bb2d4a7..7d4a1e212a417 100644 --- a/compiler/rustc_session/src/cstore.rs +++ b/compiler/rustc_session/src/cstore.rs @@ -68,6 +68,8 @@ pub enum LinkagePreference { pub struct NativeLib { pub kind: NativeLibKind, pub name: Option, + /// If packed_bundled_libs enabled, actual filename of library is stored. + pub filename: Option, pub cfg: Option, pub foreign_module: Option, pub wasm_import_module: Option, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 9f07394b61ab8..a0fb8d2bdcb7f 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1439,6 +1439,8 @@ options! { "pass `-install_name @rpath/...` to the macOS linker (default: no)"), diagnostic_width: Option = (None, parse_opt_number, [UNTRACKED], "set the current output width for diagnostic truncation"), + packed_bundled_libs: bool = (false, parse_bool, [TRACKED], + "change rlib format to store native libraries as archives"), panic_abort_tests: bool = (false, parse_bool, [TRACKED], "support compiling tests with panic=abort (default: no)"), panic_in_drop: PanicStrategy = (PanicStrategy::Unwind, parse_panic_strategy, [TRACKED], diff --git a/src/test/run-make/rlib-format-packed-bundled-libs-2/Makefile b/src/test/run-make/rlib-format-packed-bundled-libs-2/Makefile new file mode 100644 index 0000000000000..4574cf17f0ef0 --- /dev/null +++ b/src/test/run-make/rlib-format-packed-bundled-libs-2/Makefile @@ -0,0 +1,22 @@ +-include ../../run-make-fulldeps/tools.mk + +# ignore-cross-compile + +# Make sure -Zpacked_bundled_libs is compatible with verbatim. + +# We're using the llvm-nm instead of the system nm to ensure it is compatible +# with the LLVM bitcode generated by rustc. +NM = "$(LLVM_BIN_DIR)"/llvm-nm + +all: + # Build strange-named dep. + $(RUSTC) native_dep.rs --crate-type=staticlib -o $(TMPDIR)/native_dep.ext + + $(RUSTC) rust_dep.rs --crate-type=rlib -Zpacked_bundled_libs + $(NM) $(TMPDIR)/librust_dep.rlib | $(CGREP) -e "U.*native_f1" + $(AR) t $(TMPDIR)/librust_dep.rlib | $(CGREP) "native_dep.ext" + + # Make sure compiler doesn't use files, that it shouldn't know about. + rm $(TMPDIR)/native_dep.ext + + $(RUSTC) main.rs --extern rust_dep=$(TMPDIR)/librust_dep.rlib -Zpacked_bundled_libs diff --git a/src/test/run-make/rlib-format-packed-bundled-libs-2/main.rs b/src/test/run-make/rlib-format-packed-bundled-libs-2/main.rs new file mode 100644 index 0000000000000..8d2b8a2859c05 --- /dev/null +++ b/src/test/run-make/rlib-format-packed-bundled-libs-2/main.rs @@ -0,0 +1,5 @@ +extern crate rust_dep; + +pub fn main() { + rust_dep::rust_dep(); +} diff --git a/src/test/run-make/rlib-format-packed-bundled-libs-2/native_dep.rs b/src/test/run-make/rlib-format-packed-bundled-libs-2/native_dep.rs new file mode 100644 index 0000000000000..321a8237e8a4b --- /dev/null +++ b/src/test/run-make/rlib-format-packed-bundled-libs-2/native_dep.rs @@ -0,0 +1,4 @@ +#[no_mangle] +pub fn native_f1() -> i32 { + return 1; +} diff --git a/src/test/run-make/rlib-format-packed-bundled-libs-2/rust_dep.rs b/src/test/run-make/rlib-format-packed-bundled-libs-2/rust_dep.rs new file mode 100644 index 0000000000000..d99dda05cf215 --- /dev/null +++ b/src/test/run-make/rlib-format-packed-bundled-libs-2/rust_dep.rs @@ -0,0 +1,11 @@ +#![feature(native_link_modifiers_verbatim)] +#[link(name = "native_dep.ext", kind = "static", modifiers = "+verbatim")] +extern "C" { + fn native_f1() -> i32; +} + +pub fn rust_dep() { + unsafe { + assert!(native_f1() == 1); + } +} diff --git a/src/test/run-make/rlib-format-packed-bundled-libs/Makefile b/src/test/run-make/rlib-format-packed-bundled-libs/Makefile new file mode 100644 index 0000000000000..0b991ac42e3dc --- /dev/null +++ b/src/test/run-make/rlib-format-packed-bundled-libs/Makefile @@ -0,0 +1,34 @@ +-include ../../run-make-fulldeps/tools.mk + +# ignore-cross-compile + +# Make sure rlib format with -Zpacked_bundled_libs is correct. + +# We're using the llvm-nm instead of the system nm to ensure it is compatible +# with the LLVM bitcode generated by rustc. +NM = "$(LLVM_BIN_DIR)"/llvm-nm + +all: $(call NATIVE_STATICLIB,native_dep_1) $(call NATIVE_STATICLIB,native_dep_2) $(call NATIVE_STATICLIB,native_dep_3) + $(RUSTC) rust_dep_up.rs --crate-type=rlib -Zpacked_bundled_libs + $(NM) $(TMPDIR)/librust_dep_up.rlib | $(CGREP) -e "U.*native_f2" + $(NM) $(TMPDIR)/librust_dep_up.rlib | $(CGREP) -e "U.*native_f3" + $(NM) $(TMPDIR)/librust_dep_up.rlib | $(CGREP) -e "T.*rust_dep_up" + $(AR) t $(TMPDIR)/librust_dep_up.rlib | $(CGREP) "native_dep_2" + $(AR) t $(TMPDIR)/librust_dep_up.rlib | $(CGREP) "native_dep_3" + $(RUSTC) rust_dep_local.rs --extern rlib=$(TMPDIR)/librust_dep_up.rlib -Zpacked_bundled_libs --crate-type=rlib + $(NM) $(TMPDIR)/librust_dep_local.rlib | $(CGREP) -e "U.*native_f1" + $(NM) $(TMPDIR)/librust_dep_local.rlib | $(CGREP) -e "T.*rust_dep_local" + $(AR) t $(TMPDIR)/librust_dep_local.rlib | $(CGREP) "native_dep_1" + + # Make sure compiler doesn't use files, that it shouldn't know about. + rm $(TMPDIR)/*native_dep_* + + $(RUSTC) main.rs --extern lib=$(TMPDIR)/librust_dep_local.rlib -o $(TMPDIR)/main.exe -Zpacked_bundled_libs --print link-args | $(CGREP) -e "native_dep_1.*native_dep_2.*native_dep_3" + +ifndef IS_MSVC + $(NM) $(TMPDIR)/main.exe | $(CGREP) -e "T.*native_f1" + $(NM) $(TMPDIR)/main.exe | $(CGREP) -e "T.*native_f2" + $(NM) $(TMPDIR)/main.exe | $(CGREP) -e "T.*native_f3" + $(NM) $(TMPDIR)/main.exe | $(CGREP) -e "T.*rust_dep_local" + $(NM) $(TMPDIR)/main.exe | $(CGREP) -e "T.*rust_dep_up" +endif diff --git a/src/test/run-make/rlib-format-packed-bundled-libs/main.rs b/src/test/run-make/rlib-format-packed-bundled-libs/main.rs new file mode 100644 index 0000000000000..042a4879fe4e1 --- /dev/null +++ b/src/test/run-make/rlib-format-packed-bundled-libs/main.rs @@ -0,0 +1,4 @@ +extern crate rust_dep_local; +pub fn main() { + rust_dep_local::rust_dep_local(); +} diff --git a/src/test/run-make/rlib-format-packed-bundled-libs/native_dep_1.c b/src/test/run-make/rlib-format-packed-bundled-libs/native_dep_1.c new file mode 100644 index 0000000000000..07be8562c928f --- /dev/null +++ b/src/test/run-make/rlib-format-packed-bundled-libs/native_dep_1.c @@ -0,0 +1 @@ +int native_f1() { return 1; } diff --git a/src/test/run-make/rlib-format-packed-bundled-libs/native_dep_2.c b/src/test/run-make/rlib-format-packed-bundled-libs/native_dep_2.c new file mode 100644 index 0000000000000..a1b94e40dc047 --- /dev/null +++ b/src/test/run-make/rlib-format-packed-bundled-libs/native_dep_2.c @@ -0,0 +1 @@ +int native_f2() { return 2; } diff --git a/src/test/run-make/rlib-format-packed-bundled-libs/native_dep_3.c b/src/test/run-make/rlib-format-packed-bundled-libs/native_dep_3.c new file mode 100644 index 0000000000000..f81f397a4b1d0 --- /dev/null +++ b/src/test/run-make/rlib-format-packed-bundled-libs/native_dep_3.c @@ -0,0 +1 @@ +int native_f3() { return 3; } diff --git a/src/test/run-make/rlib-format-packed-bundled-libs/rust_dep_local.rs b/src/test/run-make/rlib-format-packed-bundled-libs/rust_dep_local.rs new file mode 100644 index 0000000000000..8280c7d6c5156 --- /dev/null +++ b/src/test/run-make/rlib-format-packed-bundled-libs/rust_dep_local.rs @@ -0,0 +1,13 @@ +#[link(name = "native_dep_1", kind = "static")] +extern "C" { + fn native_f1() -> i32; +} + +extern crate rust_dep_up; + +pub fn rust_dep_local() { + unsafe { + assert!(native_f1() == 1); + } + rust_dep_up::rust_dep_up(); +} diff --git a/src/test/run-make/rlib-format-packed-bundled-libs/rust_dep_up.rs b/src/test/run-make/rlib-format-packed-bundled-libs/rust_dep_up.rs new file mode 100644 index 0000000000000..edcd7c5212984 --- /dev/null +++ b/src/test/run-make/rlib-format-packed-bundled-libs/rust_dep_up.rs @@ -0,0 +1,13 @@ +#[link(name = "native_dep_2", kind = "static")] +#[link(name = "native_dep_3", kind = "static")] +extern "C" { + fn native_f2() -> i32; + fn native_f3() -> i32; +} + +pub fn rust_dep_up() { + unsafe { + assert!(native_f2() == 2); + assert!(native_f3() == 3); + } +} diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout index 236469ce9797a..f865e0e881479 100644 --- a/src/test/rustdoc-ui/z-help.stdout +++ b/src/test/rustdoc-ui/z-help.stdout @@ -97,6 +97,7 @@ -Z oom=val -- panic strategy for out-of-memory handling -Z osx-rpath-install-name=val -- pass `-install_name @rpath/...` to the macOS linker (default: no) -Z diagnostic-width=val -- set the current output width for diagnostic truncation + -Z packed-bundled-libs=val -- change rlib format to store native libraries as archives -Z panic-abort-tests=val -- support compiling tests with panic=abort (default: no) -Z panic-in-drop=val -- panic strategy for panics in drops -Z parse-only=val -- parse only; do not compile, assemble, or link (default: no)