Skip to content

Commit 7787522

Browse files
committed
ci: derive ToolchainFeatureSupport from conanfile.py via AST
Instead of duplicating the compiler version thresholds in generate-job-matrix.py (e.g. std_format=version >= 13 for GCC), parse _feature_compatibility directly from conanfile.py using the ast module. This makes conanfile.py the single source of truth for compiler feature support, and the CI matrix generator stays in sync automatically whenever conanfile.py is updated.
1 parent 578441e commit 7787522

1 file changed

Lines changed: 43 additions & 21 deletions

File tree

.github/generate-job-matrix.py

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,58 @@
11
import argparse
2+
import ast
23
import json
34
import os
5+
import pathlib
46
import random
57
import typing
68
from types import SimpleNamespace
79

10+
from job_matrix import ToolchainFeatureSupport # used by _make_feature_support
811
from job_matrix import (
912
CombinationCollector,
1013
Compiler,
1114
ConanOptions,
1215
Configuration,
1316
Toolchain,
14-
ToolchainFeatureSupport,
1517
)
1618

1719

20+
def _load_feature_compat() -> dict:
21+
"""Parse _feature_compatibility from conanfile.py via AST (no Conan import needed)."""
22+
conanfile = pathlib.Path(__file__).parent.parent / "conanfile.py"
23+
tree = ast.parse(conanfile.read_text())
24+
for node in ast.walk(tree):
25+
if (
26+
isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))
27+
and node.name == "_feature_compatibility"
28+
):
29+
for stmt in node.body:
30+
if isinstance(stmt, ast.Return):
31+
return ast.literal_eval(stmt.value)
32+
raise RuntimeError("Could not find _feature_compatibility in conanfile.py")
33+
34+
35+
_FEATURE_COMPAT = _load_feature_compat()
36+
37+
38+
def _make_feature_support(
39+
conan_compiler: str, version: int, *, freestanding: bool = False
40+
) -> ToolchainFeatureSupport:
41+
"""Derive ToolchainFeatureSupport from conanfile.py's _feature_compatibility."""
42+
43+
def supports(feature: str) -> bool:
44+
min_ver = _FEATURE_COMPAT[feature]["compiler"].get(conan_compiler)
45+
return bool(min_ver and version >= int(min_ver))
46+
47+
return ToolchainFeatureSupport(
48+
cxx_modules=supports("cxx_modules"),
49+
std_format=supports("std_format"),
50+
import_std=supports("import_std"),
51+
explicit_this=supports("explicit_this"),
52+
freestanding=freestanding,
53+
)
54+
55+
1856
def make_gcc_config(version: int) -> Toolchain:
1957
return Toolchain(
2058
name=f"GCC-{version}",
@@ -25,11 +63,7 @@ def make_gcc_config(version: int) -> Toolchain:
2563
cc=f"gcc-{version}",
2664
cxx=f"g++-{version}",
2765
),
28-
feature_support=ToolchainFeatureSupport(
29-
std_format=version >= 13,
30-
explicit_this=version >= 14,
31-
freestanding=True,
32-
),
66+
feature_support=_make_feature_support("gcc", version, freestanding=True),
3367
)
3468

3569

@@ -43,13 +77,7 @@ def make_clang_config(
4377
version=version,
4478
),
4579
lib="libc++",
46-
feature_support=ToolchainFeatureSupport(
47-
cxx_modules=version >= 17,
48-
std_format=version >= 17,
49-
import_std=version >= 18,
50-
explicit_this=version >= 18,
51-
freestanding=True,
52-
),
80+
feature_support=_make_feature_support("clang", version, freestanding=True),
5381
)
5482
match architecture:
5583
case "x86-64":
@@ -79,10 +107,7 @@ def make_apple_clang_config(os: str, version: str) -> Toolchain:
79107
cc="clang",
80108
cxx="clang++",
81109
),
82-
feature_support=ToolchainFeatureSupport(
83-
std_format=major_version >= 16,
84-
explicit_this=major_version >= 17,
85-
),
110+
feature_support=_make_feature_support("apple-clang", major_version),
86111
)
87112
return ret
88113

@@ -97,10 +122,7 @@ def make_msvc_config(release: str, version: int) -> Toolchain:
97122
cc="",
98123
cxx="",
99124
),
100-
feature_support=ToolchainFeatureSupport(
101-
std_format=version >= 194,
102-
explicit_this=version >= 194,
103-
),
125+
feature_support=_make_feature_support("msvc", version),
104126
)
105127
return ret
106128

0 commit comments

Comments
 (0)