diff options
Diffstat (limited to 'mesonbuild/backend/ninjabackend.py')
-rw-r--r-- | mesonbuild/backend/ninjabackend.py | 136 |
1 files changed, 92 insertions, 44 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 5bd660c..98740a4 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -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(): - expdir = os.path.join(basedir, d) + # 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) |