autogen: dump patch in CI (#14010)

* autogen: don't fast-fail, produce patch artifact on differences

All verification steps now use continue-on-error to run completely.
Each job generates a patch artifact containing all differences found.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* add gen from header test

* fix tests

* fail if diff

* add forward decl autogen test

* remove confusing/wrong comments

* macos unittests set LIBCLANG_PATH

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Christopher Milan
2026-01-04 19:38:12 -08:00
committed by GitHub
parent aae08b20e0
commit b2a0b9c551
3 changed files with 149 additions and 1 deletions

View File

@@ -40,11 +40,13 @@ jobs:
- name: Install autogen support packages - name: Install autogen support packages
run: sudo apt-get install -y --no-install-recommends libclang-20-dev llvm-20-dev hip-dev libusb-1.0-0-dev run: sudo apt-get install -y --no-install-recommends libclang-20-dev llvm-20-dev hip-dev libusb-1.0-0-dev
- name: Verify OpenCL autogen - name: Verify OpenCL autogen
continue-on-error: true
run: | run: |
mv tinygrad/runtime/autogen/opencl.py /tmp/opencl.py.bak mv tinygrad/runtime/autogen/opencl.py /tmp/opencl.py.bak
python3 -c "from tinygrad.runtime.autogen import opencl" python3 -c "from tinygrad.runtime.autogen import opencl"
diff /tmp/opencl.py.bak tinygrad/runtime/autogen/opencl.py diff /tmp/opencl.py.bak tinygrad/runtime/autogen/opencl.py
- name: Verify CUDA autogen - name: Verify CUDA autogen
continue-on-error: true
run: | run: |
mv tinygrad/runtime/autogen/cuda.py /tmp/cuda.py.bak mv tinygrad/runtime/autogen/cuda.py /tmp/cuda.py.bak
mv tinygrad/runtime/autogen/nvrtc.py /tmp/nvrtc.py.bak mv tinygrad/runtime/autogen/nvrtc.py /tmp/nvrtc.py.bak
@@ -58,6 +60,7 @@ jobs:
diff /tmp/nv_570.py.bak tinygrad/runtime/autogen/nv_570.py diff /tmp/nv_570.py.bak tinygrad/runtime/autogen/nv_570.py
diff /tmp/nv.py.bak tinygrad/runtime/autogen/nv.py diff /tmp/nv.py.bak tinygrad/runtime/autogen/nv.py
- name: Verify AMD autogen - name: Verify AMD autogen
continue-on-error: true
run: | run: |
mv tinygrad/runtime/autogen/comgr.py /tmp/comgr.py.bak mv tinygrad/runtime/autogen/comgr.py /tmp/comgr.py.bak
mv tinygrad/runtime/autogen/hsa.py /tmp/hsa.py.bak mv tinygrad/runtime/autogen/hsa.py /tmp/hsa.py.bak
@@ -89,6 +92,7 @@ jobs:
diff /tmp/am_smu_v13_0_0.py.bak tinygrad/runtime/autogen/am/smu_v13_0_0.py diff /tmp/am_smu_v13_0_0.py.bak tinygrad/runtime/autogen/am/smu_v13_0_0.py
diff /tmp/am_smu_v14_0_2.py.bak tinygrad/runtime/autogen/am/smu_v14_0_2.py diff /tmp/am_smu_v14_0_2.py.bak tinygrad/runtime/autogen/am/smu_v14_0_2.py
- name: Verify Linux autogen - name: Verify Linux autogen
continue-on-error: true
run: | run: |
mv tinygrad/runtime/autogen/libc.py /tmp/libc.py.bak mv tinygrad/runtime/autogen/libc.py /tmp/libc.py.bak
mv tinygrad/runtime/autogen/kfd.py /tmp/kfd.py.bak mv tinygrad/runtime/autogen/kfd.py /tmp/kfd.py.bak
@@ -104,16 +108,19 @@ jobs:
diff /tmp/pci.py.bak tinygrad/runtime/autogen/pci.py diff /tmp/pci.py.bak tinygrad/runtime/autogen/pci.py
diff /tmp/vfio.py.bak tinygrad/runtime/autogen/vfio.py diff /tmp/vfio.py.bak tinygrad/runtime/autogen/vfio.py
- name: Verify LLVM autogen - name: Verify LLVM autogen
continue-on-error: true
run: | run: |
mv tinygrad/runtime/autogen/llvm.py /tmp/llvm.py.bak mv tinygrad/runtime/autogen/llvm.py /tmp/llvm.py.bak
python3 -c "from tinygrad.runtime.autogen import llvm" python3 -c "from tinygrad.runtime.autogen import llvm"
diff /tmp/llvm.py.bak tinygrad/runtime/autogen/llvm.py diff /tmp/llvm.py.bak tinygrad/runtime/autogen/llvm.py
- name: Verify WebGPU autogen - name: Verify WebGPU autogen
continue-on-error: true
run: | run: |
mv tinygrad/runtime/autogen/webgpu.py /tmp/webgpu.py.bak mv tinygrad/runtime/autogen/webgpu.py /tmp/webgpu.py.bak
python3 -c "from tinygrad.runtime.autogen import webgpu" python3 -c "from tinygrad.runtime.autogen import webgpu"
diff /tmp/webgpu.py.bak tinygrad/runtime/autogen/webgpu.py diff /tmp/webgpu.py.bak tinygrad/runtime/autogen/webgpu.py
- name: Verify Qualcomm autogen - name: Verify Qualcomm autogen
continue-on-error: true
run: | run: |
mv tinygrad/runtime/autogen/kgsl.py /tmp/kgsl.py.bak mv tinygrad/runtime/autogen/kgsl.py /tmp/kgsl.py.bak
mv tinygrad/runtime/autogen/qcom_dsp.py /tmp/qcom_dsp.py.bak mv tinygrad/runtime/autogen/qcom_dsp.py /tmp/qcom_dsp.py.bak
@@ -121,20 +128,36 @@ jobs:
diff /tmp/kgsl.py.bak tinygrad/runtime/autogen/kgsl.py diff /tmp/kgsl.py.bak tinygrad/runtime/autogen/kgsl.py
diff /tmp/qcom_dsp.py.bak tinygrad/runtime/autogen/qcom_dsp.py diff /tmp/qcom_dsp.py.bak tinygrad/runtime/autogen/qcom_dsp.py
- name: Verify libusb autogen - name: Verify libusb autogen
continue-on-error: true
run: | run: |
mv tinygrad/runtime/autogen/libusb.py /tmp/libusb.py.bak mv tinygrad/runtime/autogen/libusb.py /tmp/libusb.py.bak
python3 -c "from tinygrad.runtime.autogen import libusb" python3 -c "from tinygrad.runtime.autogen import libusb"
diff /tmp/libusb.py.bak tinygrad/runtime/autogen/libusb.py diff /tmp/libusb.py.bak tinygrad/runtime/autogen/libusb.py
- name: Verify mesa autogen - name: Verify mesa autogen
continue-on-error: true
run: | run: |
mv tinygrad/runtime/autogen/mesa.py /tmp/mesa.py.bak mv tinygrad/runtime/autogen/mesa.py /tmp/mesa.py.bak
python3 -c "from tinygrad.runtime.autogen import mesa" python3 -c "from tinygrad.runtime.autogen import mesa"
diff /tmp/mesa.py.bak tinygrad/runtime/autogen/mesa.py diff /tmp/mesa.py.bak tinygrad/runtime/autogen/mesa.py
- name: Verify libclang autogen - name: Verify libclang autogen
continue-on-error: true
run: | run: |
cp tinygrad/runtime/autogen/libclang.py /tmp/libclang.py.bak cp tinygrad/runtime/autogen/libclang.py /tmp/libclang.py.bak
REGEN=1 python3 -c "from tinygrad.runtime.autogen import libclang" REGEN=1 python3 -c "from tinygrad.runtime.autogen import libclang"
diff /tmp/libclang.py.bak tinygrad/runtime/autogen/libclang.py diff /tmp/libclang.py.bak tinygrad/runtime/autogen/libclang.py
- name: Generate patch for differences
run: |
if ! git diff --quiet; then
git diff > autogen-ubuntu.patch
fi
- name: Upload patch artifact
uses: actions/upload-artifact@v4
with:
name: autogen-ubuntu-patch
path: autogen-ubuntu.patch
if-no-files-found: ignore
- name: Fail if differences found
run: git diff --quiet
autogen-mac: autogen-mac:
name: In-tree Autogen (macos) name: In-tree Autogen (macos)
runs-on: macos-14 runs-on: macos-14
@@ -147,10 +170,24 @@ jobs:
with: with:
llvm: 'true' llvm: 'true'
- name: Verify macos autogen - name: Verify macos autogen
continue-on-error: true
run: | run: |
mv tinygrad/runtime/autogen/metal.py /tmp/metal.py.bak mv tinygrad/runtime/autogen/metal.py /tmp/metal.py.bak
LIBCLANG_PATH=/opt/homebrew/opt/llvm@20/lib/libclang.dylib python3 -c "from tinygrad.runtime.autogen import metal" LIBCLANG_PATH=/opt/homebrew/opt/llvm@20/lib/libclang.dylib python3 -c "from tinygrad.runtime.autogen import metal"
diff /tmp/metal.py.bak tinygrad/runtime/autogen/metal.py diff /tmp/metal.py.bak tinygrad/runtime/autogen/metal.py
- name: Generate patch for differences
run: |
if ! git diff --quiet; then
git diff > autogen-macos.patch
fi
- name: Upload patch artifact
uses: actions/upload-artifact@v4
with:
name: autogen-macos-patch
path: autogen-macos.patch
if-no-files-found: ignore
- name: Fail if differences found
run: git diff --quiet
autogen-comgr-3: autogen-comgr-3:
name: In-tree Autogen (comgr 3) name: In-tree Autogen (comgr 3)
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
@@ -170,7 +207,21 @@ jobs:
sudo apt -qq update || true sudo apt -qq update || true
sudo apt-get install -y --no-install-recommends libclang-20-dev comgr sudo apt-get install -y --no-install-recommends libclang-20-dev comgr
- name: Verify comgr (3) autogen - name: Verify comgr (3) autogen
continue-on-error: true
run: | run: |
mv tinygrad/runtime/autogen/comgr_3.py /tmp/comgr_3.py.bak mv tinygrad/runtime/autogen/comgr_3.py /tmp/comgr_3.py.bak
python3 -c "from tinygrad.runtime.autogen import comgr_3" python3 -c "from tinygrad.runtime.autogen import comgr_3"
diff /tmp/comgr_3.py.bak tinygrad/runtime/autogen/comgr_3.py diff /tmp/comgr_3.py.bak tinygrad/runtime/autogen/comgr_3.py
- name: Generate patch for differences
run: |
if ! git diff --quiet; then
git diff > autogen-comgr3.patch
fi
- name: Upload patch artifact
uses: actions/upload-artifact@v4
with:
name: autogen-comgr3-patch
path: autogen-comgr3.patch
if-no-files-found: ignore
- name: Fail if differences found
run: git diff --quiet

View File

@@ -257,6 +257,7 @@ jobs:
key: unittest-12 key: unittest-12
pydeps: "pillow numpy ftfy regex" pydeps: "pillow numpy ftfy regex"
deps: testing_unit deps: testing_unit
llvm: 'true'
- name: Check Device.DEFAULT - name: Check Device.DEFAULT
run: python -c "from tinygrad import Device; assert Device.DEFAULT == 'CPU', Device.DEFAULT" run: python -c "from tinygrad import Device; assert Device.DEFAULT == 'CPU', Device.DEFAULT"
- name: Run unit tests - name: Run unit tests
@@ -309,7 +310,7 @@ jobs:
deps: testing_unit deps: testing_unit
python-version: '3.14' python-version: '3.14'
- name: Test SPEC=2 - name: Test SPEC=2
run: SPEC=2 pytest --maxfail=10 -n auto --durations=30 --ignore=test/models --ignore test/test_custom_kernel.py --ignore test/unit/test_hashing.py --timeout 60 -k "not test_setitem_big" --splits 2 --group ${{ matrix.group }} run: SPEC=2 pytest --maxfail=10 -n auto --durations=30 --ignore=test/models --ignore test/test_custom_kernel.py --ignore test/unit/test_hashing.py --ignore test/unit/test_autogen.py --timeout 60 -k "not test_setitem_big" --splits 2 --group ${{ matrix.group }}
fuzzing: fuzzing:
name: Fuzzing name: Fuzzing
@@ -793,6 +794,8 @@ jobs:
ocelot: 'true' ocelot: 'true'
llvm: 'true' llvm: 'true'
- name: Run unit tests - name: Run unit tests
env:
LIBCLANG_PATH: '/opt/homebrew/opt/llvm@20/lib/libclang.dylib'
run: METAL=1 python -m pytest -n=auto test/unit/ --durations=20 run: METAL=1 python -m pytest -n=auto test/unit/ --durations=20
- name: Run ONNX - name: Run ONNX
run: METAL=1 python -m pytest -n=auto test/external/external_test_onnx_backend.py --durations=20 run: METAL=1 python -m pytest -n=auto test/external/external_test_onnx_backend.py --durations=20

View File

@@ -1,6 +1,7 @@
import ctypes, subprocess, tempfile, unittest import ctypes, subprocess, tempfile, unittest
from tinygrad.helpers import WIN from tinygrad.helpers import WIN
from tinygrad.runtime.support.c import Struct from tinygrad.runtime.support.c import Struct
from tinygrad.runtime.support.autogen import gen
class TestAutogen(unittest.TestCase): class TestAutogen(unittest.TestCase):
def test_packed_struct_sizeof(self): def test_packed_struct_sizeof(self):
@@ -159,4 +160,97 @@ class TestAutogen(unittest.TestCase):
assert ihdr.num_dies == 1 assert ihdr.num_dies == 1
assert ihdr.base_addr_64_bit == 1 assert ihdr.base_addr_64_bit == 1
@unittest.skipIf(WIN, "doesn't compile on windows")
def test_gen_from_header(self):
header_content = """
typedef struct {
int x;
int y;
} Point;
typedef enum {
RED = 0,
GREEN = 1,
BLUE = 2
} Color;
typedef struct {
Point origin;
int width;
int height;
Color color;
} Rectangle;
int add_points(Point a, Point b);
"""
with tempfile.NamedTemporaryFile(mode='w', suffix='.h') as f:
f.write(header_content)
f.flush()
generated_code = gen(name="test_header", dll=None, files=[f.name])
namespace = {}
exec(generated_code, namespace)
self.assertIn('Point', namespace)
self.assertIn('Color', namespace)
self.assertIn('Rectangle', namespace)
self.assertIn('RED', namespace)
self.assertIn('GREEN', namespace)
self.assertIn('BLUE', namespace)
self.assertEqual(namespace['RED'], 0)
self.assertEqual(namespace['GREEN'], 1)
self.assertEqual(namespace['BLUE'], 2)
Point = namespace['Point']
p = Point()
self.assertIsInstance(p, Struct)
self.assertTrue(hasattr(p, 'x'))
self.assertTrue(hasattr(p, 'y'))
Rectangle = namespace['Rectangle']
rect = Rectangle()
self.assertTrue(hasattr(rect, 'origin'))
self.assertTrue(hasattr(rect, 'width'))
self.assertTrue(hasattr(rect, 'height'))
self.assertTrue(hasattr(rect, 'color'))
@unittest.skipIf(WIN, "doesn't compile on windows")
def test_struct_ordering(self):
header_content = """
struct A;
struct C;
typedef struct A A;
struct B {
struct C *c_ptr;
};
struct C {
struct A *a_ptr;
};
struct A {
int x;
struct B *b_ptr;
};
"""
with tempfile.NamedTemporaryFile(mode='w', suffix='.h') as f:
f.write(header_content)
f.flush()
generated_code = gen(name="test_ordering", dll=None, files=[f.name])
namespace = {}
exec(generated_code, namespace)
self.assertIn('struct_A', namespace)
self.assertIn('struct_B', namespace)
self.assertIn('struct_C', namespace)
A, B, C = namespace['struct_A'], namespace['struct_B'], namespace['struct_C']
a, b, c = A(), B(), C()
self.assertTrue(hasattr(a, 'x'))
self.assertTrue(hasattr(a, 'b_ptr'))
self.assertTrue(hasattr(b, 'c_ptr'))
self.assertTrue(hasattr(c, 'a_ptr'))
if __name__ == "__main__": unittest.main() if __name__ == "__main__": unittest.main()