#232 rust2rpm: fix edge cases in cfg-expression evaluation
Merged a year ago by decathorpe. Opened a year ago by decathorpe.
Unknown source main  into  main

file modified
+9
@@ -1,3 +1,12 @@

  from . import licensing

  

  __version__ = "23"

+ 

+ TARGET_ARCHES = [

+     "x86_64",

+     "x86",

+     "aarch64",

+     "arm",

+     "powerpc64",

+     "s390x",

+ ]

file modified
+18 -12
@@ -5,6 +5,7 @@

  from pyparsing import ParseException

  

  from . import log

+ from . import TARGET_ARCHES

  

  pp.ParserElement.enablePackrat()

  
@@ -60,7 +61,7 @@

  

  

  @functools.cache

- def evaluate_predicate(name: str, value: str) -> bool:

+ def evaluate_predicate(name: str, value: str, target_arch: str) -> bool:

      # based on: https://doc.rust-lang.org/reference/conditional-compilation.html

  

      match name:
@@ -68,7 +69,7 @@

              # Needs to be ignored, as we cannot generate patches that are

              # different depending on the host architecture - except if the

              # target architecture is "wasm32", which we don't support.

-             return value not in ["wasm32", "wasm64"]

+             return value == target_arch

  

          case "target_feature":

              # The "target_feature" predicate can be ignored as well, since the
@@ -114,30 +115,32 @@

              return True

          case "windows":

              return False

+         case "miri":

+             return False

          case _:

              log.warn(

                  f"Ignoring unknown identifier {name!r} in cfg-expression. "

-                 + 'Only "unix" and "windows" are standard identifiers, '

-                 + 'any non-standard "--cfg" flags are not supported.'

+                 + 'only "unix", "windows", and "miri" are standard identifiers; '

+                 + 'any non-standard "--cfg" flags are ignored.'

              )

              return False

  

  

- def evaluate(expr, nested=False) -> bool:

+ def evaluate(expr, target_arch: str, nested: bool = False) -> bool:

      if hasattr(expr, "asList"):

          expr = expr.asList()  # compat with pyparsing 2.7.x

      match expr:

          case ["cfg", subexpr] if not nested:

-             return evaluate(subexpr, True)

+             return evaluate(subexpr, target_arch, True)

          case ["not", subexpr] if nested:

-             return not evaluate(subexpr, True)

+             return not evaluate(subexpr, target_arch, True)

          case ["all", *args] if nested:

-             return all(evaluate(arg, True) for arg in args)

+             return all(evaluate(arg, target_arch, True) for arg in args)

          case ["any", *args] if nested:

-             return any(evaluate(arg, True) for arg in args)

+             return any(evaluate(arg, target_arch, True) for arg in args)

          case [variable, value] if nested:

              v = ast.literal_eval(value)

-             return evaluate_predicate(variable, v)

+             return evaluate_predicate(variable, v, target_arch)

          case [variable] if nested:

              return evaluate_atom(variable)

          case _:
@@ -145,5 +148,8 @@

  

  

  def parse_and_evaluate(expr):

-     parsed = cfg_grammar().parseString(expr)

-     return evaluate(parsed[0])

+     parsed = cfg_grammar().parseString(expr)[0]

+ 

+     # evaluate cfg-expression for all supported target_arch values

+     # returns True if it evaluates to True for any supported architecture

+     return any(evaluate(parsed, target_arch) for target_arch in TARGET_ARCHES)

@@ -26,6 +26,7 @@

          ("cfg(unix)", True),

          ("cfg(not(unix))", False),

          ("cfg(windows)", False),

+         ("cfg(miri)", False),

          ("cfg(linux)", False),  # not defined

          ("cfg(not(windows))", True),

          ("cfg(any(unix, windows))", True),
@@ -36,6 +37,32 @@

          ('cfg(all(target_os = "linux"))', True),

          ('cfg(any(target_os = "linux", target_os = "macos"))', True),

          ('cfg(any(target_pointer_width = "16", target_pointer_width = "32", target_pointer_width = "64"))', True),

+         # from rustix 0.35.12

+         ('cfg(any(target_os = "android", target_os = "linux"))', True),

+         (

+             'cfg(all(not(rustix_use_libc), not(miri), target_os = "linux", '

+             'any(target_arch = "x86", all(target_arch = "x86_64", target_pointer_width = "64"), '

+             'all(target_endian = "little", any(target_arch = "arm", '

+             'all(target_arch = "aarch64", target_pointer_width = "64"), '

+             'target_arch = "powerpc64", target_arch = "riscv64", target_arch = "mips", target_arch = "mips64")))))',

+             True,

+         ),

+         (

+             'cfg(any(rustix_use_libc, miri, not(all(target_os = "linux", '

+             'any(target_arch = "x86", all(target_arch = "x86_64", target_pointer_width = "64"), '

+             'all(target_endian = "little", any(target_arch = "arm", '

+             'all(target_arch = "aarch64", target_pointer_width = "64"), '

+             'target_arch = "powerpc64", target_arch = "riscv64", target_arch = "mips", target_arch = "mips64")))))))',

+             True,

+         ),

+         ('cfg(not(target_os = "emscripten"))', True),

+         # from tokio 1.21.2

+         ('cfg(all(any(target_arch = "wasm32", target_arch = "wasm64"), not(target_os = "wasi")))', False),

+         ("cfg(loom)", False),

+         ('cfg(not(all(any(target_arch = "wasm32", target_arch = "wasm64"), target_os = "unknown")))', True),

+         ('cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))', True),

+         ('cfg(target_os = "freebsd")', False),

+         ("cfg(tokio_unstable)", False),

      ],

  )

  def test_expressions(expr, expected):

Some cfg-expressions evaluated to "False" because all target_arch
checks were evaluated as "True", but that broke in situations where
the cfg-expression checked for the absence of a match for a specific
target_arch.

With this change, cfg-expressions are now evaluated once for every
supported target_arch, and they evaluate to "True" if the expression
evaluated to "True" for any value of target_arch.

Fixes #231

1 new commit added

  • Add script for checking reverse crate dependencies
a year ago

1 new commit added

  • rust2rpm: fix edge cases in cfg-expression evaluation
a year ago

This looks like it works as intended, and doesn't break any existing tests. I'll merge this and backport the patch to rust2rpm v23 in Fedora.

Pull-Request has been merged by decathorpe

a year ago