From 976c9abcd0348ffb29863ac2688c661eda524a47 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Tue, 28 Mar 2017 14:31:45 +0530 Subject: [PATCH] modules: Start using @SOURCE_ROOT@ and @BUILD_ROOT@ First step in fixing https://github.com/mesonbuild/meson/issues/1419 Also works around an issue in the MinGW windres.exe that causes it to fail if any of the arguments passed to it contain a space. There seems to be no way to quote or escape the spaces in the path to make windres parse the path correctly, so we just warn about it instead. https://sourceware.org/bugzilla/show_bug.cgi?id=4933 https://github.com/mesonbuild/meson/pull/1346 --- mesonbuild/backend/backends.py | 9 +++++++++ mesonbuild/backend/ninjabackend.py | 2 ++ mesonbuild/backend/vs2010backend.py | 6 +++++- mesonbuild/modules/__init__.py | 10 +++++++--- mesonbuild/modules/gnome.py | 14 ++++++-------- mesonbuild/modules/windows.py | 8 +++++++- 6 files changed, 36 insertions(+), 13 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index fa9a82fcd..99be17240 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -601,8 +601,13 @@ class Backend: def eval_custom_target_command(self, target, absolute_outputs=False): # We want the outputs to be absolute only when using the VS backend + # XXX: Maybe allow the vs backend to use relative paths too? + source_root = self.build_to_src + build_root = '.' outdir = self.get_target_dir(target) if absolute_outputs: + source_root = self.environment.get_source_dir() + build_root = self.environment.get_source_dir() outdir = os.path.join(self.environment.get_build_dir(), outdir) outputs = [] for i in target.output: @@ -628,6 +633,10 @@ class Backend: elif not isinstance(i, str): err_msg = 'Argument {0} is of unknown type {1}' raise RuntimeError(err_msg.format(str(i), str(type(i)))) + elif '@SOURCE_ROOT@' in i: + i = i.replace('@SOURCE_ROOT@', source_root) + elif '@BUILD_ROOT@' in i: + i = i.replace('@BUILD_ROOT@', build_root) elif '@DEPFILE@' in i: if target.depfile is None: msg = 'Custom target {!r} has @DEPFILE@ but no depfile ' \ diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index cc350b2cc..8486060d8 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1602,6 +1602,8 @@ rule FORTRAN_DEP_HACK relout = self.get_target_private_dir(target) args = [x.replace("@SOURCE_DIR@", self.build_to_src).replace("@BUILD_DIR@", relout) for x in args] + args = [x.replace("@SOURCE_ROOT@", self.build_to_src).replace("@BUILD_ROOT@", '.') + for x in args] cmdlist = exe_arr + self.replace_extra_args(args, genlist) elem = NinjaBuildElement(self.all_outputs, outfiles, rulename, infilename) if generator.depfile is not None: diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 84e829650..8c0cce69c 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -151,7 +151,11 @@ class Vs2010Backend(backends.Backend): args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', sole_output) for x in base_args] args = self.replace_outputs(args, target_private_dir, outfiles_rel) - args = [x.replace("@SOURCE_DIR@", self.environment.get_source_dir()).replace("@BUILD_DIR@", target_private_dir) + args = [x.replace("@SOURCE_DIR@", self.environment.get_source_dir()) + .replace("@BUILD_DIR@", target_private_dir) + for x in args] + args = [x.replace("@SOURCE_ROOT@", self.environment.get_source_dir()) + .replace("@BUILD_ROOT@", self.environment.get_build_dir()) for x in args] cmd = exe_arr + self.replace_extra_args(args, genlist) cbs = ET.SubElement(idgroup, 'CustomBuild', Include=infilename) diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py index c7f24d4e1..fde3b91ff 100644 --- a/mesonbuild/modules/__init__.py +++ b/mesonbuild/modules/__init__.py @@ -24,7 +24,11 @@ def find_program(program_name, target_name): return program -def get_include_args(environment, include_dirs, prefix='-I'): +def get_include_args(include_dirs, prefix='-I'): + ''' + Expand include arguments to refer to the source and build dirs + by using @SOURCE_ROOT@ and @BUILD_ROOT@ for later substitution + ''' if not include_dirs: return [] @@ -43,8 +47,8 @@ def get_include_args(environment, include_dirs, prefix='-I'): basedir = dirs.get_curdir() for d in dirs.get_incdirs(): expdir = os.path.join(basedir, d) - srctreedir = os.path.join(environment.get_source_dir(), expdir) - buildtreedir = os.path.join(environment.get_build_dir(), expdir) + srctreedir = os.path.join('@SOURCE_ROOT@', expdir) + buildtreedir = os.path.join('@BUILD_ROOT@', expdir) dirs_str += ['%s%s' % (prefix, buildtreedir), '%s%s' % (prefix, srctreedir)] for d in dirs.get_extra_build_dirs(): diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 423031d1f..4b366bf23 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -309,7 +309,7 @@ class GnomeModule(ExtensionModule): if hasattr(dep, 'held_object'): dep = dep.held_object if isinstance(dep, InternalDependency): - cflags.update(get_include_args(state.environment, dep.include_directories)) + cflags.update(get_include_args(dep.include_directories)) for lib in dep.libraries: ldflags.update(self._get_link_args(state, lib.held_object, depends, include_rpath)) libdepflags = self._get_dependencies_flags(lib.held_object.get_external_deps(), state, depends, include_rpath, @@ -398,7 +398,7 @@ class GnomeModule(ExtensionModule): scan_command += extra_args scan_command += ['-I' + os.path.join(state.environment.get_source_dir(), state.subdir), '-I' + os.path.join(state.environment.get_build_dir(), state.subdir)] - scan_command += get_include_args(state.environment, girtarget.get_include_dirs()) + scan_command += get_include_args(girtarget.get_include_dirs()) if 'link_with' in kwargs: link_with = kwargs.pop('link_with') @@ -525,9 +525,8 @@ class GnomeModule(ExtensionModule): if not isinstance(incd.held_object, (str, build.IncludeDirs)): raise MesonException( 'Gir include dirs should be include_directories().') - scan_command += get_include_args(state.environment, inc_dirs) - scan_command += get_include_args(state.environment, gir_inc_dirs + inc_dirs, - prefix='--add-include-path=') + scan_command += get_include_args(inc_dirs) + scan_command += get_include_args(gir_inc_dirs + inc_dirs, prefix='--add-include-path=') if isinstance(girtarget, build.Executable): scan_command += ['--program', girtarget] @@ -546,8 +545,7 @@ class GnomeModule(ExtensionModule): typelib_output = '%s-%s.typelib' % (ns, nsversion) typelib_cmd = [gicompiler, scan_target, '--output', '@OUTPUT@'] - typelib_cmd += get_include_args(state.environment, gir_inc_dirs, - prefix='--includedir=') + typelib_cmd += get_include_args(gir_inc_dirs, prefix='--includedir=') for incdir in typelib_includes: typelib_cmd += ["--includedir=" + incdir] @@ -716,7 +714,7 @@ class GnomeModule(ExtensionModule): if not isinstance(incd.held_object, (str, build.IncludeDirs)): raise MesonException( 'Gir include dirs should be include_directories().') - cflags.update(get_include_args(state.environment, inc_dirs)) + cflags.update(get_include_args(inc_dirs)) if cflags: args += ['--cflags=%s' % ' '.join(cflags)] if ldflags: diff --git a/mesonbuild/modules/windows.py b/mesonbuild/modules/windows.py index 820378993..c233d907b 100644 --- a/mesonbuild/modules/windows.py +++ b/mesonbuild/modules/windows.py @@ -14,6 +14,7 @@ import os +from .. import mlog from .. import mesonlib, dependencies, build from ..mesonlib import MesonException from . import get_include_args @@ -38,13 +39,18 @@ class WindowsModule(ExtensionModule): for incd in inc_dirs: if not isinstance(incd.held_object, (str, build.IncludeDirs)): raise MesonException('Resource include dirs should be include_directories().') - extra_args += get_include_args(state.environment, inc_dirs) + extra_args += get_include_args(inc_dirs) if comp.id == 'msvc': rescomp = dependencies.ExternalProgram('rc', silent=True) res_args = extra_args + ['/nologo', '/fo@OUTPUT@', '@INPUT@'] suffix = 'res' else: + m = 'Argument {!r} has a space which may not work with windres due to ' \ + 'a MinGW bug: https://sourceware.org/bugzilla/show_bug.cgi?id=4933' + for arg in extra_args: + if ' ' in arg: + mlog.warning(m.format(arg)) # Pick-up env var WINDRES if set. This is often used for specifying # an arch-specific windres. rescomp_name = os.environ.get('WINDRES', 'windres')