Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ jobs:
with:
python-version: "3.12"
- run: python bindgen/extract/test_abi_lock.py
# Constant folding is clang's own, so this one needs a real libclang: the bindings come from
# the wheel, and configure_libclang() picks up the runner image's LLVM as it would locally.
- run: pip install libclang==18.1.1 && python bindgen/extract/test_const_eval.py

smoke:
name: smoke (${{ matrix.platform }})
Expand Down
7 changes: 6 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,16 @@ walkthrough as its acceptance test, and Java-implemented COM upcalls serving imp
2. `./gradlew :bindgen:run --args="api/slang-api.json slang/src/main/java"`
One-time venv setup: `python3 -m venv bindgen/extract/.venv && bindgen/extract/.venv/bin/pip install libclang`.
`api/slang-abi.lock` is append-only ABI enforcement; `--reset-lock` is only for lock-format
migrations and must be justified in the commit message. Struct sizes and derived count
migrations, or — with James's go-ahead — for rebasing onto a break upstream has already
shipped (2026.17 repurposed `IGlobalSession` slot 32; see the 2026.19 bump commit). Either way,
justify it in the commit message and list every lock line it drops. The bump workflow never
resets, so a bump across an upstream break is done by hand. Struct sizes and derived count
sentinels (`CountOf`, `SLANG_STAGE_COUNT`, …) are locked monotonically — they may grow, since
an append moves them by construction — and everything else byte-exact. `python3
bindgen/extract/test_abi_lock.py` covers that arithmetic and needs no libclang; run it after
touching `extract_api.py`, and read the `SENTINEL_NAME` comment before widening the rule.
`bindgen/extract/test_const_eval.py` (venv python, needs libclang) covers global-constant
folding, which a wrong value would otherwise get frozen into the lock.
- ABI-drift canary: `.github/workflows/abi-canary.yml` runs weekly, parsing Slang upstream
headers and enforcing the committed lock (`extract_api.py --verify`, which checks the lock
without rewriting it). A non-append change fails the run; benign additions are reported. Run
Expand Down
23 changes: 14 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,26 @@ directly. Windows, macOS, and Linux, on x86_64 and aarch64. Requires JDK 25+.

| Artifact | Purpose |
|--------------------------------------------------------|---|
| `io.github.refux:slang-java:0.0.9` | The library: compiler API, reflection, Java file systems |
| `io.github.refux:slang-java-natives:0.0.9:<os>-<arch>` | The official Slang binaries, as one classifier per platform: `windows`, `linux`, or `macos` × `x86_64` or `aarch64` |
| `io.github.refux:slang-java:0.0.10` | The library: compiler API, reflection, Java file systems |
| `io.github.refux:slang-java-natives:0.0.10:<os>-<arch>` | The official Slang binaries, as one classifier per platform: `windows`, `linux`, or `macos` × `x86_64` or `aarch64` |

The library version tracks slang-java's own API, not Slang's. To see which Slang release a jar
binds, read its manifest — no resolving, no running:

```bash
unzip -p slang-java-0.0.9.jar META-INF/MANIFEST.MF
unzip -p slang-java-0.0.10.jar META-INF/MANIFEST.MF
```

`Slang-Version` there is a **floor**, not a lockstep: it names the release the bindings were
generated against, and any newer Slang works, because Slang's public ABI is append-only. The same
value is available at runtime as `SlangLibrary.PINNED_SLANG_VERSION`, alongside
`GlobalSession.buildTagString()` for the library actually loaded.

Serialized modules (`Module.serialize()`) are versioned separately and more narrowly: each Slang
release reads only a small range of module versions, so treat them as a cache tied to the release
that wrote them. `Session.loadModuleFromIr` throws a `SlangCompileException` for anything the
loaded Slang cannot read, and `Session.moduleInfo` tells you up front which version a blob is.

## Getting started

Add the library and the natives classifier for your machine — compute it from the host so you
Expand All @@ -46,8 +51,8 @@ val slangNatives = "${
}-${if (System.getProperty("os.arch") in listOf("aarch64", "arm64")) "aarch64" else "x86_64"}"

dependencies {
implementation("io.github.refux:slang-java:0.0.9")
runtimeOnly("io.github.refux:slang-java-natives:0.0.9:$slangNatives")
implementation("io.github.refux:slang-java:0.0.10")
runtimeOnly("io.github.refux:slang-java-natives:0.0.10:$slangNatives")
}

tasks.withType<JavaExec> {
Expand All @@ -60,10 +65,10 @@ classpath together and the loader picks the host's at runtime (LWJGL-style):

```kotlin
dependencies {
implementation("io.github.refux:slang-java:0.0.9")
runtimeOnly("io.github.refux:slang-java-natives:0.0.9:macos-aarch64")
runtimeOnly("io.github.refux:slang-java-natives:0.0.9:windows-x86_64")
runtimeOnly("io.github.refux:slang-java-natives:0.0.9:linux-x86_64")
implementation("io.github.refux:slang-java:0.0.10")
runtimeOnly("io.github.refux:slang-java-natives:0.0.10:macos-aarch64")
runtimeOnly("io.github.refux:slang-java-natives:0.0.10:windows-x86_64")
runtimeOnly("io.github.refux:slang-java-natives:0.0.10:linux-x86_64")
}
```

Expand Down
18 changes: 13 additions & 5 deletions api/slang-abi.lock
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# slang-java ABI lock -- append-only; regenerated by extract_api.py
# slang 2026.16
# slang 2026.19
enum BindingType BaseMask 255
enum BindingType CombinedTextureSampler 7
enum BindingType ConstantBuffer 3
Expand All @@ -21,16 +21,19 @@ enum BindingType TypedBuffer 5
enum BindingType Unknown 0
enum BindingType VaryingInput 11
enum BindingType VaryingOutput 12
enum BitfieldPackingRules Default 0
enum BitfieldPackingRules LegacyMSBFirstMSVC 2
enum BitfieldPackingRules MSVC 1
enum BuiltinModuleName Core 0
enum BuiltinModuleName GLSL 1
enum CompilerOptionName AllowGLSL 91
enum CompilerOptionName ArchiveType 96
enum CompilerOptionName BindlessSpaceIndex 93
enum CompilerOptionName BitfieldPackingRules 160
enum CompilerOptionName Capability 39
enum CompilerOptionName CompileCoreModule 97
enum CompilerOptionName CompilerPath 61
enum CompilerOptionName CompilerVersion 153
enum CompilerOptionName CountOf 158
enum CompilerOptionName CountOf 161
enum CompilerOptionName CountOfParsableOptions 111
enum CompilerOptionName CoverageManifestOutput 150
enum CompilerOptionName DebugInfoIncludeSource 157
Expand Down Expand Up @@ -88,6 +91,7 @@ enum CompilerOptionName ForceCLayout 129
enum CompilerOptionName ForceDXLayout 117
enum CompilerOptionName GLSLForceScalarLayout 55
enum CompilerOptionName GenerateWholeProgram 114
enum CompilerOptionName GetCompilerPath 159
enum CompilerOptionName GetModuleInfo 122
enum CompilerOptionName GetSupportedModuleVersions 123
enum CompilerOptionName Help 4
Expand Down Expand Up @@ -156,6 +160,7 @@ enum CompilerOptionName Target 17
enum CompilerOptionName TraceBranchCoverage 149
enum CompilerOptionName TraceCoverage 145
enum CompilerOptionName TraceCoverageBinding 146
enum CompilerOptionName TraceCoverageBindlessIndex 158
enum CompilerOptionName TraceCoverageBoolean 152
enum CompilerOptionName TraceCoverageCounterByteWidth 151
enum CompilerOptionName TraceCoverageReservedSpace 147
Expand Down Expand Up @@ -442,6 +447,7 @@ enum SlangMiscConstants SLANG_TARGET_FLAG_PARAMETER_BLOCKS_USE_REGISTER_SPACES 1
enum SlangMiscConstants kDefaultTargetFlags 1024
enum SlangMiscConstants kInvalidCoverageCounterIndex 4294967295
enum SlangMiscConstants kSessionFlags_None 0
enum SlangMiscConstants kUnboundedSyntheticResourceArraySize 4294967295
enum SlangModifierID SLANG_MODIFIER_CONST 3
enum SlangModifierID SLANG_MODIFIER_DIFFERENTIABLE 6
enum SlangModifierID SLANG_MODIFIER_EXPORT 4
Expand Down Expand Up @@ -717,6 +723,7 @@ fn spReflectionParameter_GetBindingIndex
fn spReflectionParameter_GetBindingSpace
fn spReflectionTypeLayout_GetCategoryByIndex
fn spReflectionTypeLayout_GetCategoryCount
fn spReflectionTypeLayout_GetContentVarLayout
fn spReflectionTypeLayout_GetElementStride
fn spReflectionTypeLayout_GetElementTypeLayout
fn spReflectionTypeLayout_GetElementVarLayout
Expand Down Expand Up @@ -904,7 +911,7 @@ iface IGlobalSession 29 compileBuiltinModule
iface IGlobalSession 3 createSession
iface IGlobalSession 30 loadBuiltinModule
iface IGlobalSession 31 saveBuiltinModule
iface IGlobalSession 32 getDownstreamCompilerVersion
iface IGlobalSession 32 getDownstreamCompilerPath
iface IGlobalSession 4 findProfile
iface IGlobalSession 5 setDownstreamCompilerPath
iface IGlobalSession 6 setDownstreamCompilerPrelude
Expand Down Expand Up @@ -1092,6 +1099,7 @@ struct SyntheticResourceInfo field access 24
struct SyntheticResourceInfo field arraySize 16
struct SyntheticResourceInfo field binding 36
struct SyntheticResourceInfo field bindingType 12
struct SyntheticResourceInfo field bindlessIndex 56
struct SyntheticResourceInfo field debugName 48
struct SyntheticResourceInfo field entryPointIndex 28
struct SyntheticResourceInfo field id 8
Expand All @@ -1100,7 +1108,7 @@ struct SyntheticResourceInfo field space 32
struct SyntheticResourceInfo field structSize 0
struct SyntheticResourceInfo field uniformOffset 40
struct SyntheticResourceInfo field uniformStride 44
struct SyntheticResourceInfo size 56
struct SyntheticResourceInfo size 64
struct TargetDesc field compilerOptionEntries 32
struct TargetDesc field compilerOptionEntryCount 40
struct TargetDesc field flags 16
Expand Down
Loading
Loading