aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesonbuild/backend/ninjabackend.py3
-rw-r--r--mesonbuild/build.py10
-rw-r--r--mesonbuild/compilers/d.py14
-rw-r--r--mesonbuild/interpreter.py38
-rw-r--r--test cases/d/9 features/meson.build17
5 files changed, 68 insertions, 14 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 8b616a6..8577bc7 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -2257,6 +2257,9 @@ rule FORTRAN_DEP_HACK
depelem.write(outfile)
commands += compiler.get_module_outdir_args(self.get_target_private_dir(target))
+ if compiler.language == 'd':
+ commands += compiler.get_feature_args(target.d_features, self.build_to_src)
+
element = NinjaBuildElement(self.all_outputs, rel_obj, compiler_name, rel_src)
for d in header_deps:
if isinstance(d, File):
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 400b9e5..c5fc7f6 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -355,6 +355,7 @@ class BuildTarget(Target):
self.extra_args = {}
self.generated = []
self.extra_files = []
+ self.d_features = {}
# Sources can be:
# 1. Pre-existing source files in the source tree
# 2. Pre-existing sources generated by configure_file in the build tree
@@ -682,12 +683,15 @@ just like those detected with the dependency() function.''')
dfeature_versions = kwargs.get('d_module_versions', None)
if dfeature_versions:
dfeatures['versions'] = dfeature_versions
- dfeature_import_dirs = kwargs.get('d_import_dirs', None)
- if dfeature_import_dirs:
+ if 'd_import_dirs' in kwargs:
+ dfeature_import_dirs = extract_as_list(kwargs, 'd_import_dirs', unholder=True)
+ for d in dfeature_import_dirs:
+ if not isinstance(d, IncludeDirs):
+ raise InvalidArguments('Arguments to d_import_dirs must be include_directories.')
dfeatures['import_dirs'] = dfeature_import_dirs
if dfeatures:
if 'd' in self.compilers:
- self.add_compiler_args('d', self.compilers['d'].get_feature_args(dfeatures))
+ self.d_features = dfeatures
self.link_args = extract_as_list(kwargs, 'link_args')
for i in self.link_args:
diff --git a/mesonbuild/compilers/d.py b/mesonbuild/compilers/d.py
index 3320736..474e1bd 100644
--- a/mesonbuild/compilers/d.py
+++ b/mesonbuild/compilers/d.py
@@ -93,7 +93,7 @@ class DCompiler(Compiler):
# FIXME: Make this work for Windows, MacOS and cross-compiling
return get_gcc_soname_args(GCC_STANDARD, prefix, shlib_name, suffix, path, soversion, is_shared_module)
- def get_feature_args(self, kwargs):
+ def get_feature_args(self, kwargs, build_to_src):
res = []
if 'unittest' in kwargs:
unittest = kwargs.pop('unittest')
@@ -122,8 +122,16 @@ class DCompiler(Compiler):
import_dir_arg = d_feature_args[self.id]['import_dir']
if not import_dir_arg:
raise EnvironmentException('D compiler %s does not support the "string import directories" feature.' % self.name_string())
- for d in import_dirs:
- res.append('{0}{1}'.format(import_dir_arg, d))
+ for idir_obj in import_dirs:
+ basedir = idir_obj.get_curdir()
+ for idir in idir_obj.get_incdirs():
+ # Avoid superfluous '/.' at the end of paths when d is '.'
+ if idir not in ('', '.'):
+ expdir = os.path.join(basedir, idir)
+ else:
+ expdir = basedir
+ srctreedir = os.path.join(build_to_src, expdir)
+ res.append('{0}{1}'.format(import_dir_arg, srctreedir))
if kwargs:
raise EnvironmentException('Unknown D compiler feature(s) selected: %s' % ', '.join(kwargs.keys()))
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 8041526..5c333a8 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -37,6 +37,7 @@ from pathlib import PurePath
import importlib
+
def stringifyUserArguments(args):
if isinstance(args, list):
return '[%s]' % ', '.join([stringifyUserArguments(x) for x in args])
@@ -247,7 +248,7 @@ class ConfigurationDataHolder(MutableInterpreterObject, ObjectHolder):
return val
def get(self, name):
- return self.held_object.values[name] # (val, desc)
+ return self.held_object.values[name] # (val, desc)
def keys(self):
return self.held_object.values.keys()
@@ -816,7 +817,8 @@ class CompilerHolder(InterpreterObject):
'''
if not hasattr(self.compiler, 'get_feature_args'):
raise InterpreterException('This {} compiler has no feature arguments.'.format(self.compiler.get_display_language()))
- return self.compiler.get_feature_args({'unittest': 'true'})
+ build_to_src = os.path.relpath(self.environment.get_source_dir(), self.environment.get_build_dir())
+ return self.compiler.get_feature_args({'unittest': 'true'}, build_to_src)
def has_member_method(self, args, kwargs):
if len(args) != 2:
@@ -1309,6 +1311,7 @@ class MesonMain(InterpreterObject):
return args[1]
raise InterpreterException('Unknown cross property: %s.' % propname)
+
pch_kwargs = set(['c_pch', 'cpp_pch'])
lang_arg_kwargs = set([
@@ -2847,12 +2850,17 @@ root and issuing %s.
@permittedKwargs(permitted_kwargs['include_directories'])
@stringArgs
def func_include_directories(self, node, args, kwargs):
+ return self.build_incdir_object(args, kwargs.get('is_system', False))
+
+ def build_incdir_object(self, incdir_strings, is_system=False):
+ if not isinstance(is_system, bool):
+ raise InvalidArguments('Is_system must be boolean.')
src_root = self.environment.get_source_dir()
build_root = self.environment.get_build_dir()
absbase_src = os.path.join(src_root, self.subdir)
absbase_build = os.path.join(build_root, self.subdir)
- for a in args:
+ for a in incdir_strings:
if a.startswith(src_root):
raise InvalidArguments('''Tried to form an absolute path to a source dir. You should not do that but use
relative paths instead.
@@ -2875,10 +2883,7 @@ different subdirectory.
absdir_build = os.path.join(absbase_build, a)
if not os.path.isdir(absdir_src) and not os.path.isdir(absdir_build):
raise InvalidArguments('Include dir %s does not exist.' % a)
- is_system = kwargs.get('is_system', False)
- if not isinstance(is_system, bool):
- raise InvalidArguments('Is_system must be boolean.')
- i = IncludeDirsHolder(build.IncludeDirs(self.subdir, args, is_system))
+ i = IncludeDirsHolder(build.IncludeDirs(self.subdir, incdir_strings, is_system))
return i
@permittedKwargs(permitted_kwargs['add_test_setup'])
@@ -3106,6 +3111,7 @@ different subdirectory.
else:
mlog.debug('Unknown target type:', str(targetholder))
raise RuntimeError('Unreachable code')
+ self.kwarg_strings_to_includedirs(kwargs)
target = targetclass(name, self.subdir, self.subproject, is_cross, sources, objs, self.environment, kwargs)
if is_cross:
self.add_cross_stdlib_info(target)
@@ -3114,6 +3120,23 @@ different subdirectory.
self.project_args_frozen = True
return l
+ def kwarg_strings_to_includedirs(self, kwargs):
+ if 'd_import_dirs' in kwargs:
+ items = mesonlib.extract_as_list(kwargs, 'd_import_dirs')
+ cleaned_items = []
+ for i in items:
+ if isinstance(i, str):
+ # BW compatibility. This was permitted so we must support it
+ # for a few releases so people can transition to "correct"
+ # path declarations.
+ if i.startswith(self.environment.get_source_dir()):
+ mlog.warning('''Building a path to the source dir is not supported. Use a relative path instead.
+This will become a hard error in the future.''')
+ i = os.path.relpath(i, os.path.join(self.environment.get_source_dir(), self.subdir))
+ i = self.build_incdir_object([i])
+ cleaned_items.append(i)
+ kwargs['d_import_dirs'] = cleaned_items
+
def get_used_languages(self, target):
result = {}
for i in target.sources:
@@ -3152,6 +3175,7 @@ different subdirectory.
if idx >= len(arg_strings):
raise InterpreterException('Format placeholder @{}@ out of range.'.format(idx))
return arg_strings[idx]
+
return re.sub(r'@(\d+)@', arg_replace, templ)
# Only permit object extraction from the same subproject
diff --git a/test cases/d/9 features/meson.build b/test cases/d/9 features/meson.build
index 9e63710..356e9f3 100644
--- a/test cases/d/9 features/meson.build
+++ b/test cases/d/9 features/meson.build
@@ -1,8 +1,22 @@
project('D Features', 'd')
-# directory for data
+# ONLY FOR BACKWARDS COMPATIBILITY.
+# DO NOT DO THIS IN NEW CODE!
+# USE include_directories() INSTEAD OF BUILDING
+# STRINGS TO PATHS MANUALLY!
data_dir = join_paths(meson.current_source_dir(), 'data')
+e_plain_bcompat = executable('dapp_menu_bcompat',
+ 'app.d',
+ d_import_dirs: [data_dir]
+)
+test('dapp_menu_t_fail_bcompat', e_plain_bcompat, should_fail: true)
+test('dapp_menu_t_bcompat', e_plain_bcompat, args: ['menu'])
+
+# directory for data
+# This is the correct way to do this.
+data_dir = include_directories('data')
+
e_plain = executable('dapp_menu',
'app.d',
d_import_dirs: [data_dir]
@@ -10,6 +24,7 @@ e_plain = executable('dapp_menu',
test('dapp_menu_t_fail', e_plain, should_fail: true)
test('dapp_menu_t', e_plain, args: ['menu'])
+
# test feature versions and string imports
e_versions = executable('dapp_versions',
'app.d',