Consider compilers used in static_library parents

Currently meson only considers what compiler/linker were used by a
Target's immediate sources or objects, not the sources of libraries it's
linked with by the link_with and link_while keywords. This means that if
given 3 libraries: libA which is C++, libB which is C, and libC which is
also C, and libC links with libB which links with libA then linking libC
will be attempted with the C linker, and will fail.

This patch corrects that by adding the compilers used by sub libraries
to the collection of compilers considered by meson when picking a
linker.

This adds a new process_compilers_late method to the BuildTarget class,
which is evaluated after process_kwargs is called. This is needed
because some D options need to be evaluated after compilers are
selected, while for C-like languages we need to check the link* targets
for language requirements, and link* targets are passed by kwargs.

This implementation is recursive, since each Target adds it's parent's
dependencies.
pull/2326/head
Dylan Baker 7 years ago
parent 59a90309ab
commit d5003c2190
  1. 43
      mesonbuild/build.py
  2. 0
      test cases/common/146 C and CPP link/dummy.c
  3. 36
      test cases/common/146 C and CPP link/meson.build
  4. 19
      test cases/common/146 C and CPP link/sub.c
  5. 16
      test cases/common/146 C and CPP link/sub.h

@ -359,6 +359,7 @@ class BuildTarget(Target):
self.check_unknown_kwargs(kwargs)
if not self.sources and not self.generated and not self.objects:
raise InvalidArguments('Build target %s has no sources.' % name)
self.process_compilers_late()
self.validate_sources()
self.validate_cross_install(environment)
@ -439,6 +440,39 @@ class BuildTarget(Target):
removed = True
return removed
def process_compilers_late(self):
"""Processes additional compilers after kwargs have been evaluated.
This can add extra compilers that might be required by keyword
arguments, such as link_with or dependencies. It will also try to guess
which compiler to use if one hasn't been selected already.
"""
# Populate list of compilers
if self.is_cross:
compilers = self.environment.coredata.cross_compilers
else:
compilers = self.environment.coredata.compilers
# If this library is linked against another library we need to consider
# the languages of those libraries as well.
if self.link_targets or self.link_whole_targets:
extra = set()
for t in itertools.chain(self.link_targets, self.link_whole_targets):
for name, compiler in t.compilers.items():
if name in clike_langs:
extra.add((name, compiler))
for name, compiler in sorted(extra, key=lambda p: sort_clike(p[0])):
self.compilers[name] = compiler
if not self.compilers:
# No source files or parent targets, target consists of only object
# files of unknown origin. Just add the first clike compiler
# that we have and hope that it can link these objects
for lang in clike_langs:
if lang in compilers:
self.compilers[lang] = compilers[lang]
break
def process_compilers(self):
'''
Populate self.compilers, which is the list of compilers that this
@ -487,14 +521,7 @@ class BuildTarget(Target):
# Re-sort according to clike_langs
self.compilers = OrderedDict(sorted(self.compilers.items(),
key=lambda t: sort_clike(t[0])))
else:
# No source files, target consists of only object files of unknown
# origin. Just add the first clike compiler that we have and hope
# that it can link these objects
for lang in clike_langs:
if lang in compilers:
self.compilers[lang] = compilers[lang]
break
# If all our sources are Vala, our target also needs the C compiler but
# it won't get added above.
if 'vala' in self.compilers and 'c' not in self.compilers:

@ -65,10 +65,44 @@ libfoo = shared_library(
#
# VS2010 lacks the /WHOLEARCHIVE option that later versions of MSVC support, so
# don't run this tests on that backend.
if meson.backend() != 'vs2010'
if not (cxx.get_id() == 'msvc' and cxx.version().version_compare('<19'))
libfoowhole = shared_library(
'foowhole',
['foobar.c', 'foobar.h'],
link_whole : [libc, libcpp],
)
endif
# Test sublinking (linking C and C++, then linking that to C)
libfoo_static = static_library(
'foo_static',
['foobar.c', 'foobar.h'],
link_with : [libc, libcpp],
)
libsub = shared_library(
'sub',
['sub.c', 'sub.h'],
link_with : libfoo_static,
)
if not (cxx.get_id() == 'msvc' and cxx.version().version_compare('<19'))
libsubwhole = shared_library(
'subwhole',
['sub.c', 'sub.h'],
link_whole : libfoo_static,
)
endif
# Test that it really is recursive
libsub_static = static_library(
'sub_static',
['sub.c', 'sub.h'],
link_with : libfoo_static,
)
libsubsub = shared_library(
'subsub',
['dummy.c'],
link_with : libsub_static,
)

@ -0,0 +1,19 @@
/* Copyright © 2017 Dylan Baker
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "sub.h"
float a_half(void) {
return .5;
}

@ -0,0 +1,16 @@
/* Copyright © 2017 Dylan Baker
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
float a_half(void);
Loading…
Cancel
Save