Skip to content

Commit 2182eb5

Browse files
authored
Build with zig (google#431)
* 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 <[email protected]> * ci: add zig build workflow Signed-off-by: inge4pres <[email protected]> * build(zig): aarch64 macros on Linux * CI: split zig build by platform Signed-off-by: inge4pres <[email protected]> * CI: release script updates version in build.zig.zon Signed-off-by: inge4pres <[email protected]> --------- Signed-off-by: inge4pres <[email protected]>
1 parent d868036 commit 2182eb5

File tree

7 files changed

+322
-0
lines changed

7 files changed

+322
-0
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: aarch64 Linux Zig
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
run:
7+
strategy:
8+
matrix:
9+
target:
10+
- aarch64-linux-musl
11+
- aarch64-linux-gnu
12+
runs-on: ubuntu-24.04-arm
13+
steps:
14+
- uses: actions/checkout@v5
15+
- uses: mlugg/setup-zig@v2
16+
with:
17+
version: latest
18+
- name: Build
19+
run: zig build -Dtarget=${{ matrix.target }}
20+
- name: Run list_cpu_features
21+
run: ./zig-out/bin/list_cpu_features --json
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: amd64 Linux Zig
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
run:
7+
strategy:
8+
matrix:
9+
target:
10+
- x86_64-linux-musl
11+
- x86_64-linux-gnu
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v5
15+
- uses: mlugg/setup-zig@v2
16+
with:
17+
version: latest
18+
- name: Build
19+
run: zig build -Dtarget=${{ matrix.target }}
20+
- name: Run list_cpu_features
21+
run: ./zig-out/bin/list_cpu_features --json

.github/workflows/zig.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
name: Zig Check
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
zig-fmt:
7+
runs-on: ubuntu-latest
8+
steps:
9+
- uses: actions/checkout@v5
10+
- uses: mlugg/setup-zig@v2
11+
with:
12+
version: latest
13+
- run: zig fmt --check .

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,7 @@ MODULE.bazel.lock
1818

1919
# Per-user bazelrc files
2020
user.bazelrc
21+
22+
# Zig build artifacts
23+
.zig-cache
24+
zig-out

build.zig

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
const std = @import("std");
2+
3+
pub fn build(b: *std.Build) void {
4+
// Standard target and optimization options
5+
const target = b.standardTargetOptions(.{});
6+
const optimize = b.standardOptimizeOption(.{});
7+
8+
// Build options (mirroring CMake options)
9+
const build_executable = b.option(bool, "BUILD_EXECUTABLE", "Build list_cpu_features executable") orelse true;
10+
const enable_install = b.option(bool, "ENABLE_INSTALL", "Enable install targets") orelse true;
11+
12+
// Create the cpu_features static library
13+
const cpu_features = b.addLibrary(.{
14+
.name = "cpu_features",
15+
.linkage = .static,
16+
.root_module = b.createModule(.{
17+
.target = target,
18+
.optimize = optimize,
19+
.link_libc = true,
20+
}),
21+
});
22+
23+
cpu_features.addIncludePath(b.path("include"));
24+
cpu_features.addIncludePath(b.path("include/internal"));
25+
26+
// Public compile definitions
27+
cpu_features.root_module.addCMacro("STACK_LINE_READER_BUFFER_SIZE", "1024");
28+
29+
// Platform-specific defines
30+
const os_tag = target.result.os.tag;
31+
const cpu_arch = target.result.cpu.arch;
32+
33+
if (os_tag.isDarwin()) {
34+
cpu_features.root_module.addCMacro("HAVE_SYSCTLBYNAME", "1");
35+
} else if (os_tag == .linux) {
36+
// Linux (including musl) provides getauxval() for hardware capability detection
37+
cpu_features.root_module.addCMacro("HAVE_STRONG_GETAUXVAL", "1");
38+
cpu_features.root_module.addCMacro("HAVE_DLFCN_H", "1");
39+
}
40+
41+
// Utility sources (always included)
42+
const utility_sources = [_][]const u8{
43+
"src/filesystem.c",
44+
"src/stack_line_reader.c",
45+
"src/string_view.c",
46+
};
47+
48+
// Common C flags for all source files
49+
const c_flags = [_][]const u8{
50+
"-Wall",
51+
"-Wextra",
52+
"-Wmissing-declarations",
53+
"-Wmissing-prototypes",
54+
"-Wno-implicit-fallthrough",
55+
"-Wno-unused-function",
56+
"-Wold-style-definition",
57+
"-Wshadow",
58+
"-Wsign-compare",
59+
"-Wstrict-prototypes",
60+
"-std=c99",
61+
"-fno-sanitize=undefined", // Disable UBSan for C code with intentional unaligned access
62+
};
63+
64+
for (utility_sources) |source| {
65+
cpu_features.addCSourceFile(.{
66+
.file = b.path(source),
67+
.flags = &c_flags,
68+
});
69+
}
70+
71+
// Unix-based hardware detection (for non-x86 Unix platforms)
72+
// Note: Android is represented as Linux in Zig's target system
73+
if (os_tag != .windows and !cpu_arch.isX86()) {
74+
const hwcaps_sources = [_][]const u8{
75+
"src/hwcaps.c",
76+
"src/hwcaps_linux_or_android.c",
77+
"src/hwcaps_freebsd_or_openbsd.c",
78+
};
79+
80+
for (hwcaps_sources) |source| {
81+
cpu_features.addCSourceFile(.{
82+
.file = b.path(source),
83+
.flags = &c_flags,
84+
});
85+
}
86+
}
87+
88+
// Architecture-specific implementation files
89+
// Determine which implementation files to include based on target architecture
90+
// Note: Android is represented as Linux in Zig's target system
91+
switch (cpu_arch) {
92+
.x86, .x86_64 => {
93+
// x86/x86_64 architecture
94+
const source: ?[]const u8 = if (os_tag == .linux)
95+
"src/impl_x86_linux_or_android.c"
96+
else if (os_tag.isDarwin())
97+
"src/impl_x86_macos.c"
98+
else if (os_tag == .windows)
99+
"src/impl_x86_windows.c"
100+
else if (os_tag == .freebsd)
101+
"src/impl_x86_freebsd.c"
102+
else
103+
null;
104+
105+
if (source) |s| {
106+
cpu_features.addCSourceFile(.{
107+
.file = b.path(s),
108+
.flags = &c_flags,
109+
});
110+
}
111+
},
112+
.aarch64, .aarch64_be => {
113+
// AArch64 architecture - always needs cpuid
114+
cpu_features.addCSourceFile(.{
115+
.file = b.path("src/impl_aarch64_cpuid.c"),
116+
.flags = &c_flags,
117+
});
118+
119+
const source: ?[]const u8 = if (os_tag == .linux)
120+
"src/impl_aarch64_linux_or_android.c"
121+
else if (os_tag.isDarwin())
122+
"src/impl_aarch64_macos_or_iphone.c"
123+
else if (os_tag == .windows)
124+
"src/impl_aarch64_windows.c"
125+
else if (os_tag == .freebsd or os_tag == .openbsd)
126+
"src/impl_aarch64_freebsd_or_openbsd.c"
127+
else
128+
null;
129+
130+
if (source) |s| {
131+
cpu_features.addCSourceFile(.{
132+
.file = b.path(s),
133+
.flags = &c_flags,
134+
});
135+
}
136+
},
137+
.arm, .armeb, .thumb, .thumbeb => {
138+
// ARM (32-bit) architecture
139+
if (os_tag == .linux) {
140+
cpu_features.addCSourceFile(.{
141+
.file = b.path("src/impl_arm_linux_or_android.c"),
142+
.flags = &c_flags,
143+
});
144+
}
145+
},
146+
.mips, .mipsel, .mips64, .mips64el => {
147+
// MIPS architecture
148+
if (os_tag == .linux) {
149+
cpu_features.addCSourceFile(.{
150+
.file = b.path("src/impl_mips_linux_or_android.c"),
151+
.flags = &c_flags,
152+
});
153+
}
154+
},
155+
.powerpc, .powerpcle, .powerpc64, .powerpc64le => {
156+
// PowerPC architecture
157+
if (os_tag == .linux) {
158+
cpu_features.addCSourceFile(.{
159+
.file = b.path("src/impl_ppc_linux.c"),
160+
.flags = &c_flags,
161+
});
162+
}
163+
},
164+
.riscv32, .riscv64 => {
165+
// RISC-V architecture
166+
if (os_tag == .linux) {
167+
cpu_features.addCSourceFile(.{
168+
.file = b.path("src/impl_riscv_linux.c"),
169+
.flags = &c_flags,
170+
});
171+
}
172+
},
173+
.s390x => {
174+
// s390x architecture
175+
if (os_tag == .linux) {
176+
cpu_features.addCSourceFile(.{
177+
.file = b.path("src/impl_s390x_linux.c"),
178+
.flags = &c_flags,
179+
});
180+
}
181+
},
182+
.loongarch64 => {
183+
// LoongArch architecture
184+
if (os_tag == .linux) {
185+
cpu_features.addCSourceFile(.{
186+
.file = b.path("src/impl_loongarch_linux.c"),
187+
.flags = &c_flags,
188+
});
189+
}
190+
},
191+
else => {
192+
std.debug.print("Warning: Unsupported architecture {s}\n", .{@tagName(cpu_arch)});
193+
},
194+
}
195+
196+
// Link against dl library on Unix-like systems
197+
if (os_tag != .windows and os_tag != .wasi) {
198+
cpu_features.linkSystemLibrary("dl");
199+
}
200+
201+
// Install the library if enabled
202+
if (enable_install) {
203+
b.installArtifact(cpu_features);
204+
205+
// Install headers
206+
const install_headers = b.addInstallDirectory(.{
207+
.source_dir = b.path("include"),
208+
.install_dir = .header,
209+
.install_subdir = "cpu_features",
210+
.exclude_extensions = &.{},
211+
});
212+
b.getInstallStep().dependOn(&install_headers.step);
213+
}
214+
215+
// Build list_cpu_features executable if requested
216+
if (build_executable) {
217+
const list_cpu_features = b.addExecutable(.{
218+
.name = "list_cpu_features",
219+
.root_module = b.createModule(.{
220+
.target = target,
221+
.optimize = optimize,
222+
.link_libc = true,
223+
}),
224+
});
225+
226+
list_cpu_features.linkLibrary(cpu_features);
227+
list_cpu_features.addIncludePath(b.path("include"));
228+
229+
list_cpu_features.addCSourceFile(.{
230+
.file = b.path("src/utils/list_cpu_features.c"),
231+
.flags = &c_flags,
232+
});
233+
234+
if (enable_install) {
235+
b.installArtifact(list_cpu_features);
236+
}
237+
238+
// Add a run step for convenience
239+
const run_cmd = b.addRunArtifact(list_cpu_features);
240+
run_cmd.step.dependOn(b.getInstallStep());
241+
if (b.args) |args| {
242+
run_cmd.addArgs(args);
243+
}
244+
245+
const run_step = b.step("run", "Run list_cpu_features");
246+
run_step.dependOn(&run_cmd.step);
247+
}
248+
}

build.zig.zon

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
.{
2+
.name = .cpu_features,
3+
.version = "0.0.1",
4+
.minimum_zig_version = "0.15.1",
5+
.paths = .{
6+
"build.zig",
7+
"build.zig.zon",
8+
"src",
9+
"include",
10+
},
11+
.fingerprint = 0xbd52e965d3c20004,
12+
}

scripts/make_release.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ sed -i "s/CpuFeatures VERSION ${LATEST_VERSION}/CpuFeatures VERSION ${VERSION}/g
6565
echo -e "${ACTION}Modifying MODULE.bazel${NOCOLOR}"
6666
sed -i "s/CPU_FEATURES_VERSION = \"${LATEST_VERSION}\"/CPU_FEATURES_VERSION = \"${VERSION}\"/g" MODULE.bazel
6767

68+
echo -e "${ACTION}Modifying build.zig.zon${NOCOLOR}"
69+
sed -i "s/.version = \"${LATEST_VERSION}\"/.version = \"${VERSION}\"/g" build.zig.zon
70+
6871
echo -e "${ACTION}Commit new revision${NOCOLOR}"
6972
git add CMakeLists.txt MODULE.bazel
7073
git commit -m"Release ${GIT_TAG}"

0 commit comments

Comments
 (0)