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
pull/1346/head
Nirbheek Chauhan 8 years ago
parent 03d0feec7c
commit 976c9abcd0
  1. 9
      mesonbuild/backend/backends.py
  2. 2
      mesonbuild/backend/ninjabackend.py
  3. 6
      mesonbuild/backend/vs2010backend.py
  4. 10
      mesonbuild/modules/__init__.py
  5. 14
      mesonbuild/modules/gnome.py
  6. 8
      mesonbuild/modules/windows.py

@ -601,8 +601,13 @@ class Backend:
def eval_custom_target_command(self, target, absolute_outputs=False): def eval_custom_target_command(self, target, absolute_outputs=False):
# We want the outputs to be absolute only when using the VS backend # 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) outdir = self.get_target_dir(target)
if absolute_outputs: 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) outdir = os.path.join(self.environment.get_build_dir(), outdir)
outputs = [] outputs = []
for i in target.output: for i in target.output:
@ -628,6 +633,10 @@ class Backend:
elif not isinstance(i, str): elif not isinstance(i, str):
err_msg = 'Argument {0} is of unknown type {1}' err_msg = 'Argument {0} is of unknown type {1}'
raise RuntimeError(err_msg.format(str(i), str(type(i)))) 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: elif '@DEPFILE@' in i:
if target.depfile is None: if target.depfile is None:
msg = 'Custom target {!r} has @DEPFILE@ but no depfile ' \ msg = 'Custom target {!r} has @DEPFILE@ but no depfile ' \

@ -1602,6 +1602,8 @@ rule FORTRAN_DEP_HACK
relout = self.get_target_private_dir(target) relout = self.get_target_private_dir(target)
args = [x.replace("@SOURCE_DIR@", self.build_to_src).replace("@BUILD_DIR@", relout) args = [x.replace("@SOURCE_DIR@", self.build_to_src).replace("@BUILD_DIR@", relout)
for x in args] 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) cmdlist = exe_arr + self.replace_extra_args(args, genlist)
elem = NinjaBuildElement(self.all_outputs, outfiles, rulename, infilename) elem = NinjaBuildElement(self.all_outputs, outfiles, rulename, infilename)
if generator.depfile is not None: if generator.depfile is not None:

@ -151,7 +151,11 @@ class Vs2010Backend(backends.Backend):
args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', sole_output) args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', sole_output)
for x in base_args] for x in base_args]
args = self.replace_outputs(args, target_private_dir, outfiles_rel) 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] for x in args]
cmd = exe_arr + self.replace_extra_args(args, genlist) cmd = exe_arr + self.replace_extra_args(args, genlist)
cbs = ET.SubElement(idgroup, 'CustomBuild', Include=infilename) cbs = ET.SubElement(idgroup, 'CustomBuild', Include=infilename)

@ -24,7 +24,11 @@ def find_program(program_name, target_name):
return program 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: if not include_dirs:
return [] return []
@ -43,8 +47,8 @@ def get_include_args(environment, include_dirs, prefix='-I'):
basedir = dirs.get_curdir() basedir = dirs.get_curdir()
for d in dirs.get_incdirs(): for d in dirs.get_incdirs():
expdir = os.path.join(basedir, d) expdir = os.path.join(basedir, d)
srctreedir = os.path.join(environment.get_source_dir(), expdir) srctreedir = os.path.join('@SOURCE_ROOT@', expdir)
buildtreedir = os.path.join(environment.get_build_dir(), expdir) buildtreedir = os.path.join('@BUILD_ROOT@', expdir)
dirs_str += ['%s%s' % (prefix, buildtreedir), dirs_str += ['%s%s' % (prefix, buildtreedir),
'%s%s' % (prefix, srctreedir)] '%s%s' % (prefix, srctreedir)]
for d in dirs.get_extra_build_dirs(): for d in dirs.get_extra_build_dirs():

@ -309,7 +309,7 @@ class GnomeModule(ExtensionModule):
if hasattr(dep, 'held_object'): if hasattr(dep, 'held_object'):
dep = dep.held_object dep = dep.held_object
if isinstance(dep, InternalDependency): 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: for lib in dep.libraries:
ldflags.update(self._get_link_args(state, lib.held_object, depends, include_rpath)) 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, 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 += extra_args
scan_command += ['-I' + os.path.join(state.environment.get_source_dir(), state.subdir), scan_command += ['-I' + os.path.join(state.environment.get_source_dir(), state.subdir),
'-I' + os.path.join(state.environment.get_build_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: if 'link_with' in kwargs:
link_with = kwargs.pop('link_with') link_with = kwargs.pop('link_with')
@ -525,9 +525,8 @@ class GnomeModule(ExtensionModule):
if not isinstance(incd.held_object, (str, build.IncludeDirs)): if not isinstance(incd.held_object, (str, build.IncludeDirs)):
raise MesonException( raise MesonException(
'Gir include dirs should be include_directories().') 'Gir include dirs should be include_directories().')
scan_command += get_include_args(state.environment, inc_dirs) scan_command += get_include_args(inc_dirs)
scan_command += get_include_args(state.environment, gir_inc_dirs + inc_dirs, scan_command += get_include_args(gir_inc_dirs + inc_dirs, prefix='--add-include-path=')
prefix='--add-include-path=')
if isinstance(girtarget, build.Executable): if isinstance(girtarget, build.Executable):
scan_command += ['--program', girtarget] scan_command += ['--program', girtarget]
@ -546,8 +545,7 @@ class GnomeModule(ExtensionModule):
typelib_output = '%s-%s.typelib' % (ns, nsversion) typelib_output = '%s-%s.typelib' % (ns, nsversion)
typelib_cmd = [gicompiler, scan_target, '--output', '@OUTPUT@'] typelib_cmd = [gicompiler, scan_target, '--output', '@OUTPUT@']
typelib_cmd += get_include_args(state.environment, gir_inc_dirs, typelib_cmd += get_include_args(gir_inc_dirs, prefix='--includedir=')
prefix='--includedir=')
for incdir in typelib_includes: for incdir in typelib_includes:
typelib_cmd += ["--includedir=" + incdir] typelib_cmd += ["--includedir=" + incdir]
@ -716,7 +714,7 @@ class GnomeModule(ExtensionModule):
if not isinstance(incd.held_object, (str, build.IncludeDirs)): if not isinstance(incd.held_object, (str, build.IncludeDirs)):
raise MesonException( raise MesonException(
'Gir include dirs should be include_directories().') '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: if cflags:
args += ['--cflags=%s' % ' '.join(cflags)] args += ['--cflags=%s' % ' '.join(cflags)]
if ldflags: if ldflags:

@ -14,6 +14,7 @@
import os import os
from .. import mlog
from .. import mesonlib, dependencies, build from .. import mesonlib, dependencies, build
from ..mesonlib import MesonException from ..mesonlib import MesonException
from . import get_include_args from . import get_include_args
@ -38,13 +39,18 @@ class WindowsModule(ExtensionModule):
for incd in inc_dirs: for incd in inc_dirs:
if not isinstance(incd.held_object, (str, build.IncludeDirs)): if not isinstance(incd.held_object, (str, build.IncludeDirs)):
raise MesonException('Resource include dirs should be include_directories().') 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': if comp.id == 'msvc':
rescomp = dependencies.ExternalProgram('rc', silent=True) rescomp = dependencies.ExternalProgram('rc', silent=True)
res_args = extra_args + ['/nologo', '/fo@OUTPUT@', '@INPUT@'] res_args = extra_args + ['/nologo', '/fo@OUTPUT@', '@INPUT@']
suffix = 'res' suffix = 'res'
else: 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 # Pick-up env var WINDRES if set. This is often used for specifying
# an arch-specific windres. # an arch-specific windres.
rescomp_name = os.environ.get('WINDRES', 'windres') rescomp_name = os.environ.get('WINDRES', 'windres')

Loading…
Cancel
Save