From b82d2c3fe03a827b885f6346493d165e01180451 Mon Sep 17 00:00:00 2001 From: Matt Knight Date: Tue, 21 May 2024 15:38:56 -0700 Subject: [PATCH] update to zig 0.12.0 (#2) * update to zig 0.12.0 * include build.zig.zon * fix typo * fix build invocation * update to 0.12.0 * don't test avr * fix path * fix build * link foundation * no gcc for now, doesn't work with mingw? --- .github/workflows/build.yml | 6 +- build.zig | 263 ++------------------- build.zig.zon | 11 + src/libc.zig | 2 +- test/build.zig | 222 +++++++++++++++++ test/build.zig.zon | 12 + {tests => test/src}/assert-validator.c | 0 {tests => test/src}/syntactic-validation.c | 0 8 files changed, 265 insertions(+), 251 deletions(-) create mode 100644 build.zig.zon create mode 100644 test/build.zig create mode 100644 test/build.zig.zon rename {tests => test/src}/assert-validator.c (100%) rename {tests => test/src}/syntactic-validation.c (100%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f48db1c..1490869 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,7 +11,6 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - single_thread: [true, false] runs-on: ${{ matrix.os }} steps: @@ -21,8 +20,9 @@ jobs: - name: Setup Zig uses: goto-bus-stop/setup-zig@v2 with: - version: 0.11.0 + version: 0.12.0 - name: Generate and validate packages + working-directory: test run: | - zig build -Dsingle-threaded=${{ matrix.single_thread }} + zig build validate diff --git a/build.zig b/build.zig index f73f285..aabe36f 100644 --- a/build.zig +++ b/build.zig @@ -1,144 +1,36 @@ const std = @import("std"); -pub const include_path = std.Build.LazyPath{ - .cwd_relative = sdk_root ++ "/include", -}; - -/// Creates a new instance of the libc target. -pub fn createLibrary(b: *std.Build, target: std.zig.CrossTarget, optimize: std.builtin.OptimizeMode) *std.Build.Step.Compile { - const libc = b.addStaticLibrary(.{ - .name = "foundation", - .target = target, - .optimize = optimize, - .root_source_file = .{ .path = "src/libc.zig" }, - }); - - libc.addIncludePath(.{ .path = "include" }); - for (header_files) |header_name| - libc.installHeader( - b.fmt("include/{s}", .{header_name}), - header_name, - ); - - return libc; -} - pub fn build(b: *std.Build) void { const validation_step = b.step("validate", "Runs the test suite and validates everything. Automatically triggered in Debug builds."); const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); - const single_threaded = b.option(bool, "single-threaded", "Create a single-threaded libc implementation (default: false)") orelse false; + const single_threaded = b.option(bool, "single_threaded", "Create a single-threaded libc implementation (default: false)") orelse false; // Run validation in debug builds for convenience: if (optimize == .Debug) { b.getInstallStep().dependOn(validation_step); } - // check if the host has a gcc or clang available: - const maybe_gcc = b.findProgram(&.{"gcc"}, &.{}) catch null; - const maybe_clang = b.findProgram(&.{"clang"}, &.{}) catch null; - - const libc = createLibrary(b, target, optimize); - libc.single_threaded = single_threaded; - b.installArtifact(libc); - - // test suite: - { - // Compile for huge amount of targets to detect breakage early on: - for ([_]bool{ false, true }) |validation_single_threaded| { - for (std.enums.values(std.builtin.OptimizeMode)) |validation_optimize| { - for (validation_target_list) |validation_target| { - - // skip everything that cannot support multithreading on freestanding: - if (!validation_single_threaded and !target_can_multithread(validation_target)) - continue; - - const vlc = createLibrary(b, validation_target, validation_optimize); - vlc.single_threaded = validation_single_threaded; - validation_step.dependOn(&vlc.step); - } - } - } - - const syntax_validator_source: std.Build.LazyPath = .{ .path = "tests/syntactic-validation.c" }; - - // use the shipped C compiler to validate our code: - { - // Check if the syntax of all of our header files is valid: - const syntax_validator = b.addStaticLibrary(.{ - .name = "syntax-validator", - .target = .{}, // just build for the host - .optimize = .Debug, - }); - syntax_validator.addCSourceFile(.{ - .file = syntax_validator_source, - .flags = &common_c_flags, - }); - syntax_validator.addIncludePath(include_path); - _ = syntax_validator.getEmittedBin(); - - // Just compile, do not install: - validation_step.dependOn(&syntax_validator.step); - } - - // use the host C compilers to validate our code: - for ([_]?[]const u8{ maybe_gcc, maybe_clang }) |maybe_cc| { - const cc = maybe_cc orelse continue; - - const ext_compiler = b.addSystemCommand(&.{cc}); - - // just compile every time, we don't have dir caching - // so changes on the headers wouldn't re-trigger this - ext_compiler.has_side_effects = true; - - ext_compiler.addPrefixedDirectoryArg("-I", include_path); - - ext_compiler.addArg("-c"); // compile only - ext_compiler.addArg("-O0"); // no optimization for fast compiles - ext_compiler.addArg("-ffreestanding"); // we require freestanding environment - ext_compiler.addArg("-nostdlib"); // do not try to link anything useful - - // turn on warnings - ext_compiler.addArg("-Werror"); - ext_compiler.addArg("-Wall"); - ext_compiler.addArg("-Wextra"); - - ext_compiler.addFileArg(syntax_validator_source); - - ext_compiler.addArg("-o"); - ext_compiler.addArg(b.pathJoin(&.{ b.makeTempPath(), "dummy" })); // we don't really care where this ends up - - validation_step.dependOn(&ext_compiler.step); - } + const libc = b.addStaticLibrary(.{ + .name = "foundation", + .target = target, + .optimize = optimize, + .root_source_file = b.path("src/libc.zig"), + .single_threaded = single_threaded, + }); - // Validate all modes of assertion: - for ([_][]const u8{ - "FOUNDATION_LIBC_ASSERT_DEFAULT", - "FOUNDATION_LIBC_ASSERT_NOFILE", - "FOUNDATION_LIBC_ASSERT_NOMSG", - "FOUNDATION_LIBC_ASSERT_EXPECTED", - }) |assert_mode| { - // Check if the syntax of all of our header files is valid: - const assert_validator = b.addStaticLibrary(.{ - .name = "assert-validator", - .target = .{}, // just build for the host - .optimize = .Debug, - }); - assert_validator.addCSourceFile(.{ - .file = .{ .path = "tests/assert-validator.c" }, - .flags = &common_c_flags, - }); - assert_validator.addIncludePath(include_path); - _ = assert_validator.getEmittedBin(); + libc.addIncludePath(b.path("include")); + for (header_files) |header_name| + libc.installHeader( + b.path(b.fmt("include/{s}", .{header_name})), + header_name, + ); - assert_validator.defineCMacro("FOUNDATION_LIBC_ASSERT", assert_mode); + libc.installHeadersDirectory(b.path("include/foundation"), "foundation", .{}); - // Just compile, do not install: - validation_step.dependOn(&assert_validator.step); - } - } + b.installArtifact(libc); } const header_files = [_][]const u8{ @@ -154,126 +46,3 @@ const header_files = [_][]const u8{ "uchar.h", "foundation/libc.h", }; - -const common_c_flags = [_][]const u8{ - "-std=c11", // target C standard - // - "-Werror", // we do not allow warnings - "-Wall", - "-Wextra", - "-Wmost", - "-Weverything", // this might be dropped later as we just want to find all potential warnings and enable/disable them as required. - // - "-Wno-reserved-macro-identifier", // we actually want to implement those! - "-Wno-reserved-identifier", // we actually want to implement those! -}; - -fn target_can_multithread(target: std.zig.CrossTarget) bool { - return switch (target.getCpuArch()) { - .wasm32, - .wasm64, - .msp430, - => false, - - else => true, - }; -} - -const validation_target_list = [_]std.zig.CrossTarget{ - .{}, // regular host platform - .{ .os_tag = .freestanding }, // host platform, but no OS - - // Check several common cpu targets: - - // arm: - .{ .cpu_arch = .arm, .os_tag = .freestanding }, - .{ .cpu_arch = .armeb, .os_tag = .freestanding }, - .{ .cpu_arch = .thumb, .os_tag = .freestanding }, - .{ .cpu_arch = .thumbeb, .os_tag = .freestanding }, - .{ .cpu_arch = .aarch64, .os_tag = .freestanding }, - // .{ .cpu_arch = .aarch64_32, .os_tag = .freestanding }, // error: unknown target triple 'aarch64_32-unknown-unknown-eabi', please use -triple or -arch - .{ .cpu_arch = .aarch64_be, .os_tag = .freestanding }, - - // risc-v: - .{ .cpu_arch = .riscv32, .os_tag = .freestanding }, - .{ .cpu_arch = .riscv64, .os_tag = .freestanding }, - - // intel: - .{ .cpu_arch = .x86_64, .os_tag = .freestanding }, - .{ .cpu_arch = .x86, .os_tag = .freestanding }, - - // mips: - .{ .cpu_arch = .mips, .os_tag = .freestanding }, - .{ .cpu_arch = .mips64, .os_tag = .freestanding }, - .{ .cpu_arch = .mips64el, .os_tag = .freestanding }, - .{ .cpu_arch = .mipsel, .os_tag = .freestanding }, - - // sparc: - .{ .cpu_arch = .sparc, .os_tag = .freestanding }, - .{ .cpu_arch = .sparc64, .os_tag = .freestanding }, - .{ .cpu_arch = .sparcel, .os_tag = .freestanding }, - - // power: - .{ .cpu_arch = .powerpc, .os_tag = .freestanding }, - .{ .cpu_arch = .powerpc64, .os_tag = .freestanding }, - .{ .cpu_arch = .powerpc64le, .os_tag = .freestanding }, - .{ .cpu_arch = .powerpcle, .os_tag = .freestanding }, - - // web assembly: - .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, - .{ .cpu_arch = .wasm64, .os_tag = .freestanding }, - - // nice to have, but broken: - .{ .cpu_arch = .avr, .os_tag = .freestanding }, - // .{ .cpu_arch = .msp430, .os_tag = .freestanding }, // error: unknown target CPU 'generic' - // .{ .cpu_arch = .m68k, .os_tag = .freestanding }, - // .{ .cpu_arch = .xtensa, .os_tag = .freestanding }, - - // Not evaluated if reasonable to check: - // arc - // csky - // hexagon - // hsail - // hsail64 - // kalimba - // lanai - // le32 - // le64 - // loongarch32 - // loongarch64 - // r600 - // s390x - // shave - // spu_2 - // tce - // tcele - // ve - // xcore - - // will never be supported due to their properties: - // spir - // spir64 - // spirv32 - // spirv64 - - // bpfeb - // bpfel - - // renderscript32 - // renderscript64 - - // amdgcn - // amdil - // amdil64 - - // nvptx - // nvptx64 - - // dxil -}; - -const sdk_root = computeSdkRoot(); - -fn computeSdkRoot() []const u8 { - return std.fs.path.dirname(@src().file).?; -} diff --git a/build.zig.zon b/build.zig.zon new file mode 100644 index 0000000..db7ac7a --- /dev/null +++ b/build.zig.zon @@ -0,0 +1,11 @@ +.{ + .name = "foundation-libc", + .version = "0.0.0", + .paths = .{ + "LICENSE", + "README.md", + "build.zig", + "build.zig.zon", + "include", + }, +} diff --git a/src/libc.zig b/src/libc.zig index fc5c902..1133ff6 100644 --- a/src/libc.zig +++ b/src/libc.zig @@ -82,7 +82,7 @@ fn fallback_panic_handler(msg_ptr: [*]const u8, msg_len: usize) callconv(.C) nor comptime { @export(fallback_panic_handler, std.builtin.ExportOptions{ .name = "foundation_libc_panic_handler", - .linkage = .Weak, + .linkage = .weak, .visibility = .default, }); } diff --git a/test/build.zig b/test/build.zig new file mode 100644 index 0000000..d6c282c --- /dev/null +++ b/test/build.zig @@ -0,0 +1,222 @@ +const std = @import("std"); +const Build = std.Build; + +pub fn build(b: *Build) void { + const validation_step = b.step("validate", "Runs the test suite and validates everything. Automatically triggered in Debug builds."); + + //const maybe_gcc = b.findProgram(&.{"gcc"}, &.{}) catch null; + const maybe_clang = b.findProgram(&.{"clang"}, &.{}) catch null; + + // Compile for huge amount of targets to detect breakage early on: + for ([_]bool{ false, true }) |validation_single_threaded| { + for (std.enums.values(std.builtin.OptimizeMode)) |validation_optimize| { + for (validation_target_list) |validation_target_query| { + const validation_target = b.resolveTargetQuery(validation_target_query); + + // skip everything that cannot support multithreading on freestanding: + if (!validation_single_threaded and !target_can_multithread(validation_target)) + continue; + + const dep = b.dependency("foundation_libc", .{ + .target = validation_target, + .optimize = validation_optimize, + .single_threaded = validation_single_threaded, + }); + + const foundation = dep.artifact("foundation"); + const syntax_validator_source = b.path("src/syntactic-validation.c"); + + { + // Check if the syntax of all of our header files is valid: + const syntax_validator = b.addStaticLibrary(.{ + .name = "syntax-validator", + .target = b.host, + .optimize = .Debug, + }); + syntax_validator.addCSourceFile(.{ + .file = syntax_validator_source, + .flags = &common_c_flags, + }); + syntax_validator.linkLibrary(foundation); + _ = syntax_validator.getEmittedBin(); + + // Just compile, do not install: + validation_step.dependOn(&syntax_validator.step); + } + + // use the host C compilers to validate our code: + for ([_]?[]const u8{maybe_clang}) |maybe_cc| { + const cc = maybe_cc orelse continue; + + const ext_compiler = b.addSystemCommand(&.{cc}); + + // just compile every time, we don't have dir caching + // so changes on the headers wouldn't re-trigger this + ext_compiler.has_side_effects = true; + + ext_compiler.addPrefixedDirectoryArg("-I", b.path("../include")); + + ext_compiler.addArg("-c"); // compile only + ext_compiler.addArg("-O0"); // no optimization for fast compiles + ext_compiler.addArg("-ffreestanding"); // we require freestanding environment + ext_compiler.addArg("-nostdlib"); // do not try to link anything useful + + // turn on warnings + ext_compiler.addArg("-Werror"); + ext_compiler.addArg("-Wall"); + ext_compiler.addArg("-Wextra"); + + ext_compiler.addFileArg(syntax_validator_source); + + ext_compiler.addArg("-o"); + ext_compiler.addArg(b.pathJoin(&.{ b.makeTempPath(), "dummy" })); // we don't really care where this ends up + + validation_step.dependOn(&ext_compiler.step); + } + + // Validate all modes of assertion: + for ([_][]const u8{ + "FOUNDATION_LIBC_ASSERT_DEFAULT", + "FOUNDATION_LIBC_ASSERT_NOFILE", + "FOUNDATION_LIBC_ASSERT_NOMSG", + "FOUNDATION_LIBC_ASSERT_EXPECTED", + }) |assert_mode| { + // Check if the syntax of all of our header files is valid: + const assert_validator = b.addStaticLibrary(.{ + .name = "assert-validator", + .target = b.host, + .optimize = .Debug, + }); + assert_validator.addCSourceFile(.{ + .file = b.path("src/assert-validator.c"), + .flags = &common_c_flags, + }); + assert_validator.linkLibrary(foundation); + _ = assert_validator.getEmittedBin(); + + assert_validator.defineCMacro("FOUNDATION_LIBC_ASSERT", assert_mode); + + // Just compile, do not install: + validation_step.dependOn(&assert_validator.step); + } + } + } + } +} + +const common_c_flags = [_][]const u8{ + "-std=c11", // target C standard + // + "-Werror", // we do not allow warnings + "-Wall", + "-Wextra", + "-Wmost", + "-Weverything", // this might be dropped later as we just want to find all potential warnings and enable/disable them as required. + // + "-Wno-reserved-macro-identifier", // we actually want to implement those! + "-Wno-reserved-identifier", // we actually want to implement those! +}; + +fn target_can_multithread(target: Build.ResolvedTarget) bool { + return switch (target.result.cpu.arch) { + .wasm32, + .wasm64, + .msp430, + => false, + + else => true, + }; +} + +const validation_target_list = [_]std.zig.CrossTarget{ + .{}, // regular host platform + .{ .os_tag = .freestanding }, // host platform, but no OS + + // Check several common cpu targets: + + // arm: + .{ .cpu_arch = .arm, .os_tag = .freestanding }, + .{ .cpu_arch = .armeb, .os_tag = .freestanding }, + .{ .cpu_arch = .thumb, .os_tag = .freestanding }, + .{ .cpu_arch = .thumbeb, .os_tag = .freestanding }, + .{ .cpu_arch = .aarch64, .os_tag = .freestanding }, + // .{ .cpu_arch = .aarch64_32, .os_tag = .freestanding }, // error: unknown target triple 'aarch64_32-unknown-unknown-eabi', please use -triple or -arch + .{ .cpu_arch = .aarch64_be, .os_tag = .freestanding }, + + // risc-v: + .{ .cpu_arch = .riscv32, .os_tag = .freestanding }, + .{ .cpu_arch = .riscv64, .os_tag = .freestanding }, + + // intel: + .{ .cpu_arch = .x86_64, .os_tag = .freestanding }, + .{ .cpu_arch = .x86, .os_tag = .freestanding }, + + // mips: + .{ .cpu_arch = .mips, .os_tag = .freestanding }, + .{ .cpu_arch = .mips64, .os_tag = .freestanding }, + .{ .cpu_arch = .mips64el, .os_tag = .freestanding }, + .{ .cpu_arch = .mipsel, .os_tag = .freestanding }, + + // sparc: + .{ .cpu_arch = .sparc, .os_tag = .freestanding }, + .{ .cpu_arch = .sparc64, .os_tag = .freestanding }, + .{ .cpu_arch = .sparcel, .os_tag = .freestanding }, + + // power: + .{ .cpu_arch = .powerpc, .os_tag = .freestanding }, + .{ .cpu_arch = .powerpc64, .os_tag = .freestanding }, + .{ .cpu_arch = .powerpc64le, .os_tag = .freestanding }, + .{ .cpu_arch = .powerpcle, .os_tag = .freestanding }, + + // web assembly: + .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, + .{ .cpu_arch = .wasm64, .os_tag = .freestanding }, + + // nice to have, but broken: + //.{ .cpu_arch = .avr, .os_tag = .freestanding }, + // .{ .cpu_arch = .msp430, .os_tag = .freestanding }, // error: unknown target CPU 'generic' + // .{ .cpu_arch = .m68k, .os_tag = .freestanding }, + // .{ .cpu_arch = .xtensa, .os_tag = .freestanding }, + + // Not evaluated if reasonable to check: + // arc + // csky + // hexagon + // hsail + // hsail64 + // kalimba + // lanai + // le32 + // le64 + // loongarch32 + // loongarch64 + // r600 + // s390x + // shave + // spu_2 + // tce + // tcele + // ve + // xcore + + // will never be supported due to their properties: + // spir + // spir64 + // spirv32 + // spirv64 + + // bpfeb + // bpfel + + // renderscript32 + // renderscript64 + + // amdgcn + // amdil + // amdil64 + + // nvptx + // nvptx64 + + // dxil +}; diff --git a/test/build.zig.zon b/test/build.zig.zon new file mode 100644 index 0000000..267e6d7 --- /dev/null +++ b/test/build.zig.zon @@ -0,0 +1,12 @@ +.{ + .name = "foundation-libc/test", + .version = "0.0.0", + .dependencies = .{ + .foundation_libc = .{ .path = ".." }, + }, + .paths = .{ + "build.zig", + "build.zig.zon", + "src", + }, +} diff --git a/tests/assert-validator.c b/test/src/assert-validator.c similarity index 100% rename from tests/assert-validator.c rename to test/src/assert-validator.c diff --git a/tests/syntactic-validation.c b/test/src/syntactic-validation.c similarity index 100% rename from tests/syntactic-validation.c rename to test/src/syntactic-validation.c