Add a list of compilers used to each BuildTarget

When the BuildTarget (executable, shared-library, static-library, etc)
is created, process the source list and assign compilers to this target.
This allows us to do compiler-specific file-naming without resorting to
ugly hacks.

This is one step towards consolidating all the 'what language does this
target use' checks and the 'this target should only have $lang files as
sources' checks we have all over the codebase. All those checks should
be done only when the target is created.
pull/814/head
Nirbheek Chauhan 8 years ago
parent a0551d7d6e
commit 98e7625c64
  1. 76
      mesonbuild/build.py

@ -51,36 +51,16 @@ known_shlib_kwargs.update({'version' : True,
'name_suffix' : True, 'name_suffix' : True,
'vs_module_defs' : True}) 'vs_module_defs' : True})
def sources_are_suffix(sources, suffix): def compilers_are_msvc(compilers):
for source in sources:
if source.endswith('.' + suffix):
return True
return False
def compiler_is_msvc(sources, is_cross, env):
""" """
Since each target does not currently have the compiler information attached Check if all the listed compilers are MSVC. Used by Executable,
to it, we must do this detection manually here. StaticLibrary, and SharedLibrary for deciding when to use MSVC-specific
file naming.
This detection is purposely incomplete and will cause bugs if other code is
extended and this piece of code is forgotten.
""" """
compiler = None for compiler in compilers.values():
if sources_are_suffix(sources, 'c'): if compiler.get_id() != 'msvc':
try:
compiler = env.detect_c_compiler(is_cross)
except MesonException:
return False
elif sources_are_suffix(sources, 'cxx') or \
sources_are_suffix(sources, 'cpp') or \
sources_are_suffix(sources, 'cc'):
try:
compiler = env.detect_cpp_compiler(is_cross)
except MesonException:
return False return False
if compiler and compiler.get_id() == 'msvc':
return True return True
return False
class InvalidArguments(MesonException): class InvalidArguments(MesonException):
@ -234,7 +214,9 @@ class BuildTarget():
self.subdir = subdir self.subdir = subdir
self.subproject = subproject # Can not be calculated from subdir as subproject dirname can be changed per project. self.subproject = subproject # Can not be calculated from subdir as subproject dirname can be changed per project.
self.is_cross = is_cross self.is_cross = is_cross
self.environment = environment
self.sources = [] self.sources = []
self.compilers = {}
self.objects = [] self.objects = []
self.external_deps = [] self.external_deps = []
self.include_dirs = [] self.include_dirs = []
@ -256,6 +238,7 @@ class BuildTarget():
len(self.generated) == 0 and \ len(self.generated) == 0 and \
len(self.objects) == 0: len(self.objects) == 0:
raise InvalidArguments('Build target %s has no sources.' % name) raise InvalidArguments('Build target %s has no sources.' % name)
self.process_compilers()
self.validate_sources() self.validate_sources()
def __repr__(self): def __repr__(self):
@ -320,6 +303,27 @@ class BuildTarget():
msg = 'Bad source of type {!r} in target {!r}.'.format(type(s).__name__, self.name) msg = 'Bad source of type {!r} in target {!r}.'.format(type(s).__name__, self.name)
raise InvalidArguments(msg) raise InvalidArguments(msg)
@staticmethod
def can_compile_remove_sources(compiler, sources):
removed = False
for s in sources[:]:
if compiler.can_compile(s):
sources.remove(s)
removed = True
return removed
def process_compilers(self):
if len(self.sources) == 0:
return
sources = list(self.sources)
if self.is_cross:
compilers = self.environment.coredata.cross_compilers
else:
compilers = self.environment.coredata.compilers
for lang, compiler in compilers.items():
if self.can_compile_remove_sources(compiler, sources):
self.compilers[lang] = compiler
def validate_sources(self): def validate_sources(self):
if len(self.sources) > 0: if len(self.sources) > 0:
firstname = self.sources[0] firstname = self.sources[0]
@ -768,7 +772,7 @@ class Executable(BuildTarget):
self.prefix = '' self.prefix = ''
if not hasattr(self, 'suffix'): if not hasattr(self, 'suffix'):
# Executable for Windows or C#/Mono # Executable for Windows or C#/Mono
if for_windows(is_cross, environment) or sources_are_suffix(self.sources, 'cs'): if for_windows(is_cross, environment) or 'cs' in self.compilers:
self.suffix = 'exe' self.suffix = 'exe'
else: else:
self.suffix = '' self.suffix = ''
@ -777,8 +781,7 @@ class Executable(BuildTarget):
self.filename += '.' + self.suffix self.filename += '.' + self.suffix
# See determine_debug_filenames() in build.SharedLibrary # See determine_debug_filenames() in build.SharedLibrary
buildtype = environment.coredata.get_builtin_option('buildtype') buildtype = environment.coredata.get_builtin_option('buildtype')
if compiler_is_msvc(self.sources, is_cross, environment) and \ if compilers_are_msvc(self.compilers) and buildtype.startswith('debug'):
buildtype.startswith('debug'):
self.debug_filename = self.prefix + self.name + '.pdb' self.debug_filename = self.prefix + self.name + '.pdb'
def type_suffix(self): def type_suffix(self):
@ -787,7 +790,7 @@ class Executable(BuildTarget):
class StaticLibrary(BuildTarget): class StaticLibrary(BuildTarget):
def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs): def __init__(self, name, subdir, subproject, is_cross, sources, objects, environment, kwargs):
super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs) super().__init__(name, subdir, subproject, is_cross, sources, objects, environment, kwargs)
if sources_are_suffix(self.sources, 'cs'): if 'cs' in self.compilers:
raise InvalidArguments('Static libraries not supported for C#.') raise InvalidArguments('Static libraries not supported for C#.')
# By default a static library is named libfoo.a even on Windows because # By default a static library is named libfoo.a even on Windows because
# MSVC does not have a consistent convention for what static libraries # MSVC does not have a consistent convention for what static libraries
@ -800,15 +803,14 @@ class StaticLibrary(BuildTarget):
self.prefix = 'lib' self.prefix = 'lib'
if not hasattr(self, 'suffix'): if not hasattr(self, 'suffix'):
# Rust static library crates have .rlib suffix # Rust static library crates have .rlib suffix
if sources_are_suffix(self.sources, 'rs'): if 'rust' in self.compilers:
self.suffix = 'rlib' self.suffix = 'rlib'
else: else:
self.suffix = 'a' self.suffix = 'a'
self.filename = self.prefix + self.name + '.' + self.suffix self.filename = self.prefix + self.name + '.' + self.suffix
# See determine_debug_filenames() in build.SharedLibrary # See determine_debug_filenames() in build.SharedLibrary
buildtype = environment.coredata.get_builtin_option('buildtype') buildtype = environment.coredata.get_builtin_option('buildtype')
if compiler_is_msvc(self.sources, is_cross, environment) and \ if compilers_are_msvc(self.compilers) and buildtype.startswith('debug'):
buildtype.startswith('debug'):
self.debug_filename = self.prefix + self.name + '.pdb' self.debug_filename = self.prefix + self.name + '.pdb'
def type_suffix(self): def type_suffix(self):
@ -864,12 +866,12 @@ class SharedLibrary(BuildTarget):
if self.prefix != None and self.suffix != None: if self.prefix != None and self.suffix != None:
pass pass
# C# and Mono # C# and Mono
elif sources_are_suffix(self.sources, 'cs'): elif 'cs' in self.compilers:
prefix = '' prefix = ''
suffix = 'dll' suffix = 'dll'
self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}' self.filename_tpl = '{0.prefix}{0.name}.{0.suffix}'
# Rust # Rust
elif sources_are_suffix(self.sources, 'rs'): elif 'rust' in self.compilers:
# Currently, we always build --crate-type=rlib # Currently, we always build --crate-type=rlib
prefix = 'lib' prefix = 'lib'
suffix = 'rlib' suffix = 'rlib'
@ -881,7 +883,7 @@ class SharedLibrary(BuildTarget):
suffix = 'dll' suffix = 'dll'
self.vs_import_filename = '{0}.lib'.format(self.name) self.vs_import_filename = '{0}.lib'.format(self.name)
self.gcc_import_filename = 'lib{0}.dll.a'.format(self.name) self.gcc_import_filename = 'lib{0}.dll.a'.format(self.name)
if compiler_is_msvc(self.sources, is_cross, env): if compilers_are_msvc(self.compilers):
# Shared library is of the form foo.dll # Shared library is of the form foo.dll
prefix = '' prefix = ''
# Import library is called foo.lib # Import library is called foo.lib
@ -928,7 +930,7 @@ class SharedLibrary(BuildTarget):
determine_filenames() above. determine_filenames() above.
""" """
buildtype = env.coredata.get_builtin_option('buildtype') buildtype = env.coredata.get_builtin_option('buildtype')
if compiler_is_msvc(self.sources, is_cross, env) and buildtype.startswith('debug'): if compilers_are_msvc(self.compilers) and buildtype.startswith('debug'):
# Currently we only implement separate debug symbol files for MSVC # Currently we only implement separate debug symbol files for MSVC
# since the toolchain does it for us. Other toolchains embed the # since the toolchain does it for us. Other toolchains embed the
# debugging symbols in the file itself by default. # debugging symbols in the file itself by default.

Loading…
Cancel
Save