Skip to content

Commit bf2075e

Browse files
committed
cargo: Do not convert cfg() to Meson AST
We'll need to evaluate those expressions before generating the AST. Instead take a config key-value dictionary and evaluate the expression to return a boolean.
1 parent 474d77d commit bf2075e

File tree

2 files changed

+36
-107
lines changed

2 files changed

+36
-107
lines changed

mesonbuild/cargo/cfg.py

Lines changed: 17 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,9 @@
2323
from __future__ import annotations
2424
import dataclasses
2525
import enum
26-
import functools
2726
import typing as T
2827

2928

30-
from . import builder
31-
from .. import mparser
3229
from ..mesonlib import MesonBugException
3330

3431
if T.TYPE_CHECKING:
@@ -144,8 +141,8 @@ class Identifier(IR):
144141
@dataclasses.dataclass
145142
class Equal(IR):
146143

147-
lhs: IR
148-
rhs: IR
144+
lhs: Identifier
145+
rhs: String
149146

150147

151148
@dataclasses.dataclass
@@ -219,57 +216,20 @@ def parse(ast: _LEX_STREAM) -> IR:
219216
return _parse(ast_i)
220217

221218

222-
@functools.singledispatch
223-
def ir_to_meson(ir: T.Any, build: builder.Builder) -> mparser.BaseNode:
224-
raise NotImplementedError
225-
226-
227-
@ir_to_meson.register
228-
def _(ir: String, build: builder.Builder) -> mparser.BaseNode:
229-
return build.string(ir.value)
230-
231-
232-
@ir_to_meson.register
233-
def _(ir: Identifier, build: builder.Builder) -> mparser.BaseNode:
234-
host_machine = build.identifier('host_machine')
235-
if ir.value == "target_arch":
236-
return build.method('cpu_family', host_machine)
237-
elif ir.value in {"target_os", "target_family"}:
238-
return build.method('system', host_machine)
239-
elif ir.value == "target_endian":
240-
return build.method('endian', host_machine)
241-
raise MesonBugException(f"Unhandled Cargo identifier: {ir.value}")
242-
243-
244-
@ir_to_meson.register
245-
def _(ir: Equal, build: builder.Builder) -> mparser.BaseNode:
246-
return build.equal(ir_to_meson(ir.lhs, build), ir_to_meson(ir.rhs, build))
247-
248-
249-
@ir_to_meson.register
250-
def _(ir: Not, build: builder.Builder) -> mparser.BaseNode:
251-
return build.not_(ir_to_meson(ir.value, build))
252-
253-
254-
@ir_to_meson.register
255-
def _(ir: Any, build: builder.Builder) -> mparser.BaseNode:
256-
if not ir.args:
257-
return build.bool(False)
258-
args = iter(reversed(ir.args))
259-
last = next(args)
260-
cur = build.or_(ir_to_meson(next(args), build), ir_to_meson(last, build))
261-
for a in args:
262-
cur = build.or_(ir_to_meson(a, build), cur)
263-
return cur
219+
def _eval_cfg(ir: IR, cfgs: T.Dict[str, str]) -> bool:
220+
if isinstance(ir, Identifier):
221+
return ir.value in cfgs
222+
elif isinstance(ir, Equal):
223+
return cfgs.get(ir.lhs.value) == ir.rhs.value
224+
elif isinstance(ir, Not):
225+
return not _eval_cfg(ir.value, cfgs)
226+
elif isinstance(ir, Any):
227+
return any(_eval_cfg(i, cfgs) for i in ir.args)
228+
elif isinstance(ir, All):
229+
return all(_eval_cfg(i, cfgs) for i in ir.args)
230+
else:
231+
raise MesonBugException(f'Unhandled Cargo cfg IR: {ir}')
264232

265233

266-
@ir_to_meson.register
267-
def _(ir: All, build: builder.Builder) -> mparser.BaseNode:
268-
if not ir.args:
269-
return build.bool(True)
270-
args = iter(reversed(ir.args))
271-
last = next(args)
272-
cur = build.and_(ir_to_meson(next(args), build), ir_to_meson(last, build))
273-
for a in args:
274-
cur = build.and_(ir_to_meson(a, build), cur)
275-
return cur
234+
def eval_cfg(raw: str, cfgs: T.Dict[str, str]) -> bool:
235+
return _eval_cfg(parse(lexer(raw)), cfgs)

unittests/cargotests.py

Lines changed: 19 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -151,60 +151,29 @@ def test_parse(self) -> None:
151151
with self.subTest():
152152
self.assertEqual(cfg.parse(iter(cfg.lexer(data))), expected)
153153

154-
def test_ir_to_meson(self) -> None:
155-
build = builder.Builder('')
156-
HOST_MACHINE = build.identifier('host_machine')
157-
154+
def test_eval_ir(self) -> None:
155+
d = {
156+
'target_os': 'unix',
157+
'unix': '',
158+
}
158159
cases = [
159-
('target_os = "windows"',
160-
build.equal(build.method('system', HOST_MACHINE),
161-
build.string('windows'))),
162-
('target_arch = "x86"',
163-
build.equal(build.method('cpu_family', HOST_MACHINE),
164-
build.string('x86'))),
165-
('target_family = "unix"',
166-
build.equal(build.method('system', HOST_MACHINE),
167-
build.string('unix'))),
168-
('not(target_arch = "x86")',
169-
build.not_(build.equal(
170-
build.method('cpu_family', HOST_MACHINE),
171-
build.string('x86')))),
172-
('any(target_arch = "x86", target_arch = "x86_64")',
173-
build.or_(
174-
build.equal(build.method('cpu_family', HOST_MACHINE),
175-
build.string('x86')),
176-
build.equal(build.method('cpu_family', HOST_MACHINE),
177-
build.string('x86_64')))),
178-
('any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")',
179-
build.or_(
180-
build.equal(build.method('cpu_family', HOST_MACHINE),
181-
build.string('x86')),
182-
build.or_(
183-
build.equal(build.method('cpu_family', HOST_MACHINE),
184-
build.string('x86_64')),
185-
build.equal(build.method('cpu_family', HOST_MACHINE),
186-
build.string('aarch64'))))),
187-
('all(target_arch = "x86", target_arch = "x86_64")',
188-
build.and_(
189-
build.equal(build.method('cpu_family', HOST_MACHINE),
190-
build.string('x86')),
191-
build.equal(build.method('cpu_family', HOST_MACHINE),
192-
build.string('x86_64')))),
193-
('all(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")',
194-
build.and_(
195-
build.equal(build.method('cpu_family', HOST_MACHINE),
196-
build.string('x86')),
197-
build.and_(
198-
build.equal(build.method('cpu_family', HOST_MACHINE),
199-
build.string('x86_64')),
200-
build.equal(build.method('cpu_family', HOST_MACHINE),
201-
build.string('aarch64'))))),
202-
('all()', build.bool(True)),
203-
('any()', build.bool(False)),
160+
('target_os = "windows"', False),
161+
('target_os = "unix"', True),
162+
('doesnotexist = "unix"', False),
163+
('not(target_os = "windows")', True),
164+
('any(target_os = "windows", target_arch = "x86_64")', False),
165+
('any(target_os = "windows", target_os = "unix")', True),
166+
('all(target_os = "windows", target_os = "unix")', False),
167+
('all(not(target_os = "windows"), target_os = "unix")', True),
168+
('any(unix, windows)', True),
169+
('all()', True),
170+
('any()', False),
171+
('cfg(unix)', True),
172+
('cfg(windows)', False),
204173
]
205174
for data, expected in cases:
206175
with self.subTest():
207-
value = cfg.ir_to_meson(cfg.parse(iter(cfg.lexer(data))), build)
176+
value = cfg.eval_cfg(data, d)
208177
self.assertEqual(value, expected)
209178

210179
class CargoLockTest(unittest.TestCase):

0 commit comments

Comments
 (0)