Selemba1000/gradle-zig
A Gradle plugin fo seamless integration of the Zig build system into your Java/Kotlin projects.
A Gradle plugin for seamless integration of the Zig build system into your Java/Kotlin projects.
This plugin allows you to compile Zig code into native libraries or executables as part of your regular Gradle build, making it easy to work with native code via JNI/JNA.
JavaPlugin source sets (main, test, etc.).linux-x86_64, windows-x86_64, macos-aarch64) and build for all of them.src/main/zig) and build outputs.build.zig Powered: Leverages the power and flexibility of Zig's own build system.Follow these instructions to integrate the Gradle Zig plugin into your project.
PATH. You can find installation instructions at ziglang.org/download. The current version in tests and documentation is 0.15.2.java or kotlin("jvm") plugins.Apply the plugin to your build.gradle.kts file.
// build.gradle.kts
plugins {
kotlin("jvm") version "2.1.20" // or `java`
id("io.github.selemba1000.gradle-zig") version "[PLUGIN_VERSION]"
}
Replace [PLUGIN_VERSION] with the latest version from the Gradle Plugin Portal.
Once the plugin is applied, it adds a zig extension to each source set defined by the JavaPlugin.
Create a build.zig file in your Zig source directory (e.g., src/main/zig/build.zig). This file defines how your Zig code is compiled. For cross-compilation and optimization options to work out of the box, the build.zig file needs to handle the default options via standardTargetOptions and standardOptimizeOptions. A minimal build.zig file that builds a shared library named foo looks like this:
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const lib = b.addLibrary(.{
.name = "foo",
.linkage = .dynamic,
.root_module = b.createModule(.{
.root_source_file = b.path("foo.zig"),
.target = target,
.optimize = optimize,
})
});
if(target.result.cpu.arch == .x86){
lib.link_z_notext = true;
}
// Install the library, disabling specific outputs for better JVM compatibility
const lib_output = b.addInstallArtifact(lib, .{
.implib_dir = .disabled,
.dest_dir = .{ .override = .lib },
.pdb_dir = .disabled
});
b.getInstallStep().dependOn(&lib_output.step);
}
lib.link_z_notext = true; option is often required for proper linking.implib and pdb generation and reroute the shared library file to the lib folder. This is a common workaround for JVM compatibility with native Windows libraries.Configure the zig block within a source set in your build.gradle.kts.
// build.gradle.kts
sourceSets {
main {
zig {
// Configuration goes here
}
}
}
By default, the plugin will create a default target and a default-library artifact. This is useful for simple projects that only need to build a single native library for the host machine.
You can specify which platforms and architectures to build for using the targets block. The plugin provides convenient helpers for common OS/architecture combinations.
// build.gradle.kts
import io.github.selemba1000.definitions.ZigTargetTriple // import if not already present
sourceSets.main.zig {
targets {
// Add targets for Linux, Windows, and macOS
linux(x86_64 = true, arm64 = true)
windows(x86_64 = true)
macos(arm64 = true)
// Or create a custom target
create("wasm-freestanding") {
setTargetTriple(ZigTargetTriple("wasm32-freestanding-musl", "wasm32"))
setTargetOptimize(ZigOptimization.ReleaseSmall)
}
}
}
The zigArtifacts block tells the plugin what to do with the compiled output from build.zig. You can define libraries or executables.
// build.gradle.kts
sourceSets.main.zig {
zigArtifacts {
// Copies the compiled library (e.g., libmy_lib.so, my_lib.dll)
// into the build resources.
library("my_lib")
// Copies the compiled executable into the build resources under a 'bin' directory.
executable("my_app")
}
}
The plugin allows you to pass additional flags to the zig build command in two ways:
Target-Independent Flags (additionalFlags)
These flags are passed to the zig build command regardless of the specific target or optimization level being compiled. They are set per source set:
// build.gradle.kts
sourceSets.main.zig {
additionalFlags.add("-Doption=value")
}
Target-Specific Flags (addTargetCompilerFlag, setTargetOptimize, setTargetTriple)
These flags are applied on a per-target basis, allowing you to customize compilation for different platforms or architectures. The plugin provides dedicated methods for common target-specific options, and a generic method for any custom flag:
// build.gradle.kts
sourceSets.main.zig{
// The first argument is the name of the parameter, the second the template.
// The semicolon in the template will be replaced by the specific value.
flagsTemplate.put("yourOption", "-DyourOption=;")
// Changing the flags template requires you to also add the default options, if you want to retain that functionality
flagsTemplate.put("target", "-Dtarget=;")
flagsTemplate.put("optimize", "-Doptimize=;")
}
Then a value for the parameter can be supplied for every target:
// build.gradle.kts
sourceSets.main.zig{
targets{
named("linux-x68_64"){
addTargetCompilerFlag("yourOption", "value")
}
}
}
Here is a complete build.gradle.kts example that compiles a native library named my_lib for 64-bit Linux and Windows.
// build.gradle.kts
import io.github.selemba1000.definitions.ZigOptimization
plugins {
kotlin("jvm") version "2.1.20"
application
id("io.github.selemba1000.gradle-zig") version "0.1.0" // Use the latest version
}
repositories {
mavenCentral()
}
dependencies {
// JNA is great for calling native functions from the JVM
implementation("net.java.dev.jna:jna:5.13.0")
}
sourceSets {
main {
zig {
// Define which targets to build for
targets {
linux(x86_64 = true)
windows(x86_64 = true)
}
// Define which artifacts to extract from the build output
zigArtifacts {
library("my_lib")
}
// Pass additional flags to the `zig build` command
additionalFlags.add("-Doption=value")
}
}
}
Now, when you run ./gradlew build, the plugin will:
zig build for each specified target.my_lib shared library from the Zig build output into build/resources/main/.Contributions are welcome! If you'd like to contribute, please feel free to fork the repository and submit a pull request.
git checkout -b feature/AmazingFeature).git commit -m 'Add some AmazingFeature').git push origin feature/AmazingFeature).This project is licensed under the MIT License - see the LICENSE file for details.