diff --git a/docs/markdown/snippets/uninstalled_static_linker.md b/docs/markdown/snippets/uninstalled_static_linker.md new file mode 100644 index 000000000..cd2e4b0c8 --- /dev/null +++ b/docs/markdown/snippets/uninstalled_static_linker.md @@ -0,0 +1,11 @@ +## More efficient static linking of uninstalled libraries + +A somewhat common use case of [[static_library]] is to create uninstalled +internal convenience libraries which are solely meant to be linked to other +targets. Some build systems call these "object libraries". Meson's +implementation does always create a static archive. + +This will now check to see if the static linker supports "thin archives" +(archives which do not contain the actual object code, only references to their +location on disk) and if so, use them to minimize space usage and speed up +linking. diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 2e2ff6d1b..a053be621 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -2790,7 +2790,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) if target.import_filename: commands += linker.gen_import_library_args(self.get_import_filename(target)) elif isinstance(target, build.StaticLibrary): - commands += linker.get_std_link_args() + commands += linker.get_std_link_args(not target.should_install()) else: raise RuntimeError('Unknown build target type.') return commands diff --git a/mesonbuild/linkers/linkers.py b/mesonbuild/linkers/linkers.py index bbd6c4611..9332baa96 100644 --- a/mesonbuild/linkers/linkers.py +++ b/mesonbuild/linkers/linkers.py @@ -59,7 +59,7 @@ class StaticLinker: def get_exelist(self) -> T.List[str]: return self.exelist.copy() - def get_std_link_args(self) -> T.List[str]: + def get_std_link_args(self, is_thin: bool) -> T.List[str]: return [] def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]: @@ -176,7 +176,7 @@ class ArLikeLinker(StaticLinker): # in fact, only the 'ar' id can return False - def get_std_link_args(self) -> T.List[str]: + def get_std_link_args(self, is_thin: bool) -> T.List[str]: return self.std_args def get_output_args(self, target: str) -> T.List[str]: @@ -193,17 +193,28 @@ class ArLinker(ArLikeLinker): super().__init__(exelist) stdo = mesonlib.Popen_safe(self.exelist + ['-h'])[1] # Enable deterministic builds if they are available. + stdargs = 'csr' + thinargs = '' if '[D]' in stdo: - self.std_args = ['csrD'] - else: - self.std_args = ['csrD'] + stdargs += 'D' + if '[T]' in stdo: + thinargs = 'T' + self.std_args = [stdargs] + self.std_thin_args = [stdargs + thinargs] self.can_rsp = '@<' in stdo def can_linker_accept_rsp(self) -> bool: return self.can_rsp + def get_std_link_args(self, is_thin: bool) -> T.List[str]: + # FIXME: osx ld rejects this: "file built for unknown-unsupported file format" + if is_thin and not mesonlib.is_osx(): + return self.std_thin_args + else: + return self.std_args + -class ArmarLinker(ArLikeLinker): # lgtm [py/missing-call-to-init] +class ArmarLinker(ArLikeLinker): id = 'armar' @@ -214,7 +225,7 @@ class DLinker(StaticLinker): self.arch = arch self.__rsp_syntax = rsp_syntax - def get_std_link_args(self) -> T.List[str]: + def get_std_link_args(self, is_thin: bool) -> T.List[str]: return ['-lib'] def get_output_args(self, target: str) -> T.List[str]: @@ -1114,7 +1125,7 @@ class PGIStaticLinker(StaticLinker): self.id = 'ar' self.std_args = ['-r'] - def get_std_link_args(self) -> T.List[str]: + def get_std_link_args(self, is_thin: bool) -> T.List[str]: return self.std_args def get_output_args(self, target: str) -> T.List[str]: diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py index 707fc1d07..9468fd544 100644 --- a/unittests/allplatformstests.py +++ b/unittests/allplatformstests.py @@ -1447,7 +1447,7 @@ class AllPlatformTests(BasePlatformTests): link_cmd = ['ar', 'csr', outfile, objectfile] link_cmd = linker.get_exelist() link_cmd += linker.get_always_args() - link_cmd += linker.get_std_link_args() + link_cmd += linker.get_std_link_args(False) link_cmd += linker.get_output_args(outfile) link_cmd += [objectfile] self.pbcompile(compiler, source, objectfile, extra_args=extra_args)