Skip to content

Commit

Permalink
compilers/d: use DFeatures for get_features_args
Browse files Browse the repository at this point in the history
  • Loading branch information
dcbaker committed Oct 9, 2023
1 parent cd6feb6 commit f5b4d2c
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 86 deletions.
4 changes: 2 additions & 2 deletions mesonbuild/compilers/compilers.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
from ..arglist import CompilerArgs

if T.TYPE_CHECKING:
from ..build import BuildTarget
from ..build import BuildTarget, DFeatures
from ..coredata import MutableKeyedOptionDictType, KeyedOptionDictType
from ..envconfig import MachineInfo
from ..environment import Environment
Expand Down Expand Up @@ -1331,7 +1331,7 @@ def links(self, code: 'mesonlib.FileOrString', env: 'Environment', *,
return self.compiles(code, env, extra_args=extra_args,
dependencies=dependencies, mode=CompileCheckMode.LINK, disable_cache=disable_cache)

def get_feature_args(self, kwargs: T.Dict[str, T.Any], build_to_src: str) -> T.List[str]:
def get_feature_args(self, kwargs: DFeatures, build_to_src: str) -> T.List[str]:
"""Used by D for extra language features."""
# TODO: using a TypeDict here would improve this
raise EnvironmentException(f'{self.id} does not implement get_feature_args')
Expand Down
145 changes: 62 additions & 83 deletions mesonbuild/compilers/d.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
from .mixins.gnu import gnu_common_warning_args

if T.TYPE_CHECKING:
from ..build import DFeatures
from ..dependencies import Dependency
from ..programs import ExternalProgram
from ..envconfig import MachineInfo
Expand Down Expand Up @@ -498,91 +499,69 @@ def get_pic_args(self) -> T.List[str]:
return []
return ['-fPIC']

def get_feature_args(self, kwargs: T.Dict[str, T.Any], build_to_src: str) -> T.List[str]:
# TODO: using a TypeDict here would improve this
def get_feature_args(self, kwargs: DFeatures, build_to_src: str) -> T.List[str]:
res: T.List[str] = []
# get_feature_args can be called multiple times for the same target when there is generated source
# so we have to copy the kwargs (target.d_features) dict before popping from it
kwargs = kwargs.copy()
if 'unittest' in kwargs:
unittest = kwargs.pop('unittest')
unittest_arg = d_feature_args[self.id]['unittest']
if not unittest_arg:
raise EnvironmentException('D compiler %s does not support the "unittest" feature.' % self.name_string())
if unittest:
res.append(unittest_arg)

if 'debug' in kwargs:
debug_level = -1
debugs = kwargs.pop('debug')
if not isinstance(debugs, list):
debugs = [debugs]

debug_arg = d_feature_args[self.id]['debug']
if not debug_arg:
raise EnvironmentException('D compiler %s does not support conditional debug identifiers.' % self.name_string())

# Parse all debug identifiers and the largest debug level identifier
for d in debugs:
if isinstance(d, int):
if d > debug_level:
debug_level = d
elif isinstance(d, str) and d.isdigit():
if int(d) > debug_level:
debug_level = int(d)
else:
res.append(f'{debug_arg}={d}')

if debug_level >= 0:
res.append(f'{debug_arg}={debug_level}')

if 'versions' in kwargs:
version_level = -1
versions = kwargs.pop('versions')
if not isinstance(versions, list):
versions = [versions]

version_arg = d_feature_args[self.id]['version']
if not version_arg:
raise EnvironmentException('D compiler %s does not support conditional version identifiers.' % self.name_string())

# Parse all version identifiers and the largest version level identifier
for v in versions:
if isinstance(v, int):
if v > version_level:
version_level = v
elif isinstance(v, str) and v.isdigit():
if int(v) > version_level:
version_level = int(v)
unittest_arg = d_feature_args[self.id]['unittest']
if not unittest_arg:
raise EnvironmentException('D compiler %s does not support the "unittest" feature.' % self.name_string())
if kwargs['unittest']:
res.append(unittest_arg)

debug_level = -1
debug_arg = d_feature_args[self.id]['debug']
if not debug_arg:
raise EnvironmentException('D compiler %s does not support conditional debug identifiers.' % self.name_string())

# Parse all debug identifiers and the largest debug level identifier
for d in kwargs['debug']:
if isinstance(d, int):
if d > debug_level:
debug_level = d
elif isinstance(d, str) and d.isdigit():
if int(d) > debug_level:
debug_level = int(d)
else:
res.append(f'{debug_arg}={d}')

if debug_level >= 0:
res.append(f'{debug_arg}={debug_level}')

version_level = -1
version_arg = d_feature_args[self.id]['version']
if not version_arg:
raise EnvironmentException('D compiler %s does not support conditional version identifiers.' % self.name_string())

# Parse all version identifiers and the largest version level identifier
for v in kwargs['versions']:
if isinstance(v, int):
if v > version_level:
version_level = v
elif isinstance(v, str) and v.isdigit():
if int(v) > version_level:
version_level = int(v)
else:
res.append(f'{version_arg}={v}')

if version_level >= 0:
res.append(f'{version_arg}={version_level}')

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())
# TODO: ImportDirs.to_string_list(), but we need both the project source
# root and project build root for that.
for idir_obj in kwargs['import_dirs']:
basedir = idir_obj.get_curdir()
for idir in idir_obj.get_incdirs():
bldtreedir = os.path.join(basedir, idir)
# Avoid superfluous '/.' at the end of paths when d is '.'
if idir not in ('', '.'):
expdir = bldtreedir
else:
res.append(f'{version_arg}={v}')

if version_level >= 0:
res.append(f'{version_arg}={version_level}')

if 'import_dirs' in kwargs:
import_dirs = kwargs.pop('import_dirs')
if not isinstance(import_dirs, list):
import_dirs = [import_dirs]

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 idir_obj in import_dirs:
basedir = idir_obj.get_curdir()
for idir in idir_obj.get_incdirs():
bldtreedir = os.path.join(basedir, idir)
# Avoid superfluous '/.' at the end of paths when d is '.'
if idir not in ('', '.'):
expdir = bldtreedir
else:
expdir = basedir
srctreedir = os.path.join(build_to_src, expdir)
res.append(f'{import_dir_arg}{srctreedir}')
res.append(f'{import_dir_arg}{bldtreedir}')

if kwargs:
raise EnvironmentException('Unknown D compiler feature(s) selected: %s' % ', '.join(kwargs.keys()))
expdir = basedir
srctreedir = os.path.join(build_to_src, expdir)
res.append(f'{import_dir_arg}{srctreedir}')
res.append(f'{import_dir_arg}{bldtreedir}')

return res

Expand Down
3 changes: 2 additions & 1 deletion mesonbuild/modules/pkgconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,8 @@ def generate(self, state: ModuleState,
if dversions:
compiler = state.environment.coredata.compilers.host.get('d')
if compiler:
deps.add_cflags(compiler.get_feature_args({'versions': dversions}, None))
deps.add_cflags(compiler.get_feature_args(
{'versions': dversions, 'import_dirs': [], 'debug': [], 'unittest': False}, None))

deps.remove_dups()

Expand Down

0 comments on commit f5b4d2c

Please sign in to comment.