|
|
|
@ -19,6 +19,7 @@ from .. import build |
|
|
|
|
from .. import mlog |
|
|
|
|
from .. import dependencies |
|
|
|
|
from .. import compilers |
|
|
|
|
from ..compilers import CompilerArgs |
|
|
|
|
from ..mesonlib import File, MesonException, get_compiler_for_source, Popen_safe |
|
|
|
|
from .backends import CleanTrees, InstallData |
|
|
|
|
from ..build import InvalidArguments |
|
|
|
@ -1725,7 +1726,7 @@ rule FORTRAN_DEP_HACK |
|
|
|
|
|
|
|
|
|
def generate_llvm_ir_compile(self, target, outfile, src): |
|
|
|
|
compiler = get_compiler_for_source(target.compilers.values(), src) |
|
|
|
|
commands = [] |
|
|
|
|
commands = CompilerArgs(compiler) |
|
|
|
|
# Compiler args for compiling this target |
|
|
|
|
commands += compilers.get_base_compile_args(self.environment.coredata.base_options, |
|
|
|
|
compiler) |
|
|
|
@ -1748,11 +1749,40 @@ rule FORTRAN_DEP_HACK |
|
|
|
|
# Write the Ninja build command |
|
|
|
|
compiler_name = 'llvm_ir{}_COMPILER'.format('_CROSS' if target.is_cross else '') |
|
|
|
|
element = NinjaBuildElement(self.all_outputs, rel_obj, compiler_name, rel_src) |
|
|
|
|
commands = self.dedup_arguments(commands) |
|
|
|
|
# Convert from GCC-style link argument naming to the naming used by the |
|
|
|
|
# current compiler. |
|
|
|
|
commands = commands.to_native() |
|
|
|
|
element.add_item('ARGS', commands) |
|
|
|
|
element.write(outfile) |
|
|
|
|
return rel_obj |
|
|
|
|
|
|
|
|
|
def get_source_dir_include_args(self, target, compiler): |
|
|
|
|
curdir = target.get_subdir() |
|
|
|
|
tmppath = os.path.normpath(os.path.join(self.build_to_src, curdir)) |
|
|
|
|
return compiler.get_include_args(tmppath, False) |
|
|
|
|
|
|
|
|
|
def get_build_dir_include_args(self, target, compiler): |
|
|
|
|
curdir = target.get_subdir() |
|
|
|
|
if curdir == '': |
|
|
|
|
curdir = '.' |
|
|
|
|
return compiler.get_include_args(curdir, False) |
|
|
|
|
|
|
|
|
|
def get_custom_target_dir_include_args(self, target, compiler): |
|
|
|
|
custom_target_include_dirs = [] |
|
|
|
|
for i in target.get_generated_sources(): |
|
|
|
|
# Generator output goes into the target private dir which is |
|
|
|
|
# already in the include paths list. Only custom targets have their |
|
|
|
|
# own target build dir. |
|
|
|
|
if not isinstance(i, build.CustomTarget): |
|
|
|
|
continue |
|
|
|
|
idir = self.get_target_dir(i) |
|
|
|
|
if idir not in custom_target_include_dirs: |
|
|
|
|
custom_target_include_dirs.append(idir) |
|
|
|
|
incs = [] |
|
|
|
|
for i in custom_target_include_dirs: |
|
|
|
|
incs += compiler.get_include_args(i, False) |
|
|
|
|
return incs |
|
|
|
|
|
|
|
|
|
def generate_single_compile(self, target, outfile, src, is_generated=False, header_deps=[], order_deps=[]): |
|
|
|
|
""" |
|
|
|
|
Compiles C/C++, ObjC/ObjC++, Fortran, and D sources |
|
|
|
@ -1763,30 +1793,40 @@ rule FORTRAN_DEP_HACK |
|
|
|
|
raise AssertionError('BUG: sources should not contain headers {!r}'.format(src.fname)) |
|
|
|
|
extra_orderdeps = [] |
|
|
|
|
compiler = get_compiler_for_source(target.compilers.values(), src) |
|
|
|
|
commands = [] |
|
|
|
|
# The first thing is implicit include directories: source, build and private. |
|
|
|
|
commands += compiler.get_include_args(self.get_target_private_dir(target), False) |
|
|
|
|
# Compiler args for compiling this target |
|
|
|
|
|
|
|
|
|
# Create an empty commands list, and start adding arguments from |
|
|
|
|
# various sources in the order in which they must override each other |
|
|
|
|
commands = CompilerArgs(compiler) |
|
|
|
|
# Add compiler args for compiling this target derived from 'base' build |
|
|
|
|
# options passed on the command-line, in default_options, etc. |
|
|
|
|
# These have the lowest priority. |
|
|
|
|
commands += compilers.get_base_compile_args(self.environment.coredata.base_options, |
|
|
|
|
compiler) |
|
|
|
|
# Add the root source and build directories as include dirs |
|
|
|
|
curdir = target.get_subdir() |
|
|
|
|
tmppath = os.path.normpath(os.path.join(self.build_to_src, curdir)) |
|
|
|
|
src_inc = compiler.get_include_args(tmppath, False) |
|
|
|
|
if curdir == '': |
|
|
|
|
curdir = '.' |
|
|
|
|
build_inc = compiler.get_include_args(curdir, False) |
|
|
|
|
commands += build_inc + src_inc |
|
|
|
|
# -I args work differently than other ones. In them the first found |
|
|
|
|
# directory is used whereas for other flags (such as -ffoo -fno-foo) the |
|
|
|
|
# latest one is used. Therefore put the internal include directories |
|
|
|
|
# here before generating the "basic compiler args" so they override args |
|
|
|
|
# coming from e.g. pkg-config. |
|
|
|
|
# The code generated by valac is usually crap and has tons of unused |
|
|
|
|
# variables and such, so disable warnings for Vala C sources. |
|
|
|
|
no_warn_args = (is_generated == 'vala') |
|
|
|
|
# Add compiler args and include paths from several sources; defaults, |
|
|
|
|
# build options, external dependencies, etc. |
|
|
|
|
commands += self.generate_basic_compiler_args(target, compiler, no_warn_args) |
|
|
|
|
# Add include dirs from the `include_directories:` kwarg on the target |
|
|
|
|
# and from `include_directories:` of internal deps of the target. |
|
|
|
|
# |
|
|
|
|
# Target include dirs should override internal deps include dirs. |
|
|
|
|
# |
|
|
|
|
# Include dirs from internal deps should override include dirs from |
|
|
|
|
# external deps. |
|
|
|
|
for i in target.get_include_dirs(): |
|
|
|
|
basedir = i.get_curdir() |
|
|
|
|
for d in i.get_incdirs(): |
|
|
|
|
# Avoid superfluous '/.' at the end of paths when d is '.' |
|
|
|
|
if d not in ('', '.'): |
|
|
|
|
expdir = os.path.join(basedir, d) |
|
|
|
|
else: |
|
|
|
|
expdir = basedir |
|
|
|
|
srctreedir = os.path.join(self.build_to_src, expdir) |
|
|
|
|
# Add source subdir first so that the build subdir overrides it |
|
|
|
|
sargs = compiler.get_include_args(srctreedir, i.is_system) |
|
|
|
|
commands += sargs |
|
|
|
|
# There may be include dirs where a build directory has not been |
|
|
|
|
# created for some source dir. For example if someone does this: |
|
|
|
|
# |
|
|
|
@ -1797,20 +1837,32 @@ rule FORTRAN_DEP_HACK |
|
|
|
|
bargs = compiler.get_include_args(expdir, i.is_system) |
|
|
|
|
else: |
|
|
|
|
bargs = [] |
|
|
|
|
sargs = compiler.get_include_args(srctreedir, i.is_system) |
|
|
|
|
commands += bargs |
|
|
|
|
commands += sargs |
|
|
|
|
for d in i.get_extra_build_dirs(): |
|
|
|
|
commands += compiler.get_include_args(d, i.is_system) |
|
|
|
|
commands += self.generate_basic_compiler_args(target, compiler, |
|
|
|
|
# The code generated by valac is usually crap |
|
|
|
|
# and has tons of unused variables and such, |
|
|
|
|
# so disable warnings for Vala C sources. |
|
|
|
|
no_warn_args=(is_generated == 'vala')) |
|
|
|
|
for d in target.external_deps: |
|
|
|
|
if d.need_threads(): |
|
|
|
|
commands += compiler.thread_flags() |
|
|
|
|
break |
|
|
|
|
# Add per-target compile args, f.ex, `c_args : ['-DFOO']`. We set these |
|
|
|
|
# near the end since these are supposed to override everything else. |
|
|
|
|
commands += self.escape_extra_args(compiler, |
|
|
|
|
target.get_extra_args(compiler.get_language())) |
|
|
|
|
# Add source dir and build dir. Project-specific and target-specific |
|
|
|
|
# include paths must override per-target compile args, include paths |
|
|
|
|
# from external dependencies, internal dependencies, and from |
|
|
|
|
# per-target `include_directories:` |
|
|
|
|
# |
|
|
|
|
# We prefer headers in the build dir and the custom target dir over the |
|
|
|
|
# source dir since, for instance, the user might have an |
|
|
|
|
# srcdir == builddir Autotools build in their source tree. Many |
|
|
|
|
# projects that are moving to Meson have both Meson and Autotools in |
|
|
|
|
# parallel as part of the transition. |
|
|
|
|
commands += self.get_source_dir_include_args(target, compiler) |
|
|
|
|
commands += self.get_custom_target_dir_include_args(target, compiler) |
|
|
|
|
commands += self.get_build_dir_include_args(target, compiler) |
|
|
|
|
# Finally add the private dir for the target to the include path. This |
|
|
|
|
# must override everything else and must be the final path added. |
|
|
|
|
commands += compiler.get_include_args(self.get_target_private_dir(target), False) |
|
|
|
|
|
|
|
|
|
# FIXME: This file handling is atrocious and broken. We need to |
|
|
|
|
# replace it with File objects used consistently everywhere. |
|
|
|
|
if isinstance(src, RawFilename): |
|
|
|
|
rel_src = src.fname |
|
|
|
|
if os.path.isabs(src.fname): |
|
|
|
@ -1835,7 +1887,13 @@ rule FORTRAN_DEP_HACK |
|
|
|
|
rel_obj = os.path.join(self.get_target_private_dir(target), obj_basename) |
|
|
|
|
rel_obj += '.' + self.environment.get_object_suffix() |
|
|
|
|
dep_file = compiler.depfile_for_object(rel_obj) |
|
|
|
|
|
|
|
|
|
# Add MSVC debug file generation compile flags: /Fd /FS |
|
|
|
|
commands += self.get_compile_debugfile_args(compiler, target, rel_obj) |
|
|
|
|
|
|
|
|
|
# PCH handling |
|
|
|
|
if self.environment.coredata.base_options.get('b_pch', False): |
|
|
|
|
commands += self.get_pch_include_args(compiler, target) |
|
|
|
|
pchlist = target.get_pch(compiler.language) |
|
|
|
|
else: |
|
|
|
|
pchlist = [] |
|
|
|
@ -1848,19 +1906,7 @@ rule FORTRAN_DEP_HACK |
|
|
|
|
i = os.path.join(self.get_target_private_dir(target), compiler.get_pch_name(pchlist[0])) |
|
|
|
|
arr.append(i) |
|
|
|
|
pch_dep = arr |
|
|
|
|
custom_target_include_dirs = [] |
|
|
|
|
for i in target.get_generated_sources(): |
|
|
|
|
if not isinstance(i, build.CustomTarget): |
|
|
|
|
continue |
|
|
|
|
idir = self.get_target_dir(i) |
|
|
|
|
if idir not in custom_target_include_dirs: |
|
|
|
|
custom_target_include_dirs.append(idir) |
|
|
|
|
for i in custom_target_include_dirs: |
|
|
|
|
commands += compiler.get_include_args(i, False) |
|
|
|
|
if self.environment.coredata.base_options.get('b_pch', False): |
|
|
|
|
commands += self.get_pch_include_args(compiler, target) |
|
|
|
|
|
|
|
|
|
commands += self.get_compile_debugfile_args(compiler, target, rel_obj) |
|
|
|
|
crstr = '' |
|
|
|
|
if target.is_cross: |
|
|
|
|
crstr = '_CROSS' |
|
|
|
@ -1895,7 +1941,9 @@ rule FORTRAN_DEP_HACK |
|
|
|
|
element.add_orderdep(d) |
|
|
|
|
element.add_orderdep(pch_dep) |
|
|
|
|
element.add_orderdep(extra_orderdeps) |
|
|
|
|
commands = self.dedup_arguments(commands) |
|
|
|
|
# Convert from GCC-style link argument naming to the naming used by the |
|
|
|
|
# current compiler. |
|
|
|
|
commands = commands.to_native() |
|
|
|
|
for i in self.get_fortran_orderdeps(target, compiler): |
|
|
|
|
element.add_orderdep(i) |
|
|
|
|
element.add_item('DEPFILE', dep_file) |
|
|
|
@ -1995,47 +2043,23 @@ rule FORTRAN_DEP_HACK |
|
|
|
|
return [] |
|
|
|
|
return linker.get_no_stdlib_link_args() |
|
|
|
|
|
|
|
|
|
def generate_link(self, target, outfile, outname, obj_list, linker, extra_args=[]): |
|
|
|
|
if isinstance(target, build.StaticLibrary): |
|
|
|
|
linker_base = 'STATIC' |
|
|
|
|
else: |
|
|
|
|
linker_base = linker.get_language() # Fixme. |
|
|
|
|
if isinstance(target, build.SharedLibrary): |
|
|
|
|
self.generate_shsym(outfile, target) |
|
|
|
|
crstr = '' |
|
|
|
|
if target.is_cross: |
|
|
|
|
crstr = '_CROSS' |
|
|
|
|
linker_rule = linker_base + crstr + '_LINKER' |
|
|
|
|
def get_target_type_link_args(self, target, linker): |
|
|
|
|
abspath = os.path.join(self.environment.get_build_dir(), target.subdir) |
|
|
|
|
commands = [] |
|
|
|
|
if not isinstance(target, build.StaticLibrary): |
|
|
|
|
commands += self.build.get_project_link_args(linker, target.subproject) |
|
|
|
|
commands += self.build.get_global_link_args(linker) |
|
|
|
|
commands += self.get_cross_stdlib_link_args(target, linker) |
|
|
|
|
commands += linker.get_linker_always_args() |
|
|
|
|
if not isinstance(target, build.StaticLibrary): |
|
|
|
|
commands += compilers.get_base_link_args(self.environment.coredata.base_options, |
|
|
|
|
linker, |
|
|
|
|
isinstance(target, build.SharedModule)) |
|
|
|
|
commands += linker.get_buildtype_linker_args(self.environment.coredata.get_builtin_option('buildtype')) |
|
|
|
|
commands += linker.get_option_link_args(self.environment.coredata.compiler_options) |
|
|
|
|
commands += self.get_link_debugfile_args(linker, target, outname) |
|
|
|
|
if not(isinstance(target, build.StaticLibrary)): |
|
|
|
|
commands += self.environment.coredata.external_link_args[linker.get_language()] |
|
|
|
|
if isinstance(target, build.Executable): |
|
|
|
|
# Currently only used with the Swift compiler to add '-emit-executable' |
|
|
|
|
commands += linker.get_std_exe_link_args() |
|
|
|
|
elif isinstance(target, build.SharedLibrary): |
|
|
|
|
if isinstance(target, build.SharedModule): |
|
|
|
|
commands += linker.get_std_shared_module_link_args() |
|
|
|
|
else: |
|
|
|
|
commands += linker.get_std_shared_lib_link_args() |
|
|
|
|
# All shared libraries are PIC |
|
|
|
|
commands += linker.get_pic_args() |
|
|
|
|
if hasattr(target, 'soversion'): |
|
|
|
|
soversion = target.soversion |
|
|
|
|
else: |
|
|
|
|
soversion = None |
|
|
|
|
# Add -Wl,-soname arguments on Linux, -install_name on OS X |
|
|
|
|
commands += linker.get_soname_args(target.prefix, target.name, target.suffix, |
|
|
|
|
abspath, soversion, isinstance(target, build.SharedModule)) |
|
|
|
|
abspath, target.soversion, |
|
|
|
|
isinstance(target, build.SharedModule)) |
|
|
|
|
# This is only visited when using the Visual Studio toolchain |
|
|
|
|
if target.vs_module_defs and hasattr(linker, 'gen_vs_module_defs_args'): |
|
|
|
|
commands += linker.gen_vs_module_defs_args(target.vs_module_defs.rel_to_builddir(self.build_to_src)) |
|
|
|
@ -2046,17 +2070,75 @@ rule FORTRAN_DEP_HACK |
|
|
|
|
commands += linker.get_std_link_args() |
|
|
|
|
else: |
|
|
|
|
raise RuntimeError('Unknown build target type.') |
|
|
|
|
# Link arguments of static libraries are not put in the command line of |
|
|
|
|
# the library. They are instead appended to the command line where |
|
|
|
|
# the static library is used. |
|
|
|
|
return commands |
|
|
|
|
|
|
|
|
|
def generate_link(self, target, outfile, outname, obj_list, linker, extra_args=[]): |
|
|
|
|
if isinstance(target, build.StaticLibrary): |
|
|
|
|
linker_base = 'STATIC' |
|
|
|
|
else: |
|
|
|
|
linker_base = linker.get_language() # Fixme. |
|
|
|
|
if isinstance(target, build.SharedLibrary): |
|
|
|
|
self.generate_shsym(outfile, target) |
|
|
|
|
crstr = '' |
|
|
|
|
if target.is_cross: |
|
|
|
|
crstr = '_CROSS' |
|
|
|
|
linker_rule = linker_base + crstr + '_LINKER' |
|
|
|
|
|
|
|
|
|
# Create an empty commands list, and start adding link arguments from |
|
|
|
|
# various sources in the order in which they must override each other |
|
|
|
|
# starting from hard-coded defaults followed by build options and so on. |
|
|
|
|
# |
|
|
|
|
# Once all the linker options have been passed, we will start passing |
|
|
|
|
# libraries and library paths from internal and external sources. |
|
|
|
|
commands = CompilerArgs(linker) |
|
|
|
|
# First, the trivial ones that are impossible to override. |
|
|
|
|
# |
|
|
|
|
# Add linker args for linking this target derived from 'base' build |
|
|
|
|
# options passed on the command-line, in default_options, etc. |
|
|
|
|
# These have the lowest priority. |
|
|
|
|
if not isinstance(target, build.StaticLibrary): |
|
|
|
|
commands += compilers.get_base_link_args(self.environment.coredata.base_options, |
|
|
|
|
linker, |
|
|
|
|
isinstance(target, build.SharedModule)) |
|
|
|
|
# Add -nostdlib if needed; can't be overriden |
|
|
|
|
commands += self.get_cross_stdlib_link_args(target, linker) |
|
|
|
|
# Add things like /NOLOGO; usually can't be overriden |
|
|
|
|
commands += linker.get_linker_always_args() |
|
|
|
|
# Add buildtype linker args: optimization level, etc. |
|
|
|
|
commands += linker.get_buildtype_linker_args(self.environment.coredata.get_builtin_option('buildtype')) |
|
|
|
|
# Add /DEBUG and the pdb filename when using MSVC |
|
|
|
|
commands += self.get_link_debugfile_args(linker, target, outname) |
|
|
|
|
# Add link args specific to this BuildTarget type, such as soname args, |
|
|
|
|
# PIC, import library generation, etc. |
|
|
|
|
commands += self.get_target_type_link_args(target, linker) |
|
|
|
|
if not isinstance(target, build.StaticLibrary): |
|
|
|
|
# Add link args added using add_project_link_arguments() |
|
|
|
|
commands += self.build.get_project_link_args(linker, target.subproject) |
|
|
|
|
# Add link args added using add_global_link_arguments() |
|
|
|
|
# These override per-project link arguments |
|
|
|
|
commands += self.build.get_global_link_args(linker) |
|
|
|
|
# Link args added from the env: LDFLAGS. We want these to |
|
|
|
|
# override all the defaults but not the per-target link args. |
|
|
|
|
commands += self.environment.coredata.external_link_args[linker.get_language()] |
|
|
|
|
|
|
|
|
|
# Now we will add libraries and library paths from various sources |
|
|
|
|
|
|
|
|
|
# Add link args to link to all internal libraries (link_with:) and |
|
|
|
|
# internal dependencies needed by this target. |
|
|
|
|
if linker_base == 'STATIC': |
|
|
|
|
# Link arguments of static libraries are not put in the command |
|
|
|
|
# line of the library. They are instead appended to the command |
|
|
|
|
# line where the static library is used. |
|
|
|
|
dependencies = [] |
|
|
|
|
else: |
|
|
|
|
dependencies = target.get_dependencies() |
|
|
|
|
commands += self.build_target_link_arguments(linker, dependencies) |
|
|
|
|
# For 'automagic' deps: Boost and GTest. Also dependency('threads'). |
|
|
|
|
# pkg-config puts the thread flags itself via `Cflags:` |
|
|
|
|
for d in target.external_deps: |
|
|
|
|
if d.need_threads(): |
|
|
|
|
commands += linker.thread_link_flags() |
|
|
|
|
# Only non-static built targets need link args and link dependencies |
|
|
|
|
if not isinstance(target, build.StaticLibrary): |
|
|
|
|
commands += target.link_args |
|
|
|
|
# External deps must be last because target link libraries may depend on them. |
|
|
|
@ -2066,12 +2148,24 @@ rule FORTRAN_DEP_HACK |
|
|
|
|
if isinstance(d, build.StaticLibrary): |
|
|
|
|
for dep in d.get_external_deps(): |
|
|
|
|
commands += dep.get_link_args() |
|
|
|
|
# Add link args for c_* or cpp_* build options. Currently this only |
|
|
|
|
# adds c_winlibs and cpp_winlibs when building for Windows. This needs |
|
|
|
|
# to be after all internal and external libraries so that unresolved |
|
|
|
|
# symbols from those can be found here. This is needed when the |
|
|
|
|
# *_winlibs that we want to link to are static mingw64 libraries. |
|
|
|
|
commands += linker.get_option_link_args(self.environment.coredata.compiler_options) |
|
|
|
|
# Set runtime-paths so we can run executables without needing to set |
|
|
|
|
# LD_LIBRARY_PATH, etc in the environment. Doesn't work on Windows. |
|
|
|
|
commands += linker.build_rpath_args(self.environment.get_build_dir(), |
|
|
|
|
self.determine_rpath_dirs(target), target.install_rpath) |
|
|
|
|
self.determine_rpath_dirs(target), |
|
|
|
|
target.install_rpath) |
|
|
|
|
# Add libraries generated by custom targets |
|
|
|
|
custom_target_libraries = self.get_custom_target_provided_libraries(target) |
|
|
|
|
commands += extra_args |
|
|
|
|
commands += custom_target_libraries |
|
|
|
|
commands = linker.unix_link_flags_to_native(self.dedup_arguments(commands)) |
|
|
|
|
# Convert from GCC-style link argument naming to the naming used by the |
|
|
|
|
# current compiler. |
|
|
|
|
commands = commands.to_native() |
|
|
|
|
dep_targets = [self.get_dependency_filename(t) for t in dependencies] |
|
|
|
|
dep_targets += [os.path.join(self.environment.source_dir, |
|
|
|
|
target.subdir, t) for t in target.link_depends] |
|
|
|
|