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<dyn ArchiveBuilder<'a> + '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<Symbol>,
+    ) -> 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::<FxHashSet<_>>()
+                } 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<Symbol>,
     ) {
         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<Symbol>,
+    pub filename: Option<Symbol>,
     pub cfg: Option<ast::MetaItem>,
     pub verbatim: Option<bool>,
     pub dll_imports: Vec<cstore::DllImport>,
@@ -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<bool>,
+    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<Symbol>,
+    verbatim: Option<bool>,
+    kind: NativeLibKind,
+    sess: &Session,
+) -> Option<Symbol> {
+    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<NativeLib> {
     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<Symbol>,
+    /// If packed_bundled_libs enabled, actual filename of library is stored.
+    pub filename: Option<Symbol>,
     pub cfg: Option<ast::MetaItem>,
     pub foreign_module: Option<DefId>,
     pub wasm_import_module: Option<Symbol>,
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<usize> = (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)