Skip to content

Commit

Permalink
cargo: Use cfg
Browse files Browse the repository at this point in the history
  • Loading branch information
xclaesse committed Nov 22, 2023
1 parent 7979332 commit a9f9523
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 28 deletions.
17 changes: 12 additions & 5 deletions mesonbuild/cargo/cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,8 @@ class Identifier(IR):
@dataclasses.dataclass
class Equal(IR):

lhs: IR
rhs: IR
lhs: Identifier
rhs: String


@dataclasses.dataclass
Expand Down Expand Up @@ -231,13 +231,16 @@ def _(ir: String, build: builder.Builder) -> mparser.BaseNode:

@ir_to_meson.register
def _(ir: Identifier, build: builder.Builder) -> mparser.BaseNode:
# rust.cfg('identifier')
return build.method('cfg', build.identifier('rust'), [build.string(ir.value)])
# cfg.has_key('identifier')
return build.method('has_key', build.identifier('cfg'), [build.string(ir.value)])


@ir_to_meson.register
def _(ir: Equal, build: builder.Builder) -> mparser.BaseNode:
return build.equal(ir_to_meson(ir.lhs, build), ir_to_meson(ir.rhs, build))
# cfg.get('identifier', '') == 'value'
return build.equal(
build.method('get', build.identifier('cfg'), [build.string(ir.lhs.value), build.string('')]),
build.string(ir.rhs.value))


@ir_to_meson.register
Expand Down Expand Up @@ -267,3 +270,7 @@ def _(ir: All, build: builder.Builder) -> mparser.BaseNode:
for a in args:
cur = build.and_(ir_to_meson(a, build), cur)
return cur


def cfg_to_meson(raw: str, build: builder.Builder) -> mparser.BaseNode:
return ir_to_meson(parse(lexer(raw)), build)
38 changes: 35 additions & 3 deletions mesonbuild/cargo/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

from . import builder
from . import version
from .cfg import cfg_to_meson
from ..mesonlib import MesonException, Popen_safe, OptionKey
from .. import coredata

Expand Down Expand Up @@ -473,7 +474,7 @@ def _create_features(cargo: Manifest, build: builder.Builder) -> T.List[mparser.
# and one per dependency.
ast: T.List[mparser.BaseNode] = []
ast.append(build.assign(build.dict({}), 'features'))
for depname in cargo.dependencies:
for depname in itertools.chain.from_iterable([cargo.dependencies] + [deps for deps in cargo.target.values()]):
ast.append(build.assign(build.dict({}), _options_varname(depname)))

# Declare a dict that map required dependencies to true
Expand Down Expand Up @@ -510,6 +511,19 @@ def _create_features(cargo: Manifest, build: builder.Builder) -> T.List[mparser.
return ast


def _create_cfg(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseNode]:
# cfg = rust.cargo_cfg(features)
return [
build.assign(
build.method(
'cargo_cfg',
build.identifier('rust'),
[build.method('keys', build.identifier('features'))],
),
'cfg'),
]


def _create_dependency(name: str, dep: Dependency, build: builder.Builder) -> T.List[mparser.BaseNode]:
ast: T.List[mparser.BaseNode] = []
# xxx_options += {'feature-default': true, ...}
Expand Down Expand Up @@ -602,6 +616,15 @@ def _create_dependencies(cargo: Manifest, build: builder.Builder) -> T.List[mpar
ast: T.List[mparser.BaseNode] = []
for name, dep in cargo.dependencies.items():
ast += _create_dependency(name, dep, build)

for condition, dependencies in cargo.target.items():
ifblock: T.List[mparser.BaseNode] = []
elseblock: T.List[mparser.BaseNode] = []
notfound = build.function('dependency', [build.string('')], {'required': build.bool(False)})
for name, dep in dependencies.items():
ifblock += _create_dependency(name, dep, build)
elseblock.append(build.assign(notfound, _dependency_varname(dep.package)))
ast.append(build.if_(cfg_to_meson(condition, build), build.block(ifblock), build.block(elseblock)))
return ast


Expand All @@ -627,7 +650,9 @@ def _create_meson_subdir(cargo: Manifest, build: builder.Builder) -> T.List[mpar
def _create_lib(cargo: Manifest, build: builder.Builder, crate_type: manifest.CRATE_TYPE) -> T.List[mparser.BaseNode]:
dependencies: T.List[mparser.BaseNode] = []
dependency_map: T.Dict[mparser.BaseNode, mparser.BaseNode] = {}
for name, dep in cargo.dependencies.items():
deps_i = [cargo.dependencies.items()]
deps_i += [deps.items() for deps in cargo.target.values()]
for name, dep in itertools.chain.from_iterable(deps_i):
dependencies.append(build.identifier(_dependency_varname(dep.package)))
if name != dep.package:
dependency_map[build.string(fixup_meson_varname(dep.package))] = build.string(name)
Expand Down Expand Up @@ -729,6 +754,7 @@ def interpret(subp_name: str, subdir: str, env: Environment) -> T.Tuple[mparser.
ast = _create_project(cargo, build)
ast += [build.assign(build.function('import', [build.string('rust')]), 'rust')]
ast += _create_features(cargo, build)
ast += _create_cfg(cargo, build)
ast += _create_dependencies(cargo, build)
ast += _create_meson_subdir(cargo, build)

Expand All @@ -745,7 +771,13 @@ def dependencies(source_dir: str) -> T.Dict[str, Dependency]:
deps: T.Dict[str, Dependency] = {}
manifests = _load_manifests(source_dir)
for cargo in manifests.values():
for name, dep in cargo.dependencies.items():
deps_i = [
cargo.dependencies.values(),
cargo.dev_dependencies.values(),
cargo.build_dependencies.values(),
]
deps_i += [deps.values() for deps in cargo.target.values()]
for dep in itertools.chain.from_iterable(deps_i):
depname = _dependency_name(dep.package, dep.api)
deps[depname] = dep
return deps
40 changes: 20 additions & 20 deletions unittests/cargotests.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,42 +153,42 @@ def test_parse(self) -> None:
def test_ir_to_meson(self) -> None:
build = builder.Builder('')

def conf(name: str) -> mparser.BaseNode:
return build.method('cfg', build.identifier('rust'), [build.string(name)])
def conf(name: str, equal: T.Optional[mparser.BaseNode] = None) -> mparser.BaseNode:
if equal:
return build.equal(build.method('get', build.identifier('cfg'), [build.string(name), build.string('')]), equal)
return build.method('has_key', build.identifier('cfg'), [build.string(name)])

cases = [
('target_os = "windows"',
build.equal(conf('target_os'), build.string('windows'))),
('target_arch = "x86"',
build.equal(conf('target_arch'), build.string('x86'))),
('target_family = "unix"',
build.equal(conf('target_family'), build.string('unix'))),
('target_os = "windows"', conf('target_os', build.string('windows'))),
('target_arch = "x86"', conf('target_arch', build.string('x86'))),
('target_family = "unix"', conf('target_family', build.string('unix'))),
('not(target_arch = "x86")',
build.not_(build.equal(conf('target_arch'), build.string('x86')))),
build.not_(conf('target_arch', build.string('x86')))),
('any(target_arch = "x86", target_arch = "x86_64")',
build.or_(
build.equal(conf('target_arch'), build.string('x86')),
build.equal(conf('target_arch'), build.string('x86_64')))),
conf('target_arch', build.string('x86')),
conf('target_arch', build.string('x86_64')))),
('any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")',
build.or_(
build.equal(conf('target_arch'), build.string('x86')),
conf('target_arch', build.string('x86')),
build.or_(
build.equal(conf('target_arch'), build.string('x86_64')),
build.equal(conf('target_arch'), build.string('aarch64'))))),
conf('target_arch', build.string('x86_64')),
conf('target_arch', build.string('aarch64'))))),
('all(target_arch = "x86", target_arch = "x86_64")',
build.and_(
build.equal(conf('target_arch'), build.string('x86')),
build.equal(conf('target_arch'), build.string('x86_64')))),
conf('target_arch', build.string('x86')),
conf('target_arch', build.string('x86_64')))),
('all(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")',
build.and_(
build.equal(conf('target_arch'), build.string('x86')),
conf('target_arch', build.string('x86')),
build.and_(
build.equal(conf('target_arch'), build.string('x86_64')),
build.equal(conf('target_arch'), build.string('aarch64'))))),
conf('target_arch', build.string('x86_64')),
conf('target_arch', build.string('aarch64'))))),
('any(unix, windows)', build.or_(conf('unix'), conf('windows'))),
('all()', build.bool(True)),
('any()', build.bool(False)),
]
for data, expected in cases:
with self.subTest():
value = cfg.ir_to_meson(cfg.parse(iter(cfg.lexer(data))), build)
value = cfg.cfg_to_meson(data, build)
self.assertEqual(value, expected)

0 comments on commit a9f9523

Please sign in to comment.