From 5eded15bca949e515cdc6381ef45b8200b8d16ad Mon Sep 17 00:00:00 2001 From: inge4pres Date: Wed, 8 Oct 2025 23:45:20 +0200 Subject: [PATCH 1/5] build with Zig Add the necessary files to build a static library with Zig. The build also includes producing execuable that can be cross-compiled Signed-off-by: inge4pres --- .gitignore | 4 + build.zig | 244 ++++++++++++++++++++++++++++++++++++++++++++++++++ build.zig.zon | 12 +++ 3 files changed, 260 insertions(+) create mode 100644 build.zig create mode 100644 build.zig.zon diff --git a/.gitignore b/.gitignore index c4ee9c80..f7f06b97 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,7 @@ MODULE.bazel.lock # Per-user bazelrc files user.bazelrc + +# Zig build artifacts +.zig-cache +zig-out diff --git a/build.zig b/build.zig new file mode 100644 index 00000000..880f6995 --- /dev/null +++ b/build.zig @@ -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); + } +} diff --git a/build.zig.zon b/build.zig.zon new file mode 100644 index 00000000..d54afba5 --- /dev/null +++ b/build.zig.zon @@ -0,0 +1,12 @@ +.{ + .name = .cpu_features, + .version = "0.0.1", + .minimum_zig_version = "0.15.1", + .paths = .{ + "build.zig", + "build.zig.zon", + "src", + "include", + }, + .fingerprint = 0xbd52e965d3c20004, +} From 50676c2a10123c29c4d4a4df4216ceedb63af4f3 Mon Sep 17 00:00:00 2001 From: inge4pres Date: Thu, 9 Oct 2025 00:09:09 +0200 Subject: [PATCH 2/5] ci: add zig build workflow Signed-off-by: inge4pres --- .github/workflows/zig.yml | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 .github/workflows/zig.yml diff --git a/.github/workflows/zig.yml b/.github/workflows/zig.yml new file mode 100644 index 00000000..d5117ef4 --- /dev/null +++ b/.github/workflows/zig.yml @@ -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 + 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 + target: aarch64-linux-musl + - os: ubuntu-24.04-arm64 + 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 From 595be4e2179acac9c3860fcc56a0bcd333a0529f Mon Sep 17 00:00:00 2001 From: inge4pres Date: Mon, 13 Oct 2025 10:30:31 +0200 Subject: [PATCH 3/5] build(zig): aarch64 macros on Linux --- build.zig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.zig b/build.zig index 880f6995..7ff7d799 100644 --- a/build.zig +++ b/build.zig @@ -32,6 +32,10 @@ pub fn build(b: *std.Build) void { if (os_tag.isDarwin()) { cpu_features.root_module.addCMacro("HAVE_SYSCTLBYNAME", "1"); + } else if (os_tag == .linux) { + // Linux (including musl) provides getauxval() for hardware capability detection + cpu_features.root_module.addCMacro("HAVE_STRONG_GETAUXVAL", "1"); + cpu_features.root_module.addCMacro("HAVE_DLFCN_H", "1"); } // Utility sources (always included) From d79830b223cb5fd3d5f49e0c09d34d9f1e714157 Mon Sep 17 00:00:00 2001 From: inge4pres Date: Mon, 13 Oct 2025 16:35:05 +0200 Subject: [PATCH 4/5] CI: split zig build by platform Signed-off-by: inge4pres --- .github/workflows/aarch64_linux_zig.yml | 21 +++++++++++ .github/workflows/amd64_linux_zig.yml | 21 +++++++++++ .github/workflows/zig.yml | 46 +++---------------------- 3 files changed, 46 insertions(+), 42 deletions(-) create mode 100644 .github/workflows/aarch64_linux_zig.yml create mode 100644 .github/workflows/amd64_linux_zig.yml diff --git a/.github/workflows/aarch64_linux_zig.yml b/.github/workflows/aarch64_linux_zig.yml new file mode 100644 index 00000000..522875a2 --- /dev/null +++ b/.github/workflows/aarch64_linux_zig.yml @@ -0,0 +1,21 @@ +name: aarch64 Linux Zig + +on: [push, pull_request] + +jobs: + run: + strategy: + matrix: + target: + - aarch64-linux-musl + - aarch64-linux-gnu + runs-on: ubuntu-24.04-arm + steps: + - uses: actions/checkout@v5 + - uses: mlugg/setup-zig@v2 + with: + version: latest + - name: Build + run: zig build -Dtarget=${{ matrix.target }} + - name: Run list_cpu_features + run: ./zig-out/bin/list_cpu_features --json diff --git a/.github/workflows/amd64_linux_zig.yml b/.github/workflows/amd64_linux_zig.yml new file mode 100644 index 00000000..d23da309 --- /dev/null +++ b/.github/workflows/amd64_linux_zig.yml @@ -0,0 +1,21 @@ +name: amd64 Linux Zig + +on: [push, pull_request] + +jobs: + run: + strategy: + matrix: + target: + - x86_64-linux-musl + - x86_64-linux-gnu + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - uses: mlugg/setup-zig@v2 + with: + version: latest + - name: Build + run: zig build -Dtarget=${{ matrix.target }} + - name: Run list_cpu_features + run: ./zig-out/bin/list_cpu_features --json diff --git a/.github/workflows/zig.yml b/.github/workflows/zig.yml index d5117ef4..777ffbac 100644 --- a/.github/workflows/zig.yml +++ b/.github/workflows/zig.yml @@ -1,51 +1,13 @@ -name: Zig build +name: Zig Check -on: - pull_request: - branches: [ main ] - -env: - ZIG_VERSION: 0.15.1 +on: [push, pull_request] jobs: - lint: + zig-fmt: runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - uses: mlugg/setup-zig@v2 with: - version: ${{ env.ZIG_VERSION }} - mirror: 'https://zigmirror.com' + version: latest - 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 - target: aarch64-linux-musl - - os: ubuntu-24.04-arm64 - 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 From 14af8d0b689631eb311600a9af50c9728f62176d Mon Sep 17 00:00:00 2001 From: inge4pres Date: Mon, 13 Oct 2025 17:57:17 +0200 Subject: [PATCH 5/5] CI: release script updates version in build.zig.zon Signed-off-by: inge4pres --- scripts/make_release.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/make_release.sh b/scripts/make_release.sh index 2e11a443..d15adfcd 100755 --- a/scripts/make_release.sh +++ b/scripts/make_release.sh @@ -65,6 +65,9 @@ sed -i "s/CpuFeatures VERSION ${LATEST_VERSION}/CpuFeatures VERSION ${VERSION}/g echo -e "${ACTION}Modifying MODULE.bazel${NOCOLOR}" sed -i "s/CPU_FEATURES_VERSION = \"${LATEST_VERSION}\"/CPU_FEATURES_VERSION = \"${VERSION}\"/g" MODULE.bazel +echo -e "${ACTION}Modifying build.zig.zon${NOCOLOR}" +sed -i "s/.version = \"${LATEST_VERSION}\"/.version = \"${VERSION}\"/g" build.zig.zon + echo -e "${ACTION}Commit new revision${NOCOLOR}" git add CMakeLists.txt MODULE.bazel git commit -m"Release ${GIT_TAG}"