Skip to content

Commit c456090

Browse files
fix(ci): production-grade cross-platform compatibility
- Fixed pyproject.toml license schema error - Implemented runtime AVX2 check in C++ engine (Safe on old CPUs) - Removed -march=native for stable universal wheels - Fixed cibuildwheel shadowing issue by testing from /tests directory - Restored backward compatibility for ZeroCopy and older demo scripts
1 parent f7bbc5a commit c456090

File tree

3 files changed

+33
-11
lines changed

3 files changed

+33
-11
lines changed

.github/workflows/build_wheels.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ jobs:
3939
# Universal wheels should be CPU-only (CUDA/ROCm are for custom local builds)
4040
CIBW_ENVIRONMENT: CRAYON_FORCE_CPU=1
4141

42-
# 3. Quality Assurance
43-
# Run the test suite against the installed wheel to verify the C-extension
44-
# doesn't segfault and actually works.
45-
CIBW_TEST_COMMAND: python -m unittest discover {project}/tests
42+
# 4. Quality Assurance
43+
# Run the test suite against the installed wheel.
44+
# We 'cd' into tests to ensure it doesn't import from 'src' locally.
45+
CIBW_TEST_COMMAND: cd {project}/tests && python -m unittest discover .
4646

4747
- uses: actions/upload-artifact@v4
4848
with:

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ def _build_hip_extension(self, ext):
200200
ext_modules = []
201201

202202
# --- 1. CPU Extension (Always) ---
203-
cpu_args = ["/O2", "/arch:AVX2"] if sys.platform == "win32" else ["-O3", "-march=native", "-mavx2"]
203+
cpu_args = ["/O2", "/arch:AVX2"] if sys.platform == "win32" else ["-O3", "-mavx2"]
204204
if sys.platform != "win32":
205205
cpu_args.append("-fPIC")
206206
cpu_args.append("-std=c++17")

src/crayon/c_ext/cpu_engine.cpp

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,25 @@
2626
#define USE_AVX2 0
2727
#endif
2828

29+
// Runtime CPU Feature Check
30+
static bool supports_avx2() {
31+
#if USE_AVX2
32+
#ifdef _MSC_VER
33+
int cpu_info[4];
34+
__cpuid(cpu_info, 7);
35+
return (cpu_info[1] & 0x20) != 0;
36+
#else
37+
unsigned int eax, ebx, ecx, edx;
38+
if (__get_cpuid(7, &eax, &ebx, &ecx, &edx)) {
39+
return (ebx & (1 << 5)) != 0;
40+
}
41+
return false;
42+
#endif
43+
#else
44+
return false;
45+
#endif
46+
}
47+
2948
// --- INTERNAL CONTEXT ---
3049
struct DATContext {
3150
const int32_t* base;
@@ -72,12 +91,12 @@ static PyObject* get_hardware_info(PyObject* self, PyObject* args) {
7291
if (cpu_name.empty()) cpu_name = "Unknown CPU";
7392

7493
std::string features = "Standard";
75-
#if USE_AVX2
94+
if (supports_avx2()) {
7695
features = "AVX2";
77-
#if defined(__AVX512F__)
78-
features = "AVX-512 (Nitro)";
79-
#endif
80-
#endif
96+
}
97+
#if defined(__AVX512F__)
98+
features = "AVX-512 (Nitro)";
99+
#endif
81100

82101
std::string info = cpu_name + " [" + features + "]";
83102
return PyUnicode_FromString(info.c_str());
@@ -119,9 +138,12 @@ static PyObject* tokenize(PyObject* self, PyObject* args) {
119138
int best_token = -1;
120139
int best_len = 0;
121140

141+
// Cache runtime capability check
142+
static bool avx2_supported = supports_avx2();
143+
122144
// OPTIMIZATION: Check for pure ASCII block if enough text remains
123145
bool fast_mode = false;
124-
if (USE_AVX2 && (len - pos) >= 32) {
146+
if (USE_AVX2 && avx2_supported && (len - pos) >= 32) {
125147
if (is_ascii_32_avx2(text + pos)) {
126148
fast_mode = true;
127149
}

0 commit comments

Comments
 (0)