Skip to content
Open
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
51 changes: 51 additions & 0 deletions .github/workflows/zig.yml
Copy link
Collaborator

@Mizux Mizux Oct 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would split this in 3 files;

  • zig.yml following the clang_format.yml Check but for Zig Check

Currently seems we have two CI workflows:

  • amd64_linux_zig.yml
  • aarch64_linux_zig.yml
    note: ubuntu-20.04-arm64 are thid party runner maybe using a regular ubuntu-latest+QEMU to cross compile et run should be more robust against the gh runner infra

Maybe to extend to Macos (brew?) and windows too later ?

thus, adding Zig to BuildSystem and a svg logo (e.g. https://github.com/ziglang/logo/blob/master/zig-mark.svg) and we should be able to generate badges too to update the README.md CI table...
ref: https://github.com/google/cpu_features/blob/main/scripts/generate_badges.d

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, and love the idea!
I'll get to it

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Zig build

on:
pull_request:
branches: [ main ]

env:
ZIG_VERSION: 0.15.1

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: mlugg/setup-zig@v2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why specifying the version and a mirror ?
For a CI I would be happy to target the default/last release pointed by the actions than fixing it a lagging behind in few months...
same for mirror not sure it is needed according to the doc in
https://github.com/mlugg/setup-zig/blob/8d6198c65fb0feaa111df26e6b467fea8345e46f/README.md?plain=1#L45-L48

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question:

a. the version can be set to latest to get the most recent release version (i'll do that)
b. the mirror: we are using a community mirror hosted by me instead of the ziglang.org website for reliability - i am fine removing it, I admit it was copy-pasted from another project of mine. There is a chance CI will fail if the ziglang.org website is down

with:
version: ${{ env.ZIG_VERSION }}
mirror: 'https://zigmirror.com'
- run: zig fmt --check .

build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: mlugg/setup-zig@v2
with:
version: ${{ env.ZIG_VERSION }}
mirror: 'https://zigmirror.com'
- run: zig build

run:
strategy:
matrix:
include:
- os: ubuntu-latest
target: x86_64-linux-musl
- os: ubuntu-latest
target: x86_64-linux-gnu
- os: ubuntu-24.04-arm64
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I am actually going to implement your suggestion here

note: ubuntu-20.04-arm64 are thid party runner maybe using a regular ubuntu-latest+QEMU to cross compile et run should be more robust against the gh runner infra

and use QEMU, if that's ok with you

target: aarch64-linux-musl
- os: ubuntu-24.04-arm64
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ubuntu-24.04-arm

target: aarch64-linux-gnu
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v5
- uses: mlugg/setup-zig@v2
with:
version: ${{ env.ZIG_VERSION }}
mirror: 'https://zigmirror.com'
- name: Run list_cpu_features
run: zig build run -Dtarget=${{ matrix.target }} -- --json
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ MODULE.bazel.lock

# Per-user bazelrc files
user.bazelrc

# Zig build artifacts
.zig-cache
zig-out
244 changes: 244 additions & 0 deletions build.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
const std = @import("std");

pub fn build(b: *std.Build) void {
// Standard target and optimization options
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});

// Build options (mirroring CMake options)
const build_executable = b.option(bool, "BUILD_EXECUTABLE", "Build list_cpu_features executable") orelse true;
const enable_install = b.option(bool, "ENABLE_INSTALL", "Enable install targets") orelse true;

// Create the cpu_features static library
const cpu_features = b.addLibrary(.{
.name = "cpu_features",
.linkage = .static,
.root_module = b.createModule(.{
.target = target,
.optimize = optimize,
.link_libc = true,
}),
});

cpu_features.addIncludePath(b.path("include"));
cpu_features.addIncludePath(b.path("include/internal"));

// Public compile definitions
cpu_features.root_module.addCMacro("STACK_LINE_READER_BUFFER_SIZE", "1024");

// Platform-specific defines
const os_tag = target.result.os.tag;
const cpu_arch = target.result.cpu.arch;

if (os_tag.isDarwin()) {
cpu_features.root_module.addCMacro("HAVE_SYSCTLBYNAME", "1");
}

// Utility sources (always included)
const utility_sources = [_][]const u8{
"src/filesystem.c",
"src/stack_line_reader.c",
"src/string_view.c",
};

// Common C flags for all source files
const c_flags = [_][]const u8{
"-Wall",
"-Wextra",
"-Wmissing-declarations",
"-Wmissing-prototypes",
"-Wno-implicit-fallthrough",
"-Wno-unused-function",
"-Wold-style-definition",
"-Wshadow",
"-Wsign-compare",
"-Wstrict-prototypes",
"-std=c99",
"-fno-sanitize=undefined", // Disable UBSan for C code with intentional unaligned access
};

for (utility_sources) |source| {
cpu_features.addCSourceFile(.{
.file = b.path(source),
.flags = &c_flags,
});
}

// Unix-based hardware detection (for non-x86 Unix platforms)
// Note: Android is represented as Linux in Zig's target system
if (os_tag != .windows and !cpu_arch.isX86()) {
const hwcaps_sources = [_][]const u8{
"src/hwcaps.c",
"src/hwcaps_linux_or_android.c",
"src/hwcaps_freebsd_or_openbsd.c",
};

for (hwcaps_sources) |source| {
cpu_features.addCSourceFile(.{
.file = b.path(source),
.flags = &c_flags,
});
}
}

// Architecture-specific implementation files
// Determine which implementation files to include based on target architecture
// Note: Android is represented as Linux in Zig's target system
switch (cpu_arch) {
.x86, .x86_64 => {
// x86/x86_64 architecture
const source: ?[]const u8 = if (os_tag == .linux)
"src/impl_x86_linux_or_android.c"
else if (os_tag.isDarwin())
"src/impl_x86_macos.c"
else if (os_tag == .windows)
"src/impl_x86_windows.c"
else if (os_tag == .freebsd)
"src/impl_x86_freebsd.c"
else
null;

if (source) |s| {
cpu_features.addCSourceFile(.{
.file = b.path(s),
.flags = &c_flags,
});
}
},
.aarch64, .aarch64_be => {
// AArch64 architecture - always needs cpuid
cpu_features.addCSourceFile(.{
.file = b.path("src/impl_aarch64_cpuid.c"),
.flags = &c_flags,
});

const source: ?[]const u8 = if (os_tag == .linux)
"src/impl_aarch64_linux_or_android.c"
else if (os_tag.isDarwin())
"src/impl_aarch64_macos_or_iphone.c"
else if (os_tag == .windows)
"src/impl_aarch64_windows.c"
else if (os_tag == .freebsd or os_tag == .openbsd)
"src/impl_aarch64_freebsd_or_openbsd.c"
else
null;

if (source) |s| {
cpu_features.addCSourceFile(.{
.file = b.path(s),
.flags = &c_flags,
});
}
},
.arm, .armeb, .thumb, .thumbeb => {
// ARM (32-bit) architecture
if (os_tag == .linux) {
cpu_features.addCSourceFile(.{
.file = b.path("src/impl_arm_linux_or_android.c"),
.flags = &c_flags,
});
}
},
.mips, .mipsel, .mips64, .mips64el => {
// MIPS architecture
if (os_tag == .linux) {
cpu_features.addCSourceFile(.{
.file = b.path("src/impl_mips_linux_or_android.c"),
.flags = &c_flags,
});
}
},
.powerpc, .powerpcle, .powerpc64, .powerpc64le => {
// PowerPC architecture
if (os_tag == .linux) {
cpu_features.addCSourceFile(.{
.file = b.path("src/impl_ppc_linux.c"),
.flags = &c_flags,
});
}
},
.riscv32, .riscv64 => {
// RISC-V architecture
if (os_tag == .linux) {
cpu_features.addCSourceFile(.{
.file = b.path("src/impl_riscv_linux.c"),
.flags = &c_flags,
});
}
},
.s390x => {
// s390x architecture
if (os_tag == .linux) {
cpu_features.addCSourceFile(.{
.file = b.path("src/impl_s390x_linux.c"),
.flags = &c_flags,
});
}
},
.loongarch64 => {
// LoongArch architecture
if (os_tag == .linux) {
cpu_features.addCSourceFile(.{
.file = b.path("src/impl_loongarch_linux.c"),
.flags = &c_flags,
});
}
},
else => {
std.debug.print("Warning: Unsupported architecture {s}\n", .{@tagName(cpu_arch)});
},
}

// Link against dl library on Unix-like systems
if (os_tag != .windows and os_tag != .wasi) {
cpu_features.linkSystemLibrary("dl");
}

// Install the library if enabled
if (enable_install) {
b.installArtifact(cpu_features);

// Install headers
const install_headers = b.addInstallDirectory(.{
.source_dir = b.path("include"),
.install_dir = .header,
.install_subdir = "cpu_features",
.exclude_extensions = &.{},
});
b.getInstallStep().dependOn(&install_headers.step);
}

// Build list_cpu_features executable if requested
if (build_executable) {
const list_cpu_features = b.addExecutable(.{
.name = "list_cpu_features",
.root_module = b.createModule(.{
.target = target,
.optimize = optimize,
.link_libc = true,
}),
});

list_cpu_features.linkLibrary(cpu_features);
list_cpu_features.addIncludePath(b.path("include"));

list_cpu_features.addCSourceFile(.{
.file = b.path("src/utils/list_cpu_features.c"),
.flags = &c_flags,
});

if (enable_install) {
b.installArtifact(list_cpu_features);
}

// Add a run step for convenience
const run_cmd = b.addRunArtifact(list_cpu_features);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
}

const run_step = b.step("run", "Run list_cpu_features");
run_step.dependOn(&run_cmd.step);
}
}
12 changes: 12 additions & 0 deletions build.zig.zon
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.{
.name = .cpu_features,
.version = "0.0.1",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not using the cpu version instead ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not using the cpu version instead ?

Do you mean using the same version as released for the other artifacts in the repo?
SGTM, and we should also update that version on a release?

.minimum_zig_version = "0.15.1",
.paths = .{
"build.zig",
"build.zig.zon",
"src",
"include",
},
.fingerprint = 0xbd52e965d3c20004,
}
Loading