From bbb6f2c51ce2c5d6a6dffa720dc5cdd1ddf1fb50 Mon Sep 17 00:00:00 2001 From: Chun-wei Fan Date: Wed, 26 May 2021 16:55:35 +0800 Subject: [PATCH] ninjabackend.py: Implement `link_whole:` for pre-VS2015 ...Update 2, to be exact, since the Visual Studio linker only gained the `/WHOLEARCHIVE:` feature since Visual Studio 2015 Update 2. This checks whether we have the corresponding `cl.exe` which is versioned at or after Visual Studio 2015 Update 2 before we try to apply the `/WHOLEARCHIVE:xxx` linker flag. If we aren't, use built-in methods in Meson to grab the object files of the dependent static lib's, along with the objects that were `link_whole:`'ed into them, and feed this list into the linker instead. This would make `link_whole:` work on Visual Studio 2015 Update 1 and earlier, including previous Visual Studio versions. --- mesonbuild/backend/ninjabackend.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 42083400c..525e05147 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -33,6 +33,7 @@ from ..arglist import CompilerArgs from ..compilers import ( Compiler, CCompiler, FortranCompiler, + mixins, PGICCompiler, VisualStudioLikeCompiler, ) @@ -43,7 +44,7 @@ from ..mesonlib import ( ) from ..mesonlib import get_compiler_for_source, has_path_sep, OptionKey from .backends import CleanTrees -from ..build import GeneratedList, InvalidArguments +from ..build import GeneratedList, InvalidArguments, ExtractedObjects from ..interpreter import Interpreter if T.TYPE_CHECKING: @@ -2701,8 +2702,24 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) return commands def get_link_whole_args(self, linker, target): - target_args = self.build_target_link_arguments(linker, target.link_whole_targets) - return linker.get_link_whole_for(target_args) if target_args else [] + use_custom = False + if isinstance(linker, mixins.visualstudio.MSVCCompiler): + # Expand our object lists manually if we are on pre-Visual Studio 2015 Update 2 + # (incidentally, the "linker" here actually refers to cl.exe) + if mesonlib.version_compare(linker.version, '<19.00.23918'): + use_custom = True + + if use_custom: + objects_from_static_libs: T.List[ExtractedObjects] = [] + for dep in target.link_whole_targets: + l = dep.extract_all_objects(False) + objects_from_static_libs += self.determine_ext_objs(l, '') + objects_from_static_libs.extend(self.flatten_object_list(dep)) + + return objects_from_static_libs + else: + target_args = self.build_target_link_arguments(linker, target.link_whole_targets) + return linker.get_link_whole_for(target_args) if target_args else [] @lru_cache(maxsize=None) def guess_library_absolute_path(self, linker, libname, search_dirs, patterns):