From 2885c517b081045135986c20b6967153c4e9e511 Mon Sep 17 00:00:00 2001 From: Nuri Amari Date: Fri, 21 Feb 2025 13:26:31 -0800 Subject: [PATCH] Add option to use thin archives and --start-lib --end-lib style linker invocations (attempt 2) Summary: When linking an executable, each apple_library depended upon is usually packaged as a static archive. While we want archive linking semantics, we often don't want the archive itself. We may instead pass the archive members to the linker between --start-lib and --end-lib flags without ever creating the archive. The hope is that by avoiding building the archive at all, we may speed up builds and save on RE resources. For the time being, this change excludes distributed thin-LTO, but that will come as a follow up. This change was reverted a couple times, but only because changes to the linker invocation crafting logic this depends upon caused issues. This is a non functional change on its own. Reviewed By: rmaz Differential Revision: D69948536 fbshipit-source-id: 41a41dfd482ec316bc7baad7db09375cf9db9295 --- prelude/cxx/cxx_library.bzl | 11 +++++++++-- prelude/linking/link_info.bzl | 11 ++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/prelude/cxx/cxx_library.bzl b/prelude/cxx/cxx_library.bzl index 29ac418ee9c0b..ca89aca0855df 100644 --- a/prelude/cxx/cxx_library.bzl +++ b/prelude/cxx/cxx_library.bzl @@ -1609,8 +1609,15 @@ def _static_library( # object files instead of the originating objects. object_external_debug_info = [] if linker_type == LinkerType("darwin"): - object_external_debug_info.append(archive.artifact) - object_external_debug_info.extend(archive.external_objects) + if archive.external_objects: + # On Darwin, when using virtual archives, object files are passed + # to the linker directly between --start-lib --end-lib flags to + # achieve archive semantics without creating the archive. Providing + # the archive artifact as an input here is unnecessary. + object_external_debug_info.extend(archive.external_objects) + else: + # For normal archives, we just need to provide the archive artifact + object_external_debug_info.append(archive.artifact) elif objects_have_external_debug_info: object_external_debug_info.extend(objects) diff --git a/prelude/linking/link_info.bzl b/prelude/linking/link_info.bzl index 4c286cab7a59f..49386f2cdafbb 100644 --- a/prelude/linking/link_info.bzl +++ b/prelude/linking/link_info.bzl @@ -247,7 +247,16 @@ def _is_linkable_comprised_of_object_files_or_a_lazy_archive(linkable: LinkableT # Adds appropriate args representing `linkable` to `args` def append_linkable_args(args: cmd_args, linkable: LinkableTypes): if isinstance(linkable, ArchiveLinkable): - if linkable.link_whole: + if linkable.linker_type == LinkerType("darwin") and linkable.archive.external_objects: + if not linkable.link_whole: + args.add("-Wl,--start-lib") + + for object in linkable.archive.external_objects: + args.add(object) + + if not linkable.link_whole: + args.add("-Wl,--end-lib") + elif linkable.link_whole: args.add(get_link_whole_args(linkable.linker_type, [linkable.archive.artifact])) else: args.add(linkable.archive.artifact)