diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 12fb3ebf7..960f2e26e 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -155,6 +155,12 @@ class Backend: dirname = 'meson-out' return dirname + def get_target_dir_relative_to(self, t, o): + '''Get a target dir relative to another target's directory''' + target_dir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(t)) + othert_dir = os.path.join(self.environment.get_build_dir(), self.get_target_dir(o)) + return os.path.relpath(target_dir, othert_dir) + def get_target_source_dir(self, target): dirname = os.path.join(self.build_to_src, self.get_target_dir(target)) return dirname diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 2d18b0e2b..e4e969690 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -344,6 +344,11 @@ class Vs2010Backend(backends.Backend): def quote_arguments(self, arr): return ['"%s"' % i for i in arr] + def add_project_reference(self, root, include, projid): + ig = ET.SubElement(root, 'ItemGroup') + pref = ET.SubElement(ig, 'ProjectReference', Include=include) + ET.SubElement(pref, 'Project').text = '{%s}' % projid + def create_basic_crap(self, target): project_name = target.name root = ET.Element('Project', {'DefaultTargets': "Build", @@ -537,6 +542,8 @@ class Vs2010Backend(backends.Backend): if lpath in lpaths: lpaths.remove(lpath) lpaths.append(lpath) + elif arg.startswith(('/', '-')): + other.append(arg) # It's ok if we miss libraries with non-standard extensions here. # They will go into the general link arguments. elif arg.endswith('.lib') or arg.endswith('.a'): @@ -907,20 +914,26 @@ class Vs2010Backend(backends.Backend): # *_winlibs that we want to link to are static mingw64 libraries. extra_link_args += compiler.get_option_link_args(self.environment.coredata.compiler_options) (additional_libpaths, additional_links, extra_link_args) = self.split_link_args(extra_link_args.to_native()) - if len(extra_link_args) > 0: - extra_link_args.append('%(AdditionalOptions)') - ET.SubElement(link, "AdditionalOptions").text = ' '.join(extra_link_args) - if len(additional_libpaths) > 0: - additional_libpaths.insert(0, '%(AdditionalLibraryDirectories)') - ET.SubElement(link, 'AdditionalLibraryDirectories').text = ';'.join(additional_libpaths) # Add more libraries to be linked if needed for t in target.get_dependencies(): lobj = self.build.targets[t.get_id()] linkname = os.path.join(down, self.get_target_filename_for_linking(lobj)) if t in target.link_whole_targets: - linkname = compiler.get_link_whole_for(linkname)[0] - additional_links.append(linkname) + # /WHOLEARCHIVE:foo must go into AdditionalOptions + extra_link_args += compiler.get_link_whole_for(linkname) + # To force Visual Studio to build this project even though it + # has no sources, we include a reference to the vcxproj file + # that builds this target. Technically we should add this only + # if the current target has no sources, but it doesn't hurt to + # have 'extra' references. + trelpath = self.get_target_dir_relative_to(t, target) + tvcxproj = os.path.join(trelpath, t.get_id() + '.vcxproj') + tid = self.environment.coredata.target_guids[t.get_id()] + self.add_project_reference(root, tvcxproj, tid) + else: + # Other libraries go into AdditionalDependencies + additional_links.append(linkname) for lib in self.get_custom_target_provided_libraries(target): additional_links.append(self.relpath(lib, self.get_target_dir(target))) additional_objects = [] @@ -929,6 +942,13 @@ class Vs2010Backend(backends.Backend): additional_objects.append(o) for o in custom_objs: additional_objects.append(o) + + if len(extra_link_args) > 0: + extra_link_args.append('%(AdditionalOptions)') + ET.SubElement(link, "AdditionalOptions").text = ' '.join(extra_link_args) + if len(additional_libpaths) > 0: + additional_libpaths.insert(0, '%(AdditionalLibraryDirectories)') + ET.SubElement(link, 'AdditionalLibraryDirectories').text = ';'.join(additional_libpaths) if len(additional_links) > 0: additional_links.append('%(AdditionalDependencies)') ET.SubElement(link, 'AdditionalDependencies').text = ';'.join(additional_links) @@ -1018,9 +1038,8 @@ class Vs2010Backend(backends.Backend): ET.SubElement(root, 'Import', Project='$(VCTargetsPath)\Microsoft.Cpp.targets') # Reference the regen target. - ig = ET.SubElement(root, 'ItemGroup') - pref = ET.SubElement(ig, 'ProjectReference', Include=os.path.join(self.environment.get_build_dir(), 'REGEN.vcxproj')) - ET.SubElement(pref, 'Project').text = self.environment.coredata.regen_guid + regen_vcxproj = os.path.join(self.environment.get_build_dir(), 'REGEN.vcxproj') + self.add_project_reference(root, regen_vcxproj, self.environment.coredata.regen_guid) self._prettyprint_vcxproj_xml(ET.ElementTree(root), ofname) def gen_regenproj(self, project_name, ofname): diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 8c02d1d1c..5f5dd6b38 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -357,7 +357,7 @@ class BuildTarget(Target): self.process_compilers() self.process_kwargs(kwargs, environment) self.check_unknown_kwargs(kwargs) - if not self.sources and not self.generated and not self.objects: + if not any([self.sources, self.generated, self.objects, self.link_whole]): raise InvalidArguments('Build target %s has no sources.' % name) self.process_compilers_late() self.validate_sources() diff --git a/test cases/common/145 whole archive/allofme/meson.build b/test cases/common/145 whole archive/allofme/meson.build new file mode 100644 index 000000000..f5c2027b5 --- /dev/null +++ b/test cases/common/145 whole archive/allofme/meson.build @@ -0,0 +1 @@ +stlib = static_library('allofme', '../libfile.c') diff --git a/test cases/common/145 whole archive/exe/meson.build b/test cases/common/145 whole archive/exe/meson.build new file mode 100644 index 000000000..f47a24627 --- /dev/null +++ b/test cases/common/145 whole archive/exe/meson.build @@ -0,0 +1,2 @@ +exe = executable('prog', '../prog.c', + link_with : dylib) diff --git a/test cases/common/145 whole archive/exe2/meson.build b/test cases/common/145 whole archive/exe2/meson.build new file mode 100644 index 000000000..5365f03b6 --- /dev/null +++ b/test cases/common/145 whole archive/exe2/meson.build @@ -0,0 +1 @@ +exe2 = executable('prog2', '../prog.c', link_with : dylib2) diff --git a/test cases/common/145 whole archive/meson.build b/test cases/common/145 whole archive/meson.build index eadebf8bd..617ae0340 100644 --- a/test cases/common/145 whole archive/meson.build +++ b/test cases/common/145 whole archive/meson.build @@ -1,5 +1,7 @@ project('whole archive', 'c') +add_project_arguments('-I' + meson.source_root(), language : 'c') + cc = meson.get_compiler('c') if cc.get_id() == 'msvc' @@ -8,15 +10,15 @@ if cc.get_id() == 'msvc' endif endif -stlib = static_library('allofme', 'libfile.c') - -# Nothing in dylib.c uses func1, so the linker would throw it -# away and thus linking the exe would fail. -dylib = shared_library('shlib', 'dylib.c', - link_whole : stlib) - -exe = executable('prog', 'prog.c', - link_with : dylib) +subdir('allofme') +subdir('shlib') +subdir('exe') test('prog', exe) +# link_whole only +subdir('stlib') +subdir('wholeshlib') +subdir('exe2') + +test('prog2', exe2) diff --git a/test cases/common/145 whole archive/shlib/meson.build b/test cases/common/145 whole archive/shlib/meson.build new file mode 100644 index 000000000..34a1b78a9 --- /dev/null +++ b/test cases/common/145 whole archive/shlib/meson.build @@ -0,0 +1,4 @@ +# Nothing in dylib.c uses func1, so the linker would throw it +# away and thus linking the exe would fail. +dylib = shared_library('shlib', '../dylib.c', + link_whole : stlib) diff --git a/test cases/common/145 whole archive/stlib/meson.build b/test cases/common/145 whole archive/stlib/meson.build new file mode 100644 index 000000000..07a434e06 --- /dev/null +++ b/test cases/common/145 whole archive/stlib/meson.build @@ -0,0 +1 @@ +static = static_library('static', '../dylib.c') diff --git a/test cases/common/145 whole archive/wholeshlib/meson.build b/test cases/common/145 whole archive/wholeshlib/meson.build new file mode 100644 index 000000000..69a1995ce --- /dev/null +++ b/test cases/common/145 whole archive/wholeshlib/meson.build @@ -0,0 +1 @@ +dylib2 = shared_library('link_whole', link_whole : [stlib, static])