Use include_directories for D impdirs.
Change the code to store D properties as plain data. Only convert them to compiler flags in the backend. This also means we can fully parse D arguments without needing to know the compiler being used.
This commit is contained in:
parent
8a68dc0179
commit
ea3b54d402
|
@ -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):
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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()))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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',
|
||||
|
|
Loading…
Reference in New Issue