mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-05-21 08:32:02 +03:00
Merge pull request #14498 from ziglang/zig-build-api
Several enhancements to the build system. Many breaking changes to the API. * combine `std.build` and `std.build.Builder` into `std.Build` * eliminate `setTarget` and `setBuildMode`; use an options struct for `b.addExecutable` and friends * implement passing options to dependency packages. closes #14285 * rename `LibExeObjStep` to `CompileStep` * move src.type.CType to std lib, use it from std.Build, this helps with populating config.h files.
This commit is contained in:
@@ -1,19 +1,18 @@
|
||||
const std = @import("std");
|
||||
const builtin = std.builtin;
|
||||
const Builder = std.build.Builder;
|
||||
const tests = @import("test/tests.zig");
|
||||
const BufMap = std.BufMap;
|
||||
const mem = std.mem;
|
||||
const ArrayList = std.ArrayList;
|
||||
const io = std.io;
|
||||
const fs = std.fs;
|
||||
const InstallDirectoryOptions = std.build.InstallDirectoryOptions;
|
||||
const InstallDirectoryOptions = std.Build.InstallDirectoryOptions;
|
||||
const assert = std.debug.assert;
|
||||
|
||||
const zig_version = std.builtin.Version{ .major = 0, .minor = 11, .patch = 0 };
|
||||
const stack_size = 32 * 1024 * 1024;
|
||||
|
||||
pub fn build(b: *Builder) !void {
|
||||
pub fn build(b: *std.Build) !void {
|
||||
const release = b.option(bool, "release", "Build in release mode") orelse false;
|
||||
const only_c = b.option(bool, "only-c", "Translate the Zig compiler to C code, with only the C backend enabled") orelse false;
|
||||
const target = t: {
|
||||
@@ -23,7 +22,7 @@ pub fn build(b: *Builder) !void {
|
||||
}
|
||||
break :t b.standardTargetOptions(.{ .default_target = default_target });
|
||||
};
|
||||
const mode: std.builtin.Mode = if (release) switch (target.getCpuArch()) {
|
||||
const optimize: std.builtin.OptimizeMode = if (release) switch (target.getCpuArch()) {
|
||||
.wasm32 => .ReleaseSmall,
|
||||
else => .ReleaseFast,
|
||||
} else .Debug;
|
||||
@@ -33,7 +32,12 @@ pub fn build(b: *Builder) !void {
|
||||
|
||||
const test_step = b.step("test", "Run all the tests");
|
||||
|
||||
const docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");
|
||||
const docgen_exe = b.addExecutable(.{
|
||||
.name = "docgen",
|
||||
.root_source_file = .{ .path = "doc/docgen.zig" },
|
||||
.target = .{},
|
||||
.optimize = .Debug,
|
||||
});
|
||||
docgen_exe.single_threaded = single_threaded;
|
||||
|
||||
const rel_zig_exe = try fs.path.relative(b.allocator, b.build_root, b.zig_exe);
|
||||
@@ -53,10 +57,12 @@ pub fn build(b: *Builder) !void {
|
||||
const docs_step = b.step("docs", "Build documentation");
|
||||
docs_step.dependOn(&docgen_cmd.step);
|
||||
|
||||
const test_cases = b.addTest("src/test.zig");
|
||||
const test_cases = b.addTest(.{
|
||||
.root_source_file = .{ .path = "src/test.zig" },
|
||||
.optimize = optimize,
|
||||
});
|
||||
test_cases.main_pkg_path = ".";
|
||||
test_cases.stack_size = stack_size;
|
||||
test_cases.setBuildMode(mode);
|
||||
test_cases.single_threaded = single_threaded;
|
||||
|
||||
const fmt_build_zig = b.addFmt(&[_][]const u8{"build.zig"});
|
||||
@@ -149,17 +155,15 @@ pub fn build(b: *Builder) !void {
|
||||
|
||||
const mem_leak_frames: u32 = b.option(u32, "mem-leak-frames", "How many stack frames to print when a memory leak occurs. Tests get 2x this amount.") orelse blk: {
|
||||
if (strip == true) break :blk @as(u32, 0);
|
||||
if (mode != .Debug) break :blk 0;
|
||||
if (optimize != .Debug) break :blk 0;
|
||||
break :blk 4;
|
||||
};
|
||||
|
||||
const exe = addCompilerStep(b);
|
||||
const exe = addCompilerStep(b, optimize, target);
|
||||
exe.strip = strip;
|
||||
exe.sanitize_thread = sanitize_thread;
|
||||
exe.build_id = b.option(bool, "build-id", "Include a build id note") orelse false;
|
||||
exe.install();
|
||||
exe.setBuildMode(mode);
|
||||
exe.setTarget(target);
|
||||
|
||||
const compile_step = b.step("compile", "Build the self-hosted compiler");
|
||||
compile_step.dependOn(&exe.step);
|
||||
@@ -195,7 +199,7 @@ pub fn build(b: *Builder) !void {
|
||||
test_cases.linkLibC();
|
||||
}
|
||||
|
||||
const is_debug = mode == .Debug;
|
||||
const is_debug = optimize == .Debug;
|
||||
const enable_logging = b.option(bool, "log", "Enable debug logging with --debug-log") orelse is_debug;
|
||||
const enable_link_snapshots = b.option(bool, "link-snapshot", "Whether to enable linker state snapshots") orelse false;
|
||||
|
||||
@@ -360,25 +364,25 @@ pub fn build(b: *Builder) !void {
|
||||
test_step.dependOn(test_cases_step);
|
||||
}
|
||||
|
||||
var chosen_modes: [4]builtin.Mode = undefined;
|
||||
var chosen_opt_modes_buf: [4]builtin.Mode = undefined;
|
||||
var chosen_mode_index: usize = 0;
|
||||
if (!skip_debug) {
|
||||
chosen_modes[chosen_mode_index] = builtin.Mode.Debug;
|
||||
chosen_opt_modes_buf[chosen_mode_index] = builtin.Mode.Debug;
|
||||
chosen_mode_index += 1;
|
||||
}
|
||||
if (!skip_release_safe) {
|
||||
chosen_modes[chosen_mode_index] = builtin.Mode.ReleaseSafe;
|
||||
chosen_opt_modes_buf[chosen_mode_index] = builtin.Mode.ReleaseSafe;
|
||||
chosen_mode_index += 1;
|
||||
}
|
||||
if (!skip_release_fast) {
|
||||
chosen_modes[chosen_mode_index] = builtin.Mode.ReleaseFast;
|
||||
chosen_opt_modes_buf[chosen_mode_index] = builtin.Mode.ReleaseFast;
|
||||
chosen_mode_index += 1;
|
||||
}
|
||||
if (!skip_release_small) {
|
||||
chosen_modes[chosen_mode_index] = builtin.Mode.ReleaseSmall;
|
||||
chosen_opt_modes_buf[chosen_mode_index] = builtin.Mode.ReleaseSmall;
|
||||
chosen_mode_index += 1;
|
||||
}
|
||||
const modes = chosen_modes[0..chosen_mode_index];
|
||||
const optimization_modes = chosen_opt_modes_buf[0..chosen_mode_index];
|
||||
|
||||
// run stage1 `zig fmt` on this build.zig file just to make sure it works
|
||||
test_step.dependOn(&fmt_build_zig.step);
|
||||
@@ -391,7 +395,7 @@ pub fn build(b: *Builder) !void {
|
||||
"test/behavior.zig",
|
||||
"behavior",
|
||||
"Run the behavior tests",
|
||||
modes,
|
||||
optimization_modes,
|
||||
skip_single_threaded,
|
||||
skip_non_native,
|
||||
skip_libc,
|
||||
@@ -405,7 +409,7 @@ pub fn build(b: *Builder) !void {
|
||||
"lib/compiler_rt.zig",
|
||||
"compiler-rt",
|
||||
"Run the compiler_rt tests",
|
||||
modes,
|
||||
optimization_modes,
|
||||
true, // skip_single_threaded
|
||||
skip_non_native,
|
||||
true, // skip_libc
|
||||
@@ -419,7 +423,7 @@ pub fn build(b: *Builder) !void {
|
||||
"lib/c.zig",
|
||||
"universal-libc",
|
||||
"Run the universal libc tests",
|
||||
modes,
|
||||
optimization_modes,
|
||||
true, // skip_single_threaded
|
||||
skip_non_native,
|
||||
true, // skip_libc
|
||||
@@ -427,11 +431,11 @@ pub fn build(b: *Builder) !void {
|
||||
skip_stage2_tests or true, // TODO get these all passing
|
||||
));
|
||||
|
||||
test_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes));
|
||||
test_step.dependOn(tests.addCompareOutputTests(b, test_filter, optimization_modes));
|
||||
test_step.dependOn(tests.addStandaloneTests(
|
||||
b,
|
||||
test_filter,
|
||||
modes,
|
||||
optimization_modes,
|
||||
skip_non_native,
|
||||
enable_macos_sdk,
|
||||
target,
|
||||
@@ -444,10 +448,10 @@ pub fn build(b: *Builder) !void {
|
||||
enable_symlinks_windows,
|
||||
));
|
||||
test_step.dependOn(tests.addCAbiTests(b, skip_non_native, skip_release));
|
||||
test_step.dependOn(tests.addLinkTests(b, test_filter, modes, enable_macos_sdk, skip_stage2_tests, enable_symlinks_windows));
|
||||
test_step.dependOn(tests.addStackTraceTests(b, test_filter, modes));
|
||||
test_step.dependOn(tests.addCliTests(b, test_filter, modes));
|
||||
test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes));
|
||||
test_step.dependOn(tests.addLinkTests(b, test_filter, optimization_modes, enable_macos_sdk, skip_stage2_tests, enable_symlinks_windows));
|
||||
test_step.dependOn(tests.addStackTraceTests(b, test_filter, optimization_modes));
|
||||
test_step.dependOn(tests.addCliTests(b, test_filter, optimization_modes));
|
||||
test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, optimization_modes));
|
||||
test_step.dependOn(tests.addTranslateCTests(b, test_filter));
|
||||
if (!skip_run_translated_c) {
|
||||
test_step.dependOn(tests.addRunTranslatedCTests(b, test_filter, target));
|
||||
@@ -461,7 +465,7 @@ pub fn build(b: *Builder) !void {
|
||||
"lib/std/std.zig",
|
||||
"std",
|
||||
"Run the standard library tests",
|
||||
modes,
|
||||
optimization_modes,
|
||||
skip_single_threaded,
|
||||
skip_non_native,
|
||||
skip_libc,
|
||||
@@ -472,7 +476,7 @@ pub fn build(b: *Builder) !void {
|
||||
try addWasiUpdateStep(b, version);
|
||||
}
|
||||
|
||||
fn addWasiUpdateStep(b: *Builder, version: [:0]const u8) !void {
|
||||
fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
|
||||
const semver = try std.SemanticVersion.parse(version);
|
||||
|
||||
var target: std.zig.CrossTarget = .{
|
||||
@@ -481,9 +485,7 @@ fn addWasiUpdateStep(b: *Builder, version: [:0]const u8) !void {
|
||||
};
|
||||
target.cpu_features_add.addFeature(@enumToInt(std.Target.wasm.Feature.bulk_memory));
|
||||
|
||||
const exe = addCompilerStep(b);
|
||||
exe.setBuildMode(.ReleaseSmall);
|
||||
exe.setTarget(target);
|
||||
const exe = addCompilerStep(b, .ReleaseSmall, target);
|
||||
|
||||
const exe_options = b.addOptions();
|
||||
exe.addOptions("build_options", exe_options);
|
||||
@@ -510,8 +512,17 @@ fn addWasiUpdateStep(b: *Builder, version: [:0]const u8) !void {
|
||||
update_zig1_step.dependOn(&run_opt.step);
|
||||
}
|
||||
|
||||
fn addCompilerStep(b: *Builder) *std.build.LibExeObjStep {
|
||||
const exe = b.addExecutable("zig", "src/main.zig");
|
||||
fn addCompilerStep(
|
||||
b: *std.Build,
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
target: std.zig.CrossTarget,
|
||||
) *std.Build.CompileStep {
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "zig",
|
||||
.root_source_file = .{ .path = "src/main.zig" },
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe.stack_size = stack_size;
|
||||
return exe;
|
||||
}
|
||||
@@ -531,9 +542,9 @@ const exe_cflags = [_][]const u8{
|
||||
};
|
||||
|
||||
fn addCmakeCfgOptionsToExe(
|
||||
b: *Builder,
|
||||
b: *std.Build,
|
||||
cfg: CMakeConfig,
|
||||
exe: *std.build.LibExeObjStep,
|
||||
exe: *std.Build.CompileStep,
|
||||
use_zig_libcxx: bool,
|
||||
) !void {
|
||||
if (exe.target.isDarwin()) {
|
||||
@@ -612,7 +623,7 @@ fn addCmakeCfgOptionsToExe(
|
||||
}
|
||||
}
|
||||
|
||||
fn addStaticLlvmOptionsToExe(exe: *std.build.LibExeObjStep) !void {
|
||||
fn addStaticLlvmOptionsToExe(exe: *std.Build.CompileStep) !void {
|
||||
// Adds the Zig C++ sources which both stage1 and stage2 need.
|
||||
//
|
||||
// We need this because otherwise zig_clang_cc1_main.cpp ends up pulling
|
||||
@@ -649,9 +660,9 @@ fn addStaticLlvmOptionsToExe(exe: *std.build.LibExeObjStep) !void {
|
||||
}
|
||||
|
||||
fn addCxxKnownPath(
|
||||
b: *Builder,
|
||||
b: *std.Build,
|
||||
ctx: CMakeConfig,
|
||||
exe: *std.build.LibExeObjStep,
|
||||
exe: *std.Build.CompileStep,
|
||||
objname: []const u8,
|
||||
errtxt: ?[]const u8,
|
||||
need_cpp_includes: bool,
|
||||
@@ -684,7 +695,7 @@ fn addCxxKnownPath(
|
||||
}
|
||||
}
|
||||
|
||||
fn addCMakeLibraryList(exe: *std.build.LibExeObjStep, list: []const u8) void {
|
||||
fn addCMakeLibraryList(exe: *std.Build.CompileStep, list: []const u8) void {
|
||||
var it = mem.tokenize(u8, list, ";");
|
||||
while (it.next()) |lib| {
|
||||
if (mem.startsWith(u8, lib, "-l")) {
|
||||
@@ -698,7 +709,7 @@ fn addCMakeLibraryList(exe: *std.build.LibExeObjStep, list: []const u8) void {
|
||||
}
|
||||
|
||||
const CMakeConfig = struct {
|
||||
llvm_linkage: std.build.LibExeObjStep.Linkage,
|
||||
llvm_linkage: std.Build.CompileStep.Linkage,
|
||||
cmake_binary_dir: []const u8,
|
||||
cmake_prefix_path: []const u8,
|
||||
cmake_static_library_prefix: []const u8,
|
||||
@@ -715,7 +726,7 @@ const CMakeConfig = struct {
|
||||
|
||||
const max_config_h_bytes = 1 * 1024 * 1024;
|
||||
|
||||
fn findConfigH(b: *Builder, config_h_path_option: ?[]const u8) ?[]const u8 {
|
||||
fn findConfigH(b: *std.Build, config_h_path_option: ?[]const u8) ?[]const u8 {
|
||||
if (config_h_path_option) |path| {
|
||||
var config_h_or_err = fs.cwd().openFile(path, .{});
|
||||
if (config_h_or_err) |*file| {
|
||||
@@ -761,7 +772,7 @@ fn findConfigH(b: *Builder, config_h_path_option: ?[]const u8) ?[]const u8 {
|
||||
} else unreachable; // TODO should not need `else unreachable`.
|
||||
}
|
||||
|
||||
fn parseConfigH(b: *Builder, config_h_text: []const u8) ?CMakeConfig {
|
||||
fn parseConfigH(b: *std.Build, config_h_text: []const u8) ?CMakeConfig {
|
||||
var ctx: CMakeConfig = .{
|
||||
.llvm_linkage = undefined,
|
||||
.cmake_binary_dir = undefined,
|
||||
@@ -850,7 +861,7 @@ fn parseConfigH(b: *Builder, config_h_text: []const u8) ?CMakeConfig {
|
||||
return ctx;
|
||||
}
|
||||
|
||||
fn toNativePathSep(b: *Builder, s: []const u8) []u8 {
|
||||
fn toNativePathSep(b: *std.Build, s: []const u8) []u8 {
|
||||
const duplicated = b.allocator.dupe(u8, s) catch unreachable;
|
||||
for (duplicated) |*byte| switch (byte.*) {
|
||||
'/' => byte.* = fs.path.sep,
|
||||
@@ -859,166 +870,6 @@ fn toNativePathSep(b: *Builder, s: []const u8) []u8 {
|
||||
return duplicated;
|
||||
}
|
||||
|
||||
const softfloat_sources = [_][]const u8{
|
||||
"deps/SoftFloat-3e/source/8086/f128M_isSignalingNaN.c",
|
||||
"deps/SoftFloat-3e/source/8086/extF80M_isSignalingNaN.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_commonNaNToF128M.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_commonNaNToExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_commonNaNToF16UI.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_commonNaNToF32UI.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_commonNaNToF64UI.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_f128MToCommonNaN.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_extF80MToCommonNaN.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_f16UIToCommonNaN.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_f32UIToCommonNaN.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_f64UIToCommonNaN.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_propagateNaNF128M.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_propagateNaNExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/8086/s_propagateNaNF16UI.c",
|
||||
"deps/SoftFloat-3e/source/8086/softfloat_raiseFlags.c",
|
||||
"deps/SoftFloat-3e/source/f128M_add.c",
|
||||
"deps/SoftFloat-3e/source/f128M_div.c",
|
||||
"deps/SoftFloat-3e/source/f128M_eq.c",
|
||||
"deps/SoftFloat-3e/source/f128M_eq_signaling.c",
|
||||
"deps/SoftFloat-3e/source/f128M_le.c",
|
||||
"deps/SoftFloat-3e/source/f128M_le_quiet.c",
|
||||
"deps/SoftFloat-3e/source/f128M_lt.c",
|
||||
"deps/SoftFloat-3e/source/f128M_lt_quiet.c",
|
||||
"deps/SoftFloat-3e/source/f128M_mul.c",
|
||||
"deps/SoftFloat-3e/source/f128M_mulAdd.c",
|
||||
"deps/SoftFloat-3e/source/f128M_rem.c",
|
||||
"deps/SoftFloat-3e/source/f128M_roundToInt.c",
|
||||
"deps/SoftFloat-3e/source/f128M_sqrt.c",
|
||||
"deps/SoftFloat-3e/source/f128M_sub.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_f16.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_f32.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_f64.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_extF80M.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_i32.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_i32_r_minMag.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_i64.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_i64_r_minMag.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_ui32.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_ui32_r_minMag.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_ui64.c",
|
||||
"deps/SoftFloat-3e/source/f128M_to_ui64_r_minMag.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_add.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_div.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_eq.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_le.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_lt.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_mul.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_rem.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_roundToInt.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_sqrt.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_sub.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_to_f16.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_to_f32.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_to_f64.c",
|
||||
"deps/SoftFloat-3e/source/extF80M_to_f128M.c",
|
||||
"deps/SoftFloat-3e/source/f16_add.c",
|
||||
"deps/SoftFloat-3e/source/f16_div.c",
|
||||
"deps/SoftFloat-3e/source/f16_eq.c",
|
||||
"deps/SoftFloat-3e/source/f16_isSignalingNaN.c",
|
||||
"deps/SoftFloat-3e/source/f16_lt.c",
|
||||
"deps/SoftFloat-3e/source/f16_mul.c",
|
||||
"deps/SoftFloat-3e/source/f16_mulAdd.c",
|
||||
"deps/SoftFloat-3e/source/f16_rem.c",
|
||||
"deps/SoftFloat-3e/source/f16_roundToInt.c",
|
||||
"deps/SoftFloat-3e/source/f16_sqrt.c",
|
||||
"deps/SoftFloat-3e/source/f16_sub.c",
|
||||
"deps/SoftFloat-3e/source/f16_to_extF80M.c",
|
||||
"deps/SoftFloat-3e/source/f16_to_f128M.c",
|
||||
"deps/SoftFloat-3e/source/f16_to_f64.c",
|
||||
"deps/SoftFloat-3e/source/f32_to_extF80M.c",
|
||||
"deps/SoftFloat-3e/source/f32_to_f128M.c",
|
||||
"deps/SoftFloat-3e/source/f64_to_extF80M.c",
|
||||
"deps/SoftFloat-3e/source/f64_to_f128M.c",
|
||||
"deps/SoftFloat-3e/source/f64_to_f16.c",
|
||||
"deps/SoftFloat-3e/source/i32_to_f128M.c",
|
||||
"deps/SoftFloat-3e/source/s_add256M.c",
|
||||
"deps/SoftFloat-3e/source/s_addCarryM.c",
|
||||
"deps/SoftFloat-3e/source/s_addComplCarryM.c",
|
||||
"deps/SoftFloat-3e/source/s_addF128M.c",
|
||||
"deps/SoftFloat-3e/source/s_addExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/s_addM.c",
|
||||
"deps/SoftFloat-3e/source/s_addMagsF16.c",
|
||||
"deps/SoftFloat-3e/source/s_addMagsF32.c",
|
||||
"deps/SoftFloat-3e/source/s_addMagsF64.c",
|
||||
"deps/SoftFloat-3e/source/s_approxRecip32_1.c",
|
||||
"deps/SoftFloat-3e/source/s_approxRecipSqrt32_1.c",
|
||||
"deps/SoftFloat-3e/source/s_approxRecipSqrt_1Ks.c",
|
||||
"deps/SoftFloat-3e/source/s_approxRecip_1Ks.c",
|
||||
"deps/SoftFloat-3e/source/s_compare128M.c",
|
||||
"deps/SoftFloat-3e/source/s_compare96M.c",
|
||||
"deps/SoftFloat-3e/source/s_compareNonnormExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/s_countLeadingZeros16.c",
|
||||
"deps/SoftFloat-3e/source/s_countLeadingZeros32.c",
|
||||
"deps/SoftFloat-3e/source/s_countLeadingZeros64.c",
|
||||
"deps/SoftFloat-3e/source/s_countLeadingZeros8.c",
|
||||
"deps/SoftFloat-3e/source/s_eq128.c",
|
||||
"deps/SoftFloat-3e/source/s_invalidF128M.c",
|
||||
"deps/SoftFloat-3e/source/s_invalidExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/s_isNaNF128M.c",
|
||||
"deps/SoftFloat-3e/source/s_le128.c",
|
||||
"deps/SoftFloat-3e/source/s_lt128.c",
|
||||
"deps/SoftFloat-3e/source/s_mul128MTo256M.c",
|
||||
"deps/SoftFloat-3e/source/s_mul64To128M.c",
|
||||
"deps/SoftFloat-3e/source/s_mulAddF128M.c",
|
||||
"deps/SoftFloat-3e/source/s_mulAddF16.c",
|
||||
"deps/SoftFloat-3e/source/s_mulAddF32.c",
|
||||
"deps/SoftFloat-3e/source/s_mulAddF64.c",
|
||||
"deps/SoftFloat-3e/source/s_negXM.c",
|
||||
"deps/SoftFloat-3e/source/s_normExtF80SigM.c",
|
||||
"deps/SoftFloat-3e/source/s_normRoundPackMToF128M.c",
|
||||
"deps/SoftFloat-3e/source/s_normRoundPackMToExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/s_normRoundPackToF16.c",
|
||||
"deps/SoftFloat-3e/source/s_normRoundPackToF32.c",
|
||||
"deps/SoftFloat-3e/source/s_normRoundPackToF64.c",
|
||||
"deps/SoftFloat-3e/source/s_normSubnormalF128SigM.c",
|
||||
"deps/SoftFloat-3e/source/s_normSubnormalF16Sig.c",
|
||||
"deps/SoftFloat-3e/source/s_normSubnormalF32Sig.c",
|
||||
"deps/SoftFloat-3e/source/s_normSubnormalF64Sig.c",
|
||||
"deps/SoftFloat-3e/source/s_remStepMBy32.c",
|
||||
"deps/SoftFloat-3e/source/s_roundMToI64.c",
|
||||
"deps/SoftFloat-3e/source/s_roundMToUI64.c",
|
||||
"deps/SoftFloat-3e/source/s_roundPackMToExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/s_roundPackMToF128M.c",
|
||||
"deps/SoftFloat-3e/source/s_roundPackToF16.c",
|
||||
"deps/SoftFloat-3e/source/s_roundPackToF32.c",
|
||||
"deps/SoftFloat-3e/source/s_roundPackToF64.c",
|
||||
"deps/SoftFloat-3e/source/s_roundToI32.c",
|
||||
"deps/SoftFloat-3e/source/s_roundToI64.c",
|
||||
"deps/SoftFloat-3e/source/s_roundToUI32.c",
|
||||
"deps/SoftFloat-3e/source/s_roundToUI64.c",
|
||||
"deps/SoftFloat-3e/source/s_shiftLeftM.c",
|
||||
"deps/SoftFloat-3e/source/s_shiftNormSigF128M.c",
|
||||
"deps/SoftFloat-3e/source/s_shiftRightJam256M.c",
|
||||
"deps/SoftFloat-3e/source/s_shiftRightJam32.c",
|
||||
"deps/SoftFloat-3e/source/s_shiftRightJam64.c",
|
||||
"deps/SoftFloat-3e/source/s_shiftRightJamM.c",
|
||||
"deps/SoftFloat-3e/source/s_shiftRightM.c",
|
||||
"deps/SoftFloat-3e/source/s_shortShiftLeft64To96M.c",
|
||||
"deps/SoftFloat-3e/source/s_shortShiftLeftM.c",
|
||||
"deps/SoftFloat-3e/source/s_shortShiftRightExtendM.c",
|
||||
"deps/SoftFloat-3e/source/s_shortShiftRightJam64.c",
|
||||
"deps/SoftFloat-3e/source/s_shortShiftRightJamM.c",
|
||||
"deps/SoftFloat-3e/source/s_shortShiftRightM.c",
|
||||
"deps/SoftFloat-3e/source/s_sub1XM.c",
|
||||
"deps/SoftFloat-3e/source/s_sub256M.c",
|
||||
"deps/SoftFloat-3e/source/s_subM.c",
|
||||
"deps/SoftFloat-3e/source/s_subMagsF16.c",
|
||||
"deps/SoftFloat-3e/source/s_subMagsF32.c",
|
||||
"deps/SoftFloat-3e/source/s_subMagsF64.c",
|
||||
"deps/SoftFloat-3e/source/s_tryPropagateNaNF128M.c",
|
||||
"deps/SoftFloat-3e/source/s_tryPropagateNaNExtF80M.c",
|
||||
"deps/SoftFloat-3e/source/softfloat_state.c",
|
||||
"deps/SoftFloat-3e/source/ui32_to_f128M.c",
|
||||
"deps/SoftFloat-3e/source/ui64_to_f128M.c",
|
||||
"deps/SoftFloat-3e/source/ui32_to_extF80M.c",
|
||||
"deps/SoftFloat-3e/source/ui64_to_extF80M.c",
|
||||
};
|
||||
|
||||
const zig_cpp_sources = [_][]const u8{
|
||||
// These are planned to stay even when we are self-hosted.
|
||||
"src/zig_llvm.cpp",
|
||||
|
||||
+51
-28
@@ -9528,11 +9528,15 @@ fn foo(comptime T: type, ptr: *T) T {
|
||||
To add standard build options to a <code class="file">build.zig</code> file:
|
||||
</p>
|
||||
{#code_begin|syntax|build#}
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const exe = b.addExecutable("example", "example.zig");
|
||||
exe.setBuildMode(b.standardReleaseOptions());
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "example",
|
||||
.root_source_file = .{ .path = "example.zig" },
|
||||
.optimize = optimize,
|
||||
});
|
||||
b.default_step.dependOn(&exe.step);
|
||||
}
|
||||
{#code_end#}
|
||||
@@ -10547,22 +10551,26 @@ const separator = if (builtin.os.tag == .windows) '\\' else '/';
|
||||
<p>This <code class="file">build.zig</code> file is automatically generated
|
||||
by <kbd>zig init-exe</kbd>.</p>
|
||||
{#code_begin|syntax|build_executable#}
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
pub fn build(b: *std.Build) void {
|
||||
// Standard target options allows the person running `zig build` to choose
|
||||
// what target to build for. Here we do not override the defaults, which
|
||||
// means any target is allowed, and the default is native. Other options
|
||||
// for restricting supported target set are available.
|
||||
const target = b.standardTargetOptions(.{});
|
||||
|
||||
// Standard release options allow the person running `zig build` to select
|
||||
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
|
||||
const mode = b.standardReleaseOptions();
|
||||
// Standard optimization options allow the person running `zig build` to select
|
||||
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
|
||||
// set a preferred release mode, allowing the user to decide how to optimize.
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const exe = b.addExecutable("example", "src/main.zig");
|
||||
exe.setTarget(target);
|
||||
exe.setBuildMode(mode);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "example",
|
||||
.root_source_file = .{ .path = "src/main.zig" },
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe.install();
|
||||
|
||||
const run_cmd = exe.run();
|
||||
@@ -10581,16 +10589,21 @@ pub fn build(b: *Builder) void {
|
||||
<p>This <code class="file">build.zig</code> file is automatically generated
|
||||
by <kbd>zig init-lib</kbd>.</p>
|
||||
{#code_begin|syntax|build_library#}
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
const lib = b.addStaticLibrary("example", "src/main.zig");
|
||||
lib.setBuildMode(mode);
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const lib = b.addStaticLibrary(.{
|
||||
.name = "example",
|
||||
.root_source_file = .{ .path = "src/main.zig" },
|
||||
.optimize = optimize,
|
||||
});
|
||||
lib.install();
|
||||
|
||||
var main_tests = b.addTest("src/main.zig");
|
||||
main_tests.setBuildMode(mode);
|
||||
const main_tests = b.addTest(.{
|
||||
.root_source_file = .{ .path = "src/main.zig" },
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
const test_step = b.step("test", "Run library tests");
|
||||
test_step.dependOn(&main_tests.step);
|
||||
@@ -10949,12 +10962,17 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
{#end_syntax_block#}
|
||||
{#code_begin|syntax|build_c#}
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));
|
||||
|
||||
const exe = b.addExecutable("test", null);
|
||||
pub fn build(b: *std.Build) void {
|
||||
const lib = b.addSharedLibrary(.{
|
||||
.name = "mathtest",
|
||||
.root_source_file = .{ .path = "mathtest.zig" },
|
||||
.version = .{ .major = 1, .minor = 0, .patch = 0 },
|
||||
});
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "test",
|
||||
});
|
||||
exe.addCSourceFile("test.c", &[_][]const u8{"-std=c99"});
|
||||
exe.linkLibrary(lib);
|
||||
exe.linkSystemLibrary("c");
|
||||
@@ -11011,12 +11029,17 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
{#end_syntax_block#}
|
||||
{#code_begin|syntax|build_object#}
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const obj = b.addObject("base64", "base64.zig");
|
||||
pub fn build(b: *std.Build) void {
|
||||
const obj = b.addObject(.{
|
||||
.name = "base64",
|
||||
.root_source_file = .{ .path = "base64.zig" },
|
||||
});
|
||||
|
||||
const exe = b.addExecutable("test", null);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "test",
|
||||
});
|
||||
exe.addCSourceFile("test.c", &[_][]const u8{"-std=c99"});
|
||||
exe.addObject(obj);
|
||||
exe.linkSystemLibrary("c");
|
||||
|
||||
@@ -3,7 +3,6 @@ const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const io = std.io;
|
||||
const fmt = std.fmt;
|
||||
const Builder = std.build.Builder;
|
||||
const mem = std.mem;
|
||||
const process = std.process;
|
||||
const ArrayList = std.ArrayList;
|
||||
@@ -42,12 +41,15 @@ pub fn main() !void {
|
||||
return error.InvalidArgs;
|
||||
};
|
||||
|
||||
const builder = try Builder.create(
|
||||
const host = try std.zig.system.NativeTargetInfo.detect(.{});
|
||||
|
||||
const builder = try std.Build.create(
|
||||
allocator,
|
||||
zig_exe,
|
||||
build_root,
|
||||
cache_root,
|
||||
global_cache_root,
|
||||
host,
|
||||
);
|
||||
defer builder.destroy();
|
||||
|
||||
@@ -58,7 +60,7 @@ pub fn main() !void {
|
||||
const stdout_stream = io.getStdOut().writer();
|
||||
|
||||
var install_prefix: ?[]const u8 = null;
|
||||
var dir_list = Builder.DirList{};
|
||||
var dir_list = std.Build.DirList{};
|
||||
|
||||
// before arg parsing, check for the NO_COLOR environment variable
|
||||
// if it exists, default the color setting to .off
|
||||
@@ -230,7 +232,7 @@ pub fn main() !void {
|
||||
};
|
||||
}
|
||||
|
||||
fn usage(builder: *Builder, already_ran_build: bool, out_stream: anytype) !void {
|
||||
fn usage(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !void {
|
||||
// run the build script to collect the options
|
||||
if (!already_ran_build) {
|
||||
builder.resolveInstallPrefix(null, .{});
|
||||
@@ -330,7 +332,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: anytype) !void
|
||||
);
|
||||
}
|
||||
|
||||
fn usageAndErr(builder: *Builder, already_ran_build: bool, out_stream: anytype) void {
|
||||
fn usageAndErr(builder: *std.Build, already_ran_build: bool, out_stream: anytype) void {
|
||||
usage(builder, already_ran_build, out_stream) catch {};
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
+43
-10
@@ -1,34 +1,67 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.build.Builder) void {
|
||||
// Although this function looks imperative, note that its job is to
|
||||
// declaratively construct a build graph that will be executed by an external
|
||||
// runner.
|
||||
pub fn build(b: *std.Build) void {
|
||||
// Standard target options allows the person running `zig build` to choose
|
||||
// what target to build for. Here we do not override the defaults, which
|
||||
// means any target is allowed, and the default is native. Other options
|
||||
// for restricting supported target set are available.
|
||||
const target = b.standardTargetOptions(.{});
|
||||
|
||||
// Standard release options allow the person running `zig build` to select
|
||||
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
|
||||
const mode = b.standardReleaseOptions();
|
||||
// Standard optimization options allow the person running `zig build` to select
|
||||
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
|
||||
// set a preferred release mode, allowing the user to decide how to optimize.
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const exe = b.addExecutable("$", "src/main.zig");
|
||||
exe.setTarget(target);
|
||||
exe.setBuildMode(mode);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "$",
|
||||
// In this case the main source file is merely a path, however, in more
|
||||
// complicated build scripts, this could be a generated file.
|
||||
.root_source_file = .{ .path = "src/main.zig" },
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
// This declares intent for the executable to be installed into the
|
||||
// standard location when the user invokes the "install" step (the default
|
||||
// step when running `zig build`).
|
||||
exe.install();
|
||||
|
||||
// This *creates* a RunStep in the build graph, to be executed when another
|
||||
// step is evaluated that depends on it. The next line below will establish
|
||||
// such a dependency.
|
||||
const run_cmd = exe.run();
|
||||
|
||||
// By making the run step depend on the install step, it will be run from the
|
||||
// installation directory rather than directly from within the cache directory.
|
||||
// This is not necessary, however, if the application depends on other installed
|
||||
// files, this ensures they will be present and in the expected location.
|
||||
run_cmd.step.dependOn(b.getInstallStep());
|
||||
|
||||
// This allows the user to pass arguments to the application in the build
|
||||
// command itself, like this: `zig build run -- arg1 arg2 etc`
|
||||
if (b.args) |args| {
|
||||
run_cmd.addArgs(args);
|
||||
}
|
||||
|
||||
// This creates a build step. It will be visible in the `zig build --help` menu,
|
||||
// and can be selected like this: `zig build run`
|
||||
// This will evaluate the `run` step rather than the default, which is "install".
|
||||
const run_step = b.step("run", "Run the app");
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
|
||||
const exe_tests = b.addTest("src/main.zig");
|
||||
exe_tests.setTarget(target);
|
||||
exe_tests.setBuildMode(mode);
|
||||
// Creates a step for unit testing.
|
||||
const exe_tests = b.addTest(.{
|
||||
.root_source_file = .{ .path = "src/main.zig" },
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
// Similar to creating the run step earlier, this exposes a `test` step to
|
||||
// the `zig build --help` menu, providing a way for the user to request
|
||||
// running the unit tests.
|
||||
const test_step = b.step("test", "Run unit tests");
|
||||
test_step.dependOn(&exe_tests.step);
|
||||
}
|
||||
|
||||
+35
-8
@@ -1,17 +1,44 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.build.Builder) void {
|
||||
// Standard release options allow the person running `zig build` to select
|
||||
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
|
||||
const mode = b.standardReleaseOptions();
|
||||
// Although this function looks imperative, note that its job is to
|
||||
// declaratively construct a build graph that will be executed by an external
|
||||
// runner.
|
||||
pub fn build(b: *std.Build) void {
|
||||
// Standard target options allows the person running `zig build` to choose
|
||||
// what target to build for. Here we do not override the defaults, which
|
||||
// means any target is allowed, and the default is native. Other options
|
||||
// for restricting supported target set are available.
|
||||
const target = b.standardTargetOptions(.{});
|
||||
|
||||
const lib = b.addStaticLibrary("$", "src/main.zig");
|
||||
lib.setBuildMode(mode);
|
||||
// Standard optimization options allow the person running `zig build` to select
|
||||
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
|
||||
// set a preferred release mode, allowing the user to decide how to optimize.
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const lib = b.addStaticLibrary(.{
|
||||
.name = "$",
|
||||
// In this case the main source file is merely a path, however, in more
|
||||
// complicated build scripts, this could be a generated file.
|
||||
.root_source_file = .{ .path = "src/main.zig" },
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
// This declares intent for the library to be installed into the standard
|
||||
// location when the user invokes the "install" step (the default step when
|
||||
// running `zig build`).
|
||||
lib.install();
|
||||
|
||||
const main_tests = b.addTest("src/main.zig");
|
||||
main_tests.setBuildMode(mode);
|
||||
// Creates a step for unit testing.
|
||||
const main_tests = b.addTest(.{
|
||||
.root_source_file = .{ .path = "src/main.zig" },
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
// This creates a build step. It will be visible in the `zig build --help` menu,
|
||||
// and can be selected like this: `zig build test`
|
||||
// This will evaluate the `test` step rather than the default, which is "install".
|
||||
const test_step = b.step("test", "Run library tests");
|
||||
test_step.dependOn(&main_tests.step);
|
||||
}
|
||||
|
||||
+1780
@@ -0,0 +1,1780 @@
|
||||
const std = @import("std.zig");
|
||||
const builtin = @import("builtin");
|
||||
const io = std.io;
|
||||
const fs = std.fs;
|
||||
const mem = std.mem;
|
||||
const debug = std.debug;
|
||||
const panic = std.debug.panic;
|
||||
const assert = debug.assert;
|
||||
const log = std.log;
|
||||
const ArrayList = std.ArrayList;
|
||||
const StringHashMap = std.StringHashMap;
|
||||
const Allocator = mem.Allocator;
|
||||
const process = std.process;
|
||||
const EnvMap = std.process.EnvMap;
|
||||
const fmt_lib = std.fmt;
|
||||
const File = std.fs.File;
|
||||
const CrossTarget = std.zig.CrossTarget;
|
||||
const NativeTargetInfo = std.zig.system.NativeTargetInfo;
|
||||
const Sha256 = std.crypto.hash.sha2.Sha256;
|
||||
const Build = @This();
|
||||
|
||||
/// deprecated: use `CompileStep`.
|
||||
pub const LibExeObjStep = CompileStep;
|
||||
/// deprecated: use `Build`.
|
||||
pub const Builder = Build;
|
||||
/// deprecated: use `InstallDirStep.Options`
|
||||
pub const InstallDirectoryOptions = InstallDirStep.Options;
|
||||
|
||||
pub const Step = @import("Build/Step.zig");
|
||||
pub const CheckFileStep = @import("Build/CheckFileStep.zig");
|
||||
pub const CheckObjectStep = @import("Build/CheckObjectStep.zig");
|
||||
pub const ConfigHeaderStep = @import("Build/ConfigHeaderStep.zig");
|
||||
pub const EmulatableRunStep = @import("Build/EmulatableRunStep.zig");
|
||||
pub const FmtStep = @import("Build/FmtStep.zig");
|
||||
pub const InstallArtifactStep = @import("Build/InstallArtifactStep.zig");
|
||||
pub const InstallDirStep = @import("Build/InstallDirStep.zig");
|
||||
pub const InstallFileStep = @import("Build/InstallFileStep.zig");
|
||||
pub const InstallRawStep = @import("Build/InstallRawStep.zig");
|
||||
pub const CompileStep = @import("Build/CompileStep.zig");
|
||||
pub const LogStep = @import("Build/LogStep.zig");
|
||||
pub const OptionsStep = @import("Build/OptionsStep.zig");
|
||||
pub const RemoveDirStep = @import("Build/RemoveDirStep.zig");
|
||||
pub const RunStep = @import("Build/RunStep.zig");
|
||||
pub const TranslateCStep = @import("Build/TranslateCStep.zig");
|
||||
pub const WriteFileStep = @import("Build/WriteFileStep.zig");
|
||||
|
||||
install_tls: TopLevelStep,
|
||||
uninstall_tls: TopLevelStep,
|
||||
allocator: Allocator,
|
||||
user_input_options: UserInputOptionsMap,
|
||||
available_options_map: AvailableOptionsMap,
|
||||
available_options_list: ArrayList(AvailableOption),
|
||||
verbose: bool,
|
||||
verbose_link: bool,
|
||||
verbose_cc: bool,
|
||||
verbose_air: bool,
|
||||
verbose_llvm_ir: bool,
|
||||
verbose_cimport: bool,
|
||||
verbose_llvm_cpu_features: bool,
|
||||
/// The purpose of executing the command is for a human to read compile errors from the terminal
|
||||
prominent_compile_errors: bool,
|
||||
color: enum { auto, on, off } = .auto,
|
||||
reference_trace: ?u32 = null,
|
||||
invalid_user_input: bool,
|
||||
zig_exe: []const u8,
|
||||
default_step: *Step,
|
||||
env_map: *EnvMap,
|
||||
top_level_steps: ArrayList(*TopLevelStep),
|
||||
install_prefix: []const u8,
|
||||
dest_dir: ?[]const u8,
|
||||
lib_dir: []const u8,
|
||||
exe_dir: []const u8,
|
||||
h_dir: []const u8,
|
||||
install_path: []const u8,
|
||||
sysroot: ?[]const u8 = null,
|
||||
search_prefixes: ArrayList([]const u8),
|
||||
libc_file: ?[]const u8 = null,
|
||||
installed_files: ArrayList(InstalledFile),
|
||||
/// Path to the directory containing build.zig.
|
||||
build_root: []const u8,
|
||||
cache_root: []const u8,
|
||||
global_cache_root: []const u8,
|
||||
/// zig lib dir
|
||||
override_lib_dir: ?[]const u8,
|
||||
vcpkg_root: VcpkgRoot = .unattempted,
|
||||
pkg_config_pkg_list: ?(PkgConfigError![]const PkgConfigPkg) = null,
|
||||
args: ?[][]const u8 = null,
|
||||
debug_log_scopes: []const []const u8 = &.{},
|
||||
debug_compile_errors: bool = false,
|
||||
|
||||
/// Experimental. Use system Darling installation to run cross compiled macOS build artifacts.
|
||||
enable_darling: bool = false,
|
||||
/// Use system QEMU installation to run cross compiled foreign architecture build artifacts.
|
||||
enable_qemu: bool = false,
|
||||
/// Darwin. Use Rosetta to run x86_64 macOS build artifacts on arm64 macOS.
|
||||
enable_rosetta: bool = false,
|
||||
/// Use system Wasmtime installation to run cross compiled wasm/wasi build artifacts.
|
||||
enable_wasmtime: bool = false,
|
||||
/// Use system Wine installation to run cross compiled Windows build artifacts.
|
||||
enable_wine: bool = false,
|
||||
/// After following the steps in https://github.com/ziglang/zig/wiki/Updating-libc#glibc,
|
||||
/// this will be the directory $glibc-build-dir/install/glibcs
|
||||
/// Given the example of the aarch64 target, this is the directory
|
||||
/// that contains the path `aarch64-linux-gnu/lib/ld-linux-aarch64.so.1`.
|
||||
glibc_runtimes_dir: ?[]const u8 = null,
|
||||
|
||||
/// Information about the native target. Computed before build() is invoked.
|
||||
host: NativeTargetInfo,
|
||||
|
||||
dep_prefix: []const u8 = "",
|
||||
|
||||
pub const ExecError = error{
|
||||
ReadFailure,
|
||||
ExitCodeFailure,
|
||||
ProcessTerminated,
|
||||
ExecNotSupported,
|
||||
} || std.ChildProcess.SpawnError;
|
||||
|
||||
pub const PkgConfigError = error{
|
||||
PkgConfigCrashed,
|
||||
PkgConfigFailed,
|
||||
PkgConfigNotInstalled,
|
||||
PkgConfigInvalidOutput,
|
||||
};
|
||||
|
||||
pub const PkgConfigPkg = struct {
|
||||
name: []const u8,
|
||||
desc: []const u8,
|
||||
};
|
||||
|
||||
pub const CStd = enum {
|
||||
C89,
|
||||
C99,
|
||||
C11,
|
||||
};
|
||||
|
||||
const UserInputOptionsMap = StringHashMap(UserInputOption);
|
||||
const AvailableOptionsMap = StringHashMap(AvailableOption);
|
||||
|
||||
const AvailableOption = struct {
|
||||
name: []const u8,
|
||||
type_id: TypeId,
|
||||
description: []const u8,
|
||||
/// If the `type_id` is `enum` this provides the list of enum options
|
||||
enum_options: ?[]const []const u8,
|
||||
};
|
||||
|
||||
const UserInputOption = struct {
|
||||
name: []const u8,
|
||||
value: UserValue,
|
||||
used: bool,
|
||||
};
|
||||
|
||||
const UserValue = union(enum) {
|
||||
flag: void,
|
||||
scalar: []const u8,
|
||||
list: ArrayList([]const u8),
|
||||
map: StringHashMap(*const UserValue),
|
||||
};
|
||||
|
||||
const TypeId = enum {
|
||||
bool,
|
||||
int,
|
||||
float,
|
||||
@"enum",
|
||||
string,
|
||||
list,
|
||||
};
|
||||
|
||||
const TopLevelStep = struct {
|
||||
pub const base_id = .top_level;
|
||||
|
||||
step: Step,
|
||||
description: []const u8,
|
||||
};
|
||||
|
||||
pub const DirList = struct {
|
||||
lib_dir: ?[]const u8 = null,
|
||||
exe_dir: ?[]const u8 = null,
|
||||
include_dir: ?[]const u8 = null,
|
||||
};
|
||||
|
||||
pub fn create(
|
||||
allocator: Allocator,
|
||||
zig_exe: []const u8,
|
||||
build_root: []const u8,
|
||||
cache_root: []const u8,
|
||||
global_cache_root: []const u8,
|
||||
host: NativeTargetInfo,
|
||||
) !*Build {
|
||||
const env_map = try allocator.create(EnvMap);
|
||||
env_map.* = try process.getEnvMap(allocator);
|
||||
|
||||
const self = try allocator.create(Build);
|
||||
self.* = Build{
|
||||
.zig_exe = zig_exe,
|
||||
.build_root = build_root,
|
||||
.cache_root = try fs.path.relative(allocator, build_root, cache_root),
|
||||
.global_cache_root = global_cache_root,
|
||||
.verbose = false,
|
||||
.verbose_link = false,
|
||||
.verbose_cc = false,
|
||||
.verbose_air = false,
|
||||
.verbose_llvm_ir = false,
|
||||
.verbose_cimport = false,
|
||||
.verbose_llvm_cpu_features = false,
|
||||
.prominent_compile_errors = false,
|
||||
.invalid_user_input = false,
|
||||
.allocator = allocator,
|
||||
.user_input_options = UserInputOptionsMap.init(allocator),
|
||||
.available_options_map = AvailableOptionsMap.init(allocator),
|
||||
.available_options_list = ArrayList(AvailableOption).init(allocator),
|
||||
.top_level_steps = ArrayList(*TopLevelStep).init(allocator),
|
||||
.default_step = undefined,
|
||||
.env_map = env_map,
|
||||
.search_prefixes = ArrayList([]const u8).init(allocator),
|
||||
.install_prefix = undefined,
|
||||
.lib_dir = undefined,
|
||||
.exe_dir = undefined,
|
||||
.h_dir = undefined,
|
||||
.dest_dir = env_map.get("DESTDIR"),
|
||||
.installed_files = ArrayList(InstalledFile).init(allocator),
|
||||
.install_tls = TopLevelStep{
|
||||
.step = Step.initNoOp(.top_level, "install", allocator),
|
||||
.description = "Copy build artifacts to prefix path",
|
||||
},
|
||||
.uninstall_tls = TopLevelStep{
|
||||
.step = Step.init(.top_level, "uninstall", allocator, makeUninstall),
|
||||
.description = "Remove build artifacts from prefix path",
|
||||
},
|
||||
.override_lib_dir = null,
|
||||
.install_path = undefined,
|
||||
.args = null,
|
||||
.host = host,
|
||||
};
|
||||
try self.top_level_steps.append(&self.install_tls);
|
||||
try self.top_level_steps.append(&self.uninstall_tls);
|
||||
self.default_step = &self.install_tls.step;
|
||||
return self;
|
||||
}
|
||||
|
||||
fn createChild(
|
||||
parent: *Build,
|
||||
dep_name: []const u8,
|
||||
build_root: []const u8,
|
||||
args: anytype,
|
||||
) !*Build {
|
||||
const child = try createChildOnly(parent, dep_name, build_root);
|
||||
try applyArgs(child, args);
|
||||
return child;
|
||||
}
|
||||
|
||||
fn createChildOnly(parent: *Build, dep_name: []const u8, build_root: []const u8) !*Build {
|
||||
const allocator = parent.allocator;
|
||||
const child = try allocator.create(Build);
|
||||
child.* = .{
|
||||
.allocator = allocator,
|
||||
.install_tls = .{
|
||||
.step = Step.initNoOp(.top_level, "install", allocator),
|
||||
.description = "Copy build artifacts to prefix path",
|
||||
},
|
||||
.uninstall_tls = .{
|
||||
.step = Step.init(.top_level, "uninstall", allocator, makeUninstall),
|
||||
.description = "Remove build artifacts from prefix path",
|
||||
},
|
||||
.user_input_options = UserInputOptionsMap.init(allocator),
|
||||
.available_options_map = AvailableOptionsMap.init(allocator),
|
||||
.available_options_list = ArrayList(AvailableOption).init(allocator),
|
||||
.verbose = parent.verbose,
|
||||
.verbose_link = parent.verbose_link,
|
||||
.verbose_cc = parent.verbose_cc,
|
||||
.verbose_air = parent.verbose_air,
|
||||
.verbose_llvm_ir = parent.verbose_llvm_ir,
|
||||
.verbose_cimport = parent.verbose_cimport,
|
||||
.verbose_llvm_cpu_features = parent.verbose_llvm_cpu_features,
|
||||
.prominent_compile_errors = parent.prominent_compile_errors,
|
||||
.color = parent.color,
|
||||
.reference_trace = parent.reference_trace,
|
||||
.invalid_user_input = false,
|
||||
.zig_exe = parent.zig_exe,
|
||||
.default_step = undefined,
|
||||
.env_map = parent.env_map,
|
||||
.top_level_steps = ArrayList(*TopLevelStep).init(allocator),
|
||||
.install_prefix = undefined,
|
||||
.dest_dir = parent.dest_dir,
|
||||
.lib_dir = parent.lib_dir,
|
||||
.exe_dir = parent.exe_dir,
|
||||
.h_dir = parent.h_dir,
|
||||
.install_path = parent.install_path,
|
||||
.sysroot = parent.sysroot,
|
||||
.search_prefixes = ArrayList([]const u8).init(allocator),
|
||||
.libc_file = parent.libc_file,
|
||||
.installed_files = ArrayList(InstalledFile).init(allocator),
|
||||
.build_root = build_root,
|
||||
.cache_root = parent.cache_root,
|
||||
.global_cache_root = parent.global_cache_root,
|
||||
.override_lib_dir = parent.override_lib_dir,
|
||||
.debug_log_scopes = parent.debug_log_scopes,
|
||||
.debug_compile_errors = parent.debug_compile_errors,
|
||||
.enable_darling = parent.enable_darling,
|
||||
.enable_qemu = parent.enable_qemu,
|
||||
.enable_rosetta = parent.enable_rosetta,
|
||||
.enable_wasmtime = parent.enable_wasmtime,
|
||||
.enable_wine = parent.enable_wine,
|
||||
.glibc_runtimes_dir = parent.glibc_runtimes_dir,
|
||||
.host = parent.host,
|
||||
.dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }),
|
||||
};
|
||||
try child.top_level_steps.append(&child.install_tls);
|
||||
try child.top_level_steps.append(&child.uninstall_tls);
|
||||
child.default_step = &child.install_tls.step;
|
||||
return child;
|
||||
}
|
||||
|
||||
fn applyArgs(b: *Build, args: anytype) !void {
|
||||
inline for (@typeInfo(@TypeOf(args)).Struct.fields) |field| {
|
||||
const v = @field(args, field.name);
|
||||
const T = @TypeOf(v);
|
||||
switch (T) {
|
||||
CrossTarget => {
|
||||
try b.user_input_options.put(field.name, .{
|
||||
.name = field.name,
|
||||
.value = .{ .scalar = try v.zigTriple(b.allocator) },
|
||||
.used = false,
|
||||
});
|
||||
try b.user_input_options.put("cpu", .{
|
||||
.name = "cpu",
|
||||
.value = .{ .scalar = try serializeCpu(b.allocator, v.getCpu()) },
|
||||
.used = false,
|
||||
});
|
||||
},
|
||||
[]const u8 => {
|
||||
try b.user_input_options.put(field.name, .{
|
||||
.name = field.name,
|
||||
.value = .{ .scalar = v },
|
||||
.used = false,
|
||||
});
|
||||
},
|
||||
else => switch (@typeInfo(T)) {
|
||||
.Bool => {
|
||||
try b.user_input_options.put(field.name, .{
|
||||
.name = field.name,
|
||||
.value = .{ .scalar = if (v) "true" else "false" },
|
||||
.used = false,
|
||||
});
|
||||
},
|
||||
.Enum => {
|
||||
try b.user_input_options.put(field.name, .{
|
||||
.name = field.name,
|
||||
.value = .{ .scalar = @tagName(v) },
|
||||
.used = false,
|
||||
});
|
||||
},
|
||||
.Int => {
|
||||
try b.user_input_options.put(field.name, .{
|
||||
.name = field.name,
|
||||
.value = .{ .scalar = try std.fmt.allocPrint(b.allocator, "{d}", .{v}) },
|
||||
.used = false,
|
||||
});
|
||||
},
|
||||
else => @compileError("option '" ++ field.name ++ "' has unsupported type: " ++ @typeName(T)),
|
||||
},
|
||||
}
|
||||
}
|
||||
const Hasher = std.crypto.auth.siphash.SipHash128(1, 3);
|
||||
// Random bytes to make unique. Refresh this with new random bytes when
|
||||
// implementation is modified in a non-backwards-compatible way.
|
||||
var hash = Hasher.init("ZaEsvQ5ClaA2IdH9");
|
||||
hash.update(b.dep_prefix);
|
||||
// TODO additionally update the hash with `args`.
|
||||
|
||||
var digest: [16]u8 = undefined;
|
||||
hash.final(&digest);
|
||||
var hash_basename: [digest.len * 2]u8 = undefined;
|
||||
_ = std.fmt.bufPrint(&hash_basename, "{s}", .{std.fmt.fmtSliceHexLower(&digest)}) catch
|
||||
unreachable;
|
||||
|
||||
const install_prefix = b.pathJoin(&.{ b.cache_root, "i", &hash_basename });
|
||||
b.resolveInstallPrefix(install_prefix, .{});
|
||||
}
|
||||
|
||||
pub fn destroy(self: *Build) void {
|
||||
self.env_map.deinit();
|
||||
self.top_level_steps.deinit();
|
||||
self.allocator.destroy(self);
|
||||
}
|
||||
|
||||
/// This function is intended to be called by lib/build_runner.zig, not a build.zig file.
|
||||
pub fn resolveInstallPrefix(self: *Build, install_prefix: ?[]const u8, dir_list: DirList) void {
|
||||
if (self.dest_dir) |dest_dir| {
|
||||
self.install_prefix = install_prefix orelse "/usr";
|
||||
self.install_path = self.pathJoin(&.{ dest_dir, self.install_prefix });
|
||||
} else {
|
||||
self.install_prefix = install_prefix orelse
|
||||
(self.pathJoin(&.{ self.build_root, "zig-out" }));
|
||||
self.install_path = self.install_prefix;
|
||||
}
|
||||
|
||||
var lib_list = [_][]const u8{ self.install_path, "lib" };
|
||||
var exe_list = [_][]const u8{ self.install_path, "bin" };
|
||||
var h_list = [_][]const u8{ self.install_path, "include" };
|
||||
|
||||
if (dir_list.lib_dir) |dir| {
|
||||
if (std.fs.path.isAbsolute(dir)) lib_list[0] = self.dest_dir orelse "";
|
||||
lib_list[1] = dir;
|
||||
}
|
||||
|
||||
if (dir_list.exe_dir) |dir| {
|
||||
if (std.fs.path.isAbsolute(dir)) exe_list[0] = self.dest_dir orelse "";
|
||||
exe_list[1] = dir;
|
||||
}
|
||||
|
||||
if (dir_list.include_dir) |dir| {
|
||||
if (std.fs.path.isAbsolute(dir)) h_list[0] = self.dest_dir orelse "";
|
||||
h_list[1] = dir;
|
||||
}
|
||||
|
||||
self.lib_dir = self.pathJoin(&lib_list);
|
||||
self.exe_dir = self.pathJoin(&exe_list);
|
||||
self.h_dir = self.pathJoin(&h_list);
|
||||
}
|
||||
|
||||
pub fn addOptions(self: *Build) *OptionsStep {
|
||||
return OptionsStep.create(self);
|
||||
}
|
||||
|
||||
pub const ExecutableOptions = struct {
|
||||
name: []const u8,
|
||||
root_source_file: ?FileSource = null,
|
||||
version: ?std.builtin.Version = null,
|
||||
target: CrossTarget = .{},
|
||||
optimize: std.builtin.Mode = .Debug,
|
||||
linkage: ?CompileStep.Linkage = null,
|
||||
};
|
||||
|
||||
pub fn addExecutable(b: *Build, options: ExecutableOptions) *CompileStep {
|
||||
return CompileStep.create(b, .{
|
||||
.name = options.name,
|
||||
.root_source_file = options.root_source_file,
|
||||
.version = options.version,
|
||||
.target = options.target,
|
||||
.optimize = options.optimize,
|
||||
.kind = .exe,
|
||||
.linkage = options.linkage,
|
||||
});
|
||||
}
|
||||
|
||||
pub const ObjectOptions = struct {
|
||||
name: []const u8,
|
||||
root_source_file: ?FileSource = null,
|
||||
target: CrossTarget,
|
||||
optimize: std.builtin.Mode,
|
||||
};
|
||||
|
||||
pub fn addObject(b: *Build, options: ObjectOptions) *CompileStep {
|
||||
return CompileStep.create(b, .{
|
||||
.name = options.name,
|
||||
.root_source_file = options.root_source_file,
|
||||
.target = options.target,
|
||||
.optimize = options.optimize,
|
||||
.kind = .obj,
|
||||
});
|
||||
}
|
||||
|
||||
pub const SharedLibraryOptions = struct {
|
||||
name: []const u8,
|
||||
root_source_file: ?FileSource = null,
|
||||
version: ?std.builtin.Version = null,
|
||||
target: CrossTarget,
|
||||
optimize: std.builtin.Mode,
|
||||
};
|
||||
|
||||
pub fn addSharedLibrary(b: *Build, options: SharedLibraryOptions) *CompileStep {
|
||||
return CompileStep.create(b, .{
|
||||
.name = options.name,
|
||||
.root_source_file = options.root_source_file,
|
||||
.kind = .lib,
|
||||
.linkage = .dynamic,
|
||||
.version = options.version,
|
||||
.target = options.target,
|
||||
.optimize = options.optimize,
|
||||
});
|
||||
}
|
||||
|
||||
pub const StaticLibraryOptions = struct {
|
||||
name: []const u8,
|
||||
root_source_file: ?FileSource = null,
|
||||
target: CrossTarget,
|
||||
optimize: std.builtin.Mode,
|
||||
version: ?std.builtin.Version = null,
|
||||
};
|
||||
|
||||
pub fn addStaticLibrary(b: *Build, options: StaticLibraryOptions) *CompileStep {
|
||||
return CompileStep.create(b, .{
|
||||
.name = options.name,
|
||||
.root_source_file = options.root_source_file,
|
||||
.kind = .lib,
|
||||
.linkage = .static,
|
||||
.version = options.version,
|
||||
.target = options.target,
|
||||
.optimize = options.optimize,
|
||||
});
|
||||
}
|
||||
|
||||
pub const TestOptions = struct {
|
||||
name: []const u8 = "test",
|
||||
kind: CompileStep.Kind = .@"test",
|
||||
root_source_file: FileSource,
|
||||
target: CrossTarget = .{},
|
||||
optimize: std.builtin.Mode = .Debug,
|
||||
version: ?std.builtin.Version = null,
|
||||
};
|
||||
|
||||
pub fn addTest(b: *Build, options: TestOptions) *CompileStep {
|
||||
return CompileStep.create(b, .{
|
||||
.name = options.name,
|
||||
.kind = options.kind,
|
||||
.root_source_file = options.root_source_file,
|
||||
.target = options.target,
|
||||
.optimize = options.optimize,
|
||||
});
|
||||
}
|
||||
|
||||
pub const AssemblyOptions = struct {
|
||||
name: []const u8,
|
||||
source_file: FileSource,
|
||||
target: CrossTarget,
|
||||
optimize: std.builtin.Mode,
|
||||
};
|
||||
|
||||
pub fn addAssembly(b: *Build, options: AssemblyOptions) *CompileStep {
|
||||
const obj_step = CompileStep.create(b, .{
|
||||
.name = options.name,
|
||||
.root_source_file = null,
|
||||
.target = options.target,
|
||||
.optimize = options.optimize,
|
||||
});
|
||||
obj_step.addAssemblyFileSource(options.source_file.dupe(b));
|
||||
return obj_step;
|
||||
}
|
||||
|
||||
/// Initializes a RunStep with argv, which must at least have the path to the
|
||||
/// executable. More command line arguments can be added with `addArg`,
|
||||
/// `addArgs`, and `addArtifactArg`.
|
||||
/// Be careful using this function, as it introduces a system dependency.
|
||||
/// To run an executable built with zig build, see `CompileStep.run`.
|
||||
pub fn addSystemCommand(self: *Build, argv: []const []const u8) *RunStep {
|
||||
assert(argv.len >= 1);
|
||||
const run_step = RunStep.create(self, self.fmt("run {s}", .{argv[0]}));
|
||||
run_step.addArgs(argv);
|
||||
return run_step;
|
||||
}
|
||||
|
||||
pub fn addConfigHeader(
|
||||
b: *Build,
|
||||
source: FileSource,
|
||||
style: ConfigHeaderStep.Style,
|
||||
values: anytype,
|
||||
) *ConfigHeaderStep {
|
||||
const config_header_step = ConfigHeaderStep.create(b, source, style);
|
||||
config_header_step.addValues(values);
|
||||
return config_header_step;
|
||||
}
|
||||
|
||||
/// Allocator.dupe without the need to handle out of memory.
|
||||
pub fn dupe(self: *Build, bytes: []const u8) []u8 {
|
||||
return self.allocator.dupe(u8, bytes) catch @panic("OOM");
|
||||
}
|
||||
|
||||
/// Duplicates an array of strings without the need to handle out of memory.
|
||||
pub fn dupeStrings(self: *Build, strings: []const []const u8) [][]u8 {
|
||||
const array = self.allocator.alloc([]u8, strings.len) catch @panic("OOM");
|
||||
for (strings) |s, i| {
|
||||
array[i] = self.dupe(s);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/// Duplicates a path and converts all slashes to the OS's canonical path separator.
|
||||
pub fn dupePath(self: *Build, bytes: []const u8) []u8 {
|
||||
const the_copy = self.dupe(bytes);
|
||||
for (the_copy) |*byte| {
|
||||
switch (byte.*) {
|
||||
'/', '\\' => byte.* = fs.path.sep,
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
return the_copy;
|
||||
}
|
||||
|
||||
/// Duplicates a package recursively.
|
||||
pub fn dupePkg(self: *Build, package: Pkg) Pkg {
|
||||
var the_copy = Pkg{
|
||||
.name = self.dupe(package.name),
|
||||
.source = package.source.dupe(self),
|
||||
};
|
||||
|
||||
if (package.dependencies) |dependencies| {
|
||||
const new_dependencies = self.allocator.alloc(Pkg, dependencies.len) catch @panic("OOM");
|
||||
the_copy.dependencies = new_dependencies;
|
||||
|
||||
for (dependencies) |dep_package, i| {
|
||||
new_dependencies[i] = self.dupePkg(dep_package);
|
||||
}
|
||||
}
|
||||
return the_copy;
|
||||
}
|
||||
|
||||
pub fn addWriteFile(self: *Build, file_path: []const u8, data: []const u8) *WriteFileStep {
|
||||
const write_file_step = self.addWriteFiles();
|
||||
write_file_step.add(file_path, data);
|
||||
return write_file_step;
|
||||
}
|
||||
|
||||
pub fn addWriteFiles(self: *Build) *WriteFileStep {
|
||||
const write_file_step = self.allocator.create(WriteFileStep) catch @panic("OOM");
|
||||
write_file_step.* = WriteFileStep.init(self);
|
||||
return write_file_step;
|
||||
}
|
||||
|
||||
pub fn addLog(self: *Build, comptime format: []const u8, args: anytype) *LogStep {
|
||||
const data = self.fmt(format, args);
|
||||
const log_step = self.allocator.create(LogStep) catch @panic("OOM");
|
||||
log_step.* = LogStep.init(self, data);
|
||||
return log_step;
|
||||
}
|
||||
|
||||
pub fn addRemoveDirTree(self: *Build, dir_path: []const u8) *RemoveDirStep {
|
||||
const remove_dir_step = self.allocator.create(RemoveDirStep) catch @panic("OOM");
|
||||
remove_dir_step.* = RemoveDirStep.init(self, dir_path);
|
||||
return remove_dir_step;
|
||||
}
|
||||
|
||||
pub fn addFmt(self: *Build, paths: []const []const u8) *FmtStep {
|
||||
return FmtStep.create(self, paths);
|
||||
}
|
||||
|
||||
pub fn addTranslateC(self: *Build, options: TranslateCStep.Options) *TranslateCStep {
|
||||
return TranslateCStep.create(self, options);
|
||||
}
|
||||
|
||||
pub fn make(self: *Build, step_names: []const []const u8) !void {
|
||||
try self.makePath(self.cache_root);
|
||||
|
||||
var wanted_steps = ArrayList(*Step).init(self.allocator);
|
||||
defer wanted_steps.deinit();
|
||||
|
||||
if (step_names.len == 0) {
|
||||
try wanted_steps.append(self.default_step);
|
||||
} else {
|
||||
for (step_names) |step_name| {
|
||||
const s = try self.getTopLevelStepByName(step_name);
|
||||
try wanted_steps.append(s);
|
||||
}
|
||||
}
|
||||
|
||||
for (wanted_steps.items) |s| {
|
||||
try self.makeOneStep(s);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getInstallStep(self: *Build) *Step {
|
||||
return &self.install_tls.step;
|
||||
}
|
||||
|
||||
pub fn getUninstallStep(self: *Build) *Step {
|
||||
return &self.uninstall_tls.step;
|
||||
}
|
||||
|
||||
fn makeUninstall(uninstall_step: *Step) anyerror!void {
|
||||
const uninstall_tls = @fieldParentPtr(TopLevelStep, "step", uninstall_step);
|
||||
const self = @fieldParentPtr(Build, "uninstall_tls", uninstall_tls);
|
||||
|
||||
for (self.installed_files.items) |installed_file| {
|
||||
const full_path = self.getInstallPath(installed_file.dir, installed_file.path);
|
||||
if (self.verbose) {
|
||||
log.info("rm {s}", .{full_path});
|
||||
}
|
||||
fs.cwd().deleteTree(full_path) catch {};
|
||||
}
|
||||
|
||||
// TODO remove empty directories
|
||||
}
|
||||
|
||||
fn makeOneStep(self: *Build, s: *Step) anyerror!void {
|
||||
if (s.loop_flag) {
|
||||
log.err("Dependency loop detected:\n {s}", .{s.name});
|
||||
return error.DependencyLoopDetected;
|
||||
}
|
||||
s.loop_flag = true;
|
||||
|
||||
for (s.dependencies.items) |dep| {
|
||||
self.makeOneStep(dep) catch |err| {
|
||||
if (err == error.DependencyLoopDetected) {
|
||||
log.err(" {s}", .{s.name});
|
||||
}
|
||||
return err;
|
||||
};
|
||||
}
|
||||
|
||||
s.loop_flag = false;
|
||||
|
||||
try s.make();
|
||||
}
|
||||
|
||||
fn getTopLevelStepByName(self: *Build, name: []const u8) !*Step {
|
||||
for (self.top_level_steps.items) |top_level_step| {
|
||||
if (mem.eql(u8, top_level_step.step.name, name)) {
|
||||
return &top_level_step.step;
|
||||
}
|
||||
}
|
||||
log.err("Cannot run step '{s}' because it does not exist", .{name});
|
||||
return error.InvalidStepName;
|
||||
}
|
||||
|
||||
pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_raw: []const u8) ?T {
|
||||
const name = self.dupe(name_raw);
|
||||
const description = self.dupe(description_raw);
|
||||
const type_id = comptime typeToEnum(T);
|
||||
const enum_options = if (type_id == .@"enum") blk: {
|
||||
const fields = comptime std.meta.fields(T);
|
||||
var options = ArrayList([]const u8).initCapacity(self.allocator, fields.len) catch @panic("OOM");
|
||||
|
||||
inline for (fields) |field| {
|
||||
options.appendAssumeCapacity(field.name);
|
||||
}
|
||||
|
||||
break :blk options.toOwnedSlice() catch @panic("OOM");
|
||||
} else null;
|
||||
const available_option = AvailableOption{
|
||||
.name = name,
|
||||
.type_id = type_id,
|
||||
.description = description,
|
||||
.enum_options = enum_options,
|
||||
};
|
||||
if ((self.available_options_map.fetchPut(name, available_option) catch @panic("OOM")) != null) {
|
||||
panic("Option '{s}' declared twice", .{name});
|
||||
}
|
||||
self.available_options_list.append(available_option) catch @panic("OOM");
|
||||
|
||||
const option_ptr = self.user_input_options.getPtr(name) orelse return null;
|
||||
option_ptr.used = true;
|
||||
switch (type_id) {
|
||||
.bool => switch (option_ptr.value) {
|
||||
.flag => return true,
|
||||
.scalar => |s| {
|
||||
if (mem.eql(u8, s, "true")) {
|
||||
return true;
|
||||
} else if (mem.eql(u8, s, "false")) {
|
||||
return false;
|
||||
} else {
|
||||
log.err("Expected -D{s} to be a boolean, but received '{s}'\n", .{ name, s });
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
}
|
||||
},
|
||||
.list, .map => {
|
||||
log.err("Expected -D{s} to be a boolean, but received a {s}.\n", .{
|
||||
name, @tagName(option_ptr.value),
|
||||
});
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
},
|
||||
},
|
||||
.int => switch (option_ptr.value) {
|
||||
.flag, .list, .map => {
|
||||
log.err("Expected -D{s} to be an integer, but received a {s}.\n", .{
|
||||
name, @tagName(option_ptr.value),
|
||||
});
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
},
|
||||
.scalar => |s| {
|
||||
const n = std.fmt.parseInt(T, s, 10) catch |err| switch (err) {
|
||||
error.Overflow => {
|
||||
log.err("-D{s} value {s} cannot fit into type {s}.\n", .{ name, s, @typeName(T) });
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
},
|
||||
else => {
|
||||
log.err("Expected -D{s} to be an integer of type {s}.\n", .{ name, @typeName(T) });
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
},
|
||||
};
|
||||
return n;
|
||||
},
|
||||
},
|
||||
.float => switch (option_ptr.value) {
|
||||
.flag, .map, .list => {
|
||||
log.err("Expected -D{s} to be a float, but received a {s}.\n", .{
|
||||
name, @tagName(option_ptr.value),
|
||||
});
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
},
|
||||
.scalar => |s| {
|
||||
const n = std.fmt.parseFloat(T, s) catch {
|
||||
log.err("Expected -D{s} to be a float of type {s}.\n", .{ name, @typeName(T) });
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
};
|
||||
return n;
|
||||
},
|
||||
},
|
||||
.@"enum" => switch (option_ptr.value) {
|
||||
.flag, .map, .list => {
|
||||
log.err("Expected -D{s} to be an enum, but received a {s}.\n", .{
|
||||
name, @tagName(option_ptr.value),
|
||||
});
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
},
|
||||
.scalar => |s| {
|
||||
if (std.meta.stringToEnum(T, s)) |enum_lit| {
|
||||
return enum_lit;
|
||||
} else {
|
||||
log.err("Expected -D{s} to be of type {s}.\n", .{ name, @typeName(T) });
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
}
|
||||
},
|
||||
},
|
||||
.string => switch (option_ptr.value) {
|
||||
.flag, .list, .map => {
|
||||
log.err("Expected -D{s} to be a string, but received a {s}.\n", .{
|
||||
name, @tagName(option_ptr.value),
|
||||
});
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
},
|
||||
.scalar => |s| return s,
|
||||
},
|
||||
.list => switch (option_ptr.value) {
|
||||
.flag, .map => {
|
||||
log.err("Expected -D{s} to be a list, but received a {s}.\n", .{
|
||||
name, @tagName(option_ptr.value),
|
||||
});
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
},
|
||||
.scalar => |s| {
|
||||
return self.allocator.dupe([]const u8, &[_][]const u8{s}) catch @panic("OOM");
|
||||
},
|
||||
.list => |lst| return lst.items,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn step(self: *Build, name: []const u8, description: []const u8) *Step {
|
||||
const step_info = self.allocator.create(TopLevelStep) catch @panic("OOM");
|
||||
step_info.* = TopLevelStep{
|
||||
.step = Step.initNoOp(.top_level, name, self.allocator),
|
||||
.description = self.dupe(description),
|
||||
};
|
||||
self.top_level_steps.append(step_info) catch @panic("OOM");
|
||||
return &step_info.step;
|
||||
}
|
||||
|
||||
pub const StandardOptimizeOptionOptions = struct {
|
||||
preferred_optimize_mode: ?std.builtin.Mode = null,
|
||||
};
|
||||
|
||||
pub fn standardOptimizeOption(self: *Build, options: StandardOptimizeOptionOptions) std.builtin.Mode {
|
||||
if (options.preferred_optimize_mode) |mode| {
|
||||
if (self.option(bool, "release", "optimize for end users") orelse false) {
|
||||
return mode;
|
||||
} else {
|
||||
return .Debug;
|
||||
}
|
||||
} else {
|
||||
return self.option(
|
||||
std.builtin.Mode,
|
||||
"optimize",
|
||||
"prioritize performance, safety, or binary size (-O flag)",
|
||||
) orelse .Debug;
|
||||
}
|
||||
}
|
||||
|
||||
pub const StandardTargetOptionsArgs = struct {
|
||||
whitelist: ?[]const CrossTarget = null,
|
||||
|
||||
default_target: CrossTarget = CrossTarget{},
|
||||
};
|
||||
|
||||
/// Exposes standard `zig build` options for choosing a target.
|
||||
pub fn standardTargetOptions(self: *Build, args: StandardTargetOptionsArgs) CrossTarget {
|
||||
const maybe_triple = self.option(
|
||||
[]const u8,
|
||||
"target",
|
||||
"The CPU architecture, OS, and ABI to build for",
|
||||
);
|
||||
const mcpu = self.option([]const u8, "cpu", "Target CPU features to add or subtract");
|
||||
|
||||
if (maybe_triple == null and mcpu == null) {
|
||||
return args.default_target;
|
||||
}
|
||||
|
||||
const triple = maybe_triple orelse "native";
|
||||
|
||||
var diags: CrossTarget.ParseOptions.Diagnostics = .{};
|
||||
const selected_target = CrossTarget.parse(.{
|
||||
.arch_os_abi = triple,
|
||||
.cpu_features = mcpu,
|
||||
.diagnostics = &diags,
|
||||
}) catch |err| switch (err) {
|
||||
error.UnknownCpuModel => {
|
||||
log.err("Unknown CPU: '{s}'\nAvailable CPUs for architecture '{s}':", .{
|
||||
diags.cpu_name.?,
|
||||
@tagName(diags.arch.?),
|
||||
});
|
||||
for (diags.arch.?.allCpuModels()) |cpu| {
|
||||
log.err(" {s}", .{cpu.name});
|
||||
}
|
||||
self.markInvalidUserInput();
|
||||
return args.default_target;
|
||||
},
|
||||
error.UnknownCpuFeature => {
|
||||
log.err(
|
||||
\\Unknown CPU feature: '{s}'
|
||||
\\Available CPU features for architecture '{s}':
|
||||
\\
|
||||
, .{
|
||||
diags.unknown_feature_name.?,
|
||||
@tagName(diags.arch.?),
|
||||
});
|
||||
for (diags.arch.?.allFeaturesList()) |feature| {
|
||||
log.err(" {s}: {s}", .{ feature.name, feature.description });
|
||||
}
|
||||
self.markInvalidUserInput();
|
||||
return args.default_target;
|
||||
},
|
||||
error.UnknownOperatingSystem => {
|
||||
log.err(
|
||||
\\Unknown OS: '{s}'
|
||||
\\Available operating systems:
|
||||
\\
|
||||
, .{diags.os_name.?});
|
||||
inline for (std.meta.fields(std.Target.Os.Tag)) |field| {
|
||||
log.err(" {s}", .{field.name});
|
||||
}
|
||||
self.markInvalidUserInput();
|
||||
return args.default_target;
|
||||
},
|
||||
else => |e| {
|
||||
log.err("Unable to parse target '{s}': {s}\n", .{ triple, @errorName(e) });
|
||||
self.markInvalidUserInput();
|
||||
return args.default_target;
|
||||
},
|
||||
};
|
||||
|
||||
const selected_canonicalized_triple = selected_target.zigTriple(self.allocator) catch @panic("OOM");
|
||||
|
||||
if (args.whitelist) |list| whitelist_check: {
|
||||
// Make sure it's a match of one of the list.
|
||||
var mismatch_triple = true;
|
||||
var mismatch_cpu_features = true;
|
||||
var whitelist_item = CrossTarget{};
|
||||
for (list) |t| {
|
||||
mismatch_cpu_features = true;
|
||||
mismatch_triple = true;
|
||||
|
||||
const t_triple = t.zigTriple(self.allocator) catch @panic("OOM");
|
||||
if (mem.eql(u8, t_triple, selected_canonicalized_triple)) {
|
||||
mismatch_triple = false;
|
||||
whitelist_item = t;
|
||||
if (t.getCpuFeatures().isSuperSetOf(selected_target.getCpuFeatures())) {
|
||||
mismatch_cpu_features = false;
|
||||
break :whitelist_check;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mismatch_triple) {
|
||||
log.err("Chosen target '{s}' does not match one of the supported targets:", .{
|
||||
selected_canonicalized_triple,
|
||||
});
|
||||
for (list) |t| {
|
||||
const t_triple = t.zigTriple(self.allocator) catch @panic("OOM");
|
||||
log.err(" {s}", .{t_triple});
|
||||
}
|
||||
} else {
|
||||
assert(mismatch_cpu_features);
|
||||
const whitelist_cpu = whitelist_item.getCpu();
|
||||
const selected_cpu = selected_target.getCpu();
|
||||
log.err("Chosen CPU model '{s}' does not match one of the supported targets:", .{
|
||||
selected_cpu.model.name,
|
||||
});
|
||||
log.err(" Supported feature Set: ", .{});
|
||||
const all_features = whitelist_cpu.arch.allFeaturesList();
|
||||
var populated_cpu_features = whitelist_cpu.model.features;
|
||||
populated_cpu_features.populateDependencies(all_features);
|
||||
for (all_features) |feature, i_usize| {
|
||||
const i = @intCast(std.Target.Cpu.Feature.Set.Index, i_usize);
|
||||
const in_cpu_set = populated_cpu_features.isEnabled(i);
|
||||
if (in_cpu_set) {
|
||||
log.err("{s} ", .{feature.name});
|
||||
}
|
||||
}
|
||||
log.err(" Remove: ", .{});
|
||||
for (all_features) |feature, i_usize| {
|
||||
const i = @intCast(std.Target.Cpu.Feature.Set.Index, i_usize);
|
||||
const in_cpu_set = populated_cpu_features.isEnabled(i);
|
||||
const in_actual_set = selected_cpu.features.isEnabled(i);
|
||||
if (in_actual_set and !in_cpu_set) {
|
||||
log.err("{s} ", .{feature.name});
|
||||
}
|
||||
}
|
||||
}
|
||||
self.markInvalidUserInput();
|
||||
return args.default_target;
|
||||
}
|
||||
|
||||
return selected_target;
|
||||
}
|
||||
|
||||
pub fn addUserInputOption(self: *Build, name_raw: []const u8, value_raw: []const u8) !bool {
|
||||
const name = self.dupe(name_raw);
|
||||
const value = self.dupe(value_raw);
|
||||
const gop = try self.user_input_options.getOrPut(name);
|
||||
if (!gop.found_existing) {
|
||||
gop.value_ptr.* = UserInputOption{
|
||||
.name = name,
|
||||
.value = .{ .scalar = value },
|
||||
.used = false,
|
||||
};
|
||||
return false;
|
||||
}
|
||||
|
||||
// option already exists
|
||||
switch (gop.value_ptr.value) {
|
||||
.scalar => |s| {
|
||||
// turn it into a list
|
||||
var list = ArrayList([]const u8).init(self.allocator);
|
||||
try list.append(s);
|
||||
try list.append(value);
|
||||
try self.user_input_options.put(name, .{
|
||||
.name = name,
|
||||
.value = .{ .list = list },
|
||||
.used = false,
|
||||
});
|
||||
},
|
||||
.list => |*list| {
|
||||
// append to the list
|
||||
try list.append(value);
|
||||
try self.user_input_options.put(name, .{
|
||||
.name = name,
|
||||
.value = .{ .list = list.* },
|
||||
.used = false,
|
||||
});
|
||||
},
|
||||
.flag => {
|
||||
log.warn("Option '-D{s}={s}' conflicts with flag '-D{s}'.", .{ name, value, name });
|
||||
return true;
|
||||
},
|
||||
.map => |*map| {
|
||||
_ = map;
|
||||
log.warn("TODO maps as command line arguments is not implemented yet.", .{});
|
||||
return true;
|
||||
},
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn addUserInputFlag(self: *Build, name_raw: []const u8) !bool {
|
||||
const name = self.dupe(name_raw);
|
||||
const gop = try self.user_input_options.getOrPut(name);
|
||||
if (!gop.found_existing) {
|
||||
gop.value_ptr.* = .{
|
||||
.name = name,
|
||||
.value = .{ .flag = {} },
|
||||
.used = false,
|
||||
};
|
||||
return false;
|
||||
}
|
||||
|
||||
// option already exists
|
||||
switch (gop.value_ptr.value) {
|
||||
.scalar => |s| {
|
||||
log.err("Flag '-D{s}' conflicts with option '-D{s}={s}'.", .{ name, name, s });
|
||||
return true;
|
||||
},
|
||||
.list, .map => {
|
||||
log.err("Flag '-D{s}' conflicts with multiple options of the same name.", .{name});
|
||||
return true;
|
||||
},
|
||||
.flag => {},
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn typeToEnum(comptime T: type) TypeId {
|
||||
return switch (@typeInfo(T)) {
|
||||
.Int => .int,
|
||||
.Float => .float,
|
||||
.Bool => .bool,
|
||||
.Enum => .@"enum",
|
||||
else => switch (T) {
|
||||
[]const u8 => .string,
|
||||
[]const []const u8 => .list,
|
||||
else => @compileError("Unsupported type: " ++ @typeName(T)),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
fn markInvalidUserInput(self: *Build) void {
|
||||
self.invalid_user_input = true;
|
||||
}
|
||||
|
||||
pub fn validateUserInputDidItFail(self: *Build) bool {
|
||||
// make sure all args are used
|
||||
var it = self.user_input_options.iterator();
|
||||
while (it.next()) |entry| {
|
||||
if (!entry.value_ptr.used) {
|
||||
log.err("Invalid option: -D{s}", .{entry.key_ptr.*});
|
||||
self.markInvalidUserInput();
|
||||
}
|
||||
}
|
||||
|
||||
return self.invalid_user_input;
|
||||
}
|
||||
|
||||
pub fn spawnChild(self: *Build, argv: []const []const u8) !void {
|
||||
return self.spawnChildEnvMap(null, self.env_map, argv);
|
||||
}
|
||||
|
||||
fn printCmd(cwd: ?[]const u8, argv: []const []const u8) void {
|
||||
if (cwd) |yes_cwd| std.debug.print("cd {s} && ", .{yes_cwd});
|
||||
for (argv) |arg| {
|
||||
std.debug.print("{s} ", .{arg});
|
||||
}
|
||||
std.debug.print("\n", .{});
|
||||
}
|
||||
|
||||
pub fn spawnChildEnvMap(self: *Build, cwd: ?[]const u8, env_map: *const EnvMap, argv: []const []const u8) !void {
|
||||
if (self.verbose) {
|
||||
printCmd(cwd, argv);
|
||||
}
|
||||
|
||||
if (!std.process.can_spawn)
|
||||
return error.ExecNotSupported;
|
||||
|
||||
var child = std.ChildProcess.init(argv, self.allocator);
|
||||
child.cwd = cwd;
|
||||
child.env_map = env_map;
|
||||
|
||||
const term = child.spawnAndWait() catch |err| {
|
||||
log.err("Unable to spawn {s}: {s}", .{ argv[0], @errorName(err) });
|
||||
return err;
|
||||
};
|
||||
|
||||
switch (term) {
|
||||
.Exited => |code| {
|
||||
if (code != 0) {
|
||||
log.err("The following command exited with error code {}:", .{code});
|
||||
printCmd(cwd, argv);
|
||||
return error.UncleanExit;
|
||||
}
|
||||
},
|
||||
else => {
|
||||
log.err("The following command terminated unexpectedly:", .{});
|
||||
printCmd(cwd, argv);
|
||||
|
||||
return error.UncleanExit;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn makePath(self: *Build, path: []const u8) !void {
|
||||
fs.cwd().makePath(self.pathFromRoot(path)) catch |err| {
|
||||
log.err("Unable to create path {s}: {s}", .{ path, @errorName(err) });
|
||||
return err;
|
||||
};
|
||||
}
|
||||
|
||||
pub fn installArtifact(self: *Build, artifact: *CompileStep) void {
|
||||
self.getInstallStep().dependOn(&self.addInstallArtifact(artifact).step);
|
||||
}
|
||||
|
||||
pub fn addInstallArtifact(self: *Build, artifact: *CompileStep) *InstallArtifactStep {
|
||||
return InstallArtifactStep.create(self, artifact);
|
||||
}
|
||||
|
||||
///`dest_rel_path` is relative to prefix path
|
||||
pub fn installFile(self: *Build, src_path: []const u8, dest_rel_path: []const u8) void {
|
||||
self.getInstallStep().dependOn(&self.addInstallFileWithDir(.{ .path = src_path }, .prefix, dest_rel_path).step);
|
||||
}
|
||||
|
||||
pub fn installDirectory(self: *Build, options: InstallDirectoryOptions) void {
|
||||
self.getInstallStep().dependOn(&self.addInstallDirectory(options).step);
|
||||
}
|
||||
|
||||
///`dest_rel_path` is relative to bin path
|
||||
pub fn installBinFile(self: *Build, src_path: []const u8, dest_rel_path: []const u8) void {
|
||||
self.getInstallStep().dependOn(&self.addInstallFileWithDir(.{ .path = src_path }, .bin, dest_rel_path).step);
|
||||
}
|
||||
|
||||
///`dest_rel_path` is relative to lib path
|
||||
pub fn installLibFile(self: *Build, src_path: []const u8, dest_rel_path: []const u8) void {
|
||||
self.getInstallStep().dependOn(&self.addInstallFileWithDir(.{ .path = src_path }, .lib, dest_rel_path).step);
|
||||
}
|
||||
|
||||
/// Output format (BIN vs Intel HEX) determined by filename
|
||||
pub fn installRaw(self: *Build, artifact: *CompileStep, dest_filename: []const u8, options: InstallRawStep.CreateOptions) *InstallRawStep {
|
||||
const raw = self.addInstallRaw(artifact, dest_filename, options);
|
||||
self.getInstallStep().dependOn(&raw.step);
|
||||
return raw;
|
||||
}
|
||||
|
||||
///`dest_rel_path` is relative to install prefix path
|
||||
pub fn addInstallFile(self: *Build, source: FileSource, dest_rel_path: []const u8) *InstallFileStep {
|
||||
return self.addInstallFileWithDir(source.dupe(self), .prefix, dest_rel_path);
|
||||
}
|
||||
|
||||
///`dest_rel_path` is relative to bin path
|
||||
pub fn addInstallBinFile(self: *Build, source: FileSource, dest_rel_path: []const u8) *InstallFileStep {
|
||||
return self.addInstallFileWithDir(source.dupe(self), .bin, dest_rel_path);
|
||||
}
|
||||
|
||||
///`dest_rel_path` is relative to lib path
|
||||
pub fn addInstallLibFile(self: *Build, source: FileSource, dest_rel_path: []const u8) *InstallFileStep {
|
||||
return self.addInstallFileWithDir(source.dupe(self), .lib, dest_rel_path);
|
||||
}
|
||||
|
||||
pub fn addInstallHeaderFile(b: *Build, src_path: []const u8, dest_rel_path: []const u8) *InstallFileStep {
|
||||
return b.addInstallFileWithDir(.{ .path = src_path }, .header, dest_rel_path);
|
||||
}
|
||||
|
||||
pub fn addInstallRaw(self: *Build, artifact: *CompileStep, dest_filename: []const u8, options: InstallRawStep.CreateOptions) *InstallRawStep {
|
||||
return InstallRawStep.create(self, artifact, dest_filename, options);
|
||||
}
|
||||
|
||||
pub fn addInstallFileWithDir(
|
||||
self: *Build,
|
||||
source: FileSource,
|
||||
install_dir: InstallDir,
|
||||
dest_rel_path: []const u8,
|
||||
) *InstallFileStep {
|
||||
if (dest_rel_path.len == 0) {
|
||||
panic("dest_rel_path must be non-empty", .{});
|
||||
}
|
||||
const install_step = self.allocator.create(InstallFileStep) catch @panic("OOM");
|
||||
install_step.* = InstallFileStep.init(self, source.dupe(self), install_dir, dest_rel_path);
|
||||
return install_step;
|
||||
}
|
||||
|
||||
pub fn addInstallDirectory(self: *Build, options: InstallDirectoryOptions) *InstallDirStep {
|
||||
const install_step = self.allocator.create(InstallDirStep) catch @panic("OOM");
|
||||
install_step.* = InstallDirStep.init(self, options);
|
||||
return install_step;
|
||||
}
|
||||
|
||||
pub fn pushInstalledFile(self: *Build, dir: InstallDir, dest_rel_path: []const u8) void {
|
||||
const file = InstalledFile{
|
||||
.dir = dir,
|
||||
.path = dest_rel_path,
|
||||
};
|
||||
self.installed_files.append(file.dupe(self)) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn updateFile(self: *Build, source_path: []const u8, dest_path: []const u8) !void {
|
||||
if (self.verbose) {
|
||||
log.info("cp {s} {s} ", .{ source_path, dest_path });
|
||||
}
|
||||
const cwd = fs.cwd();
|
||||
const prev_status = try fs.Dir.updateFile(cwd, source_path, cwd, dest_path, .{});
|
||||
if (self.verbose) switch (prev_status) {
|
||||
.stale => log.info("# installed", .{}),
|
||||
.fresh => log.info("# up-to-date", .{}),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn truncateFile(self: *Build, dest_path: []const u8) !void {
|
||||
if (self.verbose) {
|
||||
log.info("truncate {s}", .{dest_path});
|
||||
}
|
||||
const cwd = fs.cwd();
|
||||
var src_file = cwd.createFile(dest_path, .{}) catch |err| switch (err) {
|
||||
error.FileNotFound => blk: {
|
||||
if (fs.path.dirname(dest_path)) |dirname| {
|
||||
try cwd.makePath(dirname);
|
||||
}
|
||||
break :blk try cwd.createFile(dest_path, .{});
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
src_file.close();
|
||||
}
|
||||
|
||||
pub fn pathFromRoot(self: *Build, rel_path: []const u8) []u8 {
|
||||
return fs.path.resolve(self.allocator, &[_][]const u8{ self.build_root, rel_path }) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn pathJoin(self: *Build, paths: []const []const u8) []u8 {
|
||||
return fs.path.join(self.allocator, paths) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn fmt(self: *Build, comptime format: []const u8, args: anytype) []u8 {
|
||||
return fmt_lib.allocPrint(self.allocator, format, args) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn findProgram(self: *Build, names: []const []const u8, paths: []const []const u8) ![]const u8 {
|
||||
// TODO report error for ambiguous situations
|
||||
const exe_extension = @as(CrossTarget, .{}).exeFileExt();
|
||||
for (self.search_prefixes.items) |search_prefix| {
|
||||
for (names) |name| {
|
||||
if (fs.path.isAbsolute(name)) {
|
||||
return name;
|
||||
}
|
||||
const full_path = self.pathJoin(&.{
|
||||
search_prefix,
|
||||
"bin",
|
||||
self.fmt("{s}{s}", .{ name, exe_extension }),
|
||||
});
|
||||
return fs.realpathAlloc(self.allocator, full_path) catch continue;
|
||||
}
|
||||
}
|
||||
if (self.env_map.get("PATH")) |PATH| {
|
||||
for (names) |name| {
|
||||
if (fs.path.isAbsolute(name)) {
|
||||
return name;
|
||||
}
|
||||
var it = mem.tokenize(u8, PATH, &[_]u8{fs.path.delimiter});
|
||||
while (it.next()) |path| {
|
||||
const full_path = self.pathJoin(&.{
|
||||
path,
|
||||
self.fmt("{s}{s}", .{ name, exe_extension }),
|
||||
});
|
||||
return fs.realpathAlloc(self.allocator, full_path) catch continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (names) |name| {
|
||||
if (fs.path.isAbsolute(name)) {
|
||||
return name;
|
||||
}
|
||||
for (paths) |path| {
|
||||
const full_path = self.pathJoin(&.{
|
||||
path,
|
||||
self.fmt("{s}{s}", .{ name, exe_extension }),
|
||||
});
|
||||
return fs.realpathAlloc(self.allocator, full_path) catch continue;
|
||||
}
|
||||
}
|
||||
return error.FileNotFound;
|
||||
}
|
||||
|
||||
pub fn execAllowFail(
|
||||
self: *Build,
|
||||
argv: []const []const u8,
|
||||
out_code: *u8,
|
||||
stderr_behavior: std.ChildProcess.StdIo,
|
||||
) ExecError![]u8 {
|
||||
assert(argv.len != 0);
|
||||
|
||||
if (!std.process.can_spawn)
|
||||
return error.ExecNotSupported;
|
||||
|
||||
const max_output_size = 400 * 1024;
|
||||
var child = std.ChildProcess.init(argv, self.allocator);
|
||||
child.stdin_behavior = .Ignore;
|
||||
child.stdout_behavior = .Pipe;
|
||||
child.stderr_behavior = stderr_behavior;
|
||||
child.env_map = self.env_map;
|
||||
|
||||
try child.spawn();
|
||||
|
||||
const stdout = child.stdout.?.reader().readAllAlloc(self.allocator, max_output_size) catch {
|
||||
return error.ReadFailure;
|
||||
};
|
||||
errdefer self.allocator.free(stdout);
|
||||
|
||||
const term = try child.wait();
|
||||
switch (term) {
|
||||
.Exited => |code| {
|
||||
if (code != 0) {
|
||||
out_code.* = @truncate(u8, code);
|
||||
return error.ExitCodeFailure;
|
||||
}
|
||||
return stdout;
|
||||
},
|
||||
.Signal, .Stopped, .Unknown => |code| {
|
||||
out_code.* = @truncate(u8, code);
|
||||
return error.ProcessTerminated;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn execFromStep(self: *Build, argv: []const []const u8, src_step: ?*Step) ![]u8 {
|
||||
assert(argv.len != 0);
|
||||
|
||||
if (self.verbose) {
|
||||
printCmd(null, argv);
|
||||
}
|
||||
|
||||
if (!std.process.can_spawn) {
|
||||
if (src_step) |s| log.err("{s}...", .{s.name});
|
||||
log.err("Unable to spawn the following command: cannot spawn child process", .{});
|
||||
printCmd(null, argv);
|
||||
std.os.abort();
|
||||
}
|
||||
|
||||
var code: u8 = undefined;
|
||||
return self.execAllowFail(argv, &code, .Inherit) catch |err| switch (err) {
|
||||
error.ExecNotSupported => {
|
||||
if (src_step) |s| log.err("{s}...", .{s.name});
|
||||
log.err("Unable to spawn the following command: cannot spawn child process", .{});
|
||||
printCmd(null, argv);
|
||||
std.os.abort();
|
||||
},
|
||||
error.FileNotFound => {
|
||||
if (src_step) |s| log.err("{s}...", .{s.name});
|
||||
log.err("Unable to spawn the following command: file not found", .{});
|
||||
printCmd(null, argv);
|
||||
std.os.exit(@truncate(u8, code));
|
||||
},
|
||||
error.ExitCodeFailure => {
|
||||
if (src_step) |s| log.err("{s}...", .{s.name});
|
||||
if (self.prominent_compile_errors) {
|
||||
log.err("The step exited with error code {d}", .{code});
|
||||
} else {
|
||||
log.err("The following command exited with error code {d}:", .{code});
|
||||
printCmd(null, argv);
|
||||
}
|
||||
|
||||
std.os.exit(@truncate(u8, code));
|
||||
},
|
||||
error.ProcessTerminated => {
|
||||
if (src_step) |s| log.err("{s}...", .{s.name});
|
||||
log.err("The following command terminated unexpectedly:", .{});
|
||||
printCmd(null, argv);
|
||||
std.os.exit(@truncate(u8, code));
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn exec(self: *Build, argv: []const []const u8) ![]u8 {
|
||||
return self.execFromStep(argv, null);
|
||||
}
|
||||
|
||||
pub fn addSearchPrefix(self: *Build, search_prefix: []const u8) void {
|
||||
self.search_prefixes.append(self.dupePath(search_prefix)) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn getInstallPath(self: *Build, dir: InstallDir, dest_rel_path: []const u8) []const u8 {
|
||||
assert(!fs.path.isAbsolute(dest_rel_path)); // Install paths must be relative to the prefix
|
||||
const base_dir = switch (dir) {
|
||||
.prefix => self.install_path,
|
||||
.bin => self.exe_dir,
|
||||
.lib => self.lib_dir,
|
||||
.header => self.h_dir,
|
||||
.custom => |path| self.pathJoin(&.{ self.install_path, path }),
|
||||
};
|
||||
return fs.path.resolve(
|
||||
self.allocator,
|
||||
&[_][]const u8{ base_dir, dest_rel_path },
|
||||
) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub const Dependency = struct {
|
||||
builder: *Build,
|
||||
|
||||
pub fn artifact(d: *Dependency, name: []const u8) *CompileStep {
|
||||
var found: ?*CompileStep = null;
|
||||
for (d.builder.install_tls.step.dependencies.items) |dep_step| {
|
||||
const inst = dep_step.cast(InstallArtifactStep) orelse continue;
|
||||
if (mem.eql(u8, inst.artifact.name, name)) {
|
||||
if (found != null) panic("artifact name '{s}' is ambiguous", .{name});
|
||||
found = inst.artifact;
|
||||
}
|
||||
}
|
||||
return found orelse {
|
||||
for (d.builder.install_tls.step.dependencies.items) |dep_step| {
|
||||
const inst = dep_step.cast(InstallArtifactStep) orelse continue;
|
||||
log.info("available artifact: '{s}'", .{inst.artifact.name});
|
||||
}
|
||||
panic("unable to find artifact '{s}'", .{name});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn dependency(b: *Build, name: []const u8, args: anytype) *Dependency {
|
||||
const build_runner = @import("root");
|
||||
const deps = build_runner.dependencies;
|
||||
|
||||
inline for (@typeInfo(deps.imports).Struct.decls) |decl| {
|
||||
if (mem.startsWith(u8, decl.name, b.dep_prefix) and
|
||||
mem.endsWith(u8, decl.name, name) and
|
||||
decl.name.len == b.dep_prefix.len + name.len)
|
||||
{
|
||||
const build_zig = @field(deps.imports, decl.name);
|
||||
const build_root = @field(deps.build_root, decl.name);
|
||||
return dependencyInner(b, name, build_root, build_zig, args);
|
||||
}
|
||||
}
|
||||
|
||||
const full_path = b.pathFromRoot("build.zig.ini");
|
||||
std.debug.print("no dependency named '{s}' in '{s}'\n", .{ name, full_path });
|
||||
std.process.exit(1);
|
||||
}
|
||||
|
||||
fn dependencyInner(
|
||||
b: *Build,
|
||||
name: []const u8,
|
||||
build_root: []const u8,
|
||||
comptime build_zig: type,
|
||||
args: anytype,
|
||||
) *Dependency {
|
||||
const sub_builder = b.createChild(name, build_root, args) catch @panic("unhandled error");
|
||||
sub_builder.runBuild(build_zig) catch @panic("unhandled error");
|
||||
|
||||
if (sub_builder.validateUserInputDidItFail()) {
|
||||
std.debug.dumpCurrentStackTrace(@returnAddress());
|
||||
}
|
||||
|
||||
const dep = b.allocator.create(Dependency) catch @panic("OOM");
|
||||
dep.* = .{ .builder = sub_builder };
|
||||
return dep;
|
||||
}
|
||||
|
||||
pub fn runBuild(b: *Build, build_zig: anytype) anyerror!void {
|
||||
switch (@typeInfo(@typeInfo(@TypeOf(build_zig.build)).Fn.return_type.?)) {
|
||||
.Void => build_zig.build(b),
|
||||
.ErrorUnion => try build_zig.build(b),
|
||||
else => @compileError("expected return type of build to be 'void' or '!void'"),
|
||||
}
|
||||
}
|
||||
|
||||
test "builder.findProgram compiles" {
|
||||
if (builtin.os.tag == .wasi) return error.SkipZigTest;
|
||||
|
||||
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
defer arena.deinit();
|
||||
|
||||
const host = try NativeTargetInfo.detect(.{});
|
||||
|
||||
const builder = try Build.create(
|
||||
arena.allocator(),
|
||||
"zig",
|
||||
"zig-cache",
|
||||
"zig-cache",
|
||||
"zig-cache",
|
||||
host,
|
||||
);
|
||||
defer builder.destroy();
|
||||
_ = builder.findProgram(&[_][]const u8{}, &[_][]const u8{}) catch null;
|
||||
}
|
||||
|
||||
pub const Pkg = struct {
|
||||
name: []const u8,
|
||||
source: FileSource,
|
||||
dependencies: ?[]const Pkg = null,
|
||||
};
|
||||
|
||||
/// A file that is generated by a build step.
|
||||
/// This struct is an interface that is meant to be used with `@fieldParentPtr` to implement the actual path logic.
|
||||
pub const GeneratedFile = struct {
|
||||
/// The step that generates the file
|
||||
step: *Step,
|
||||
|
||||
/// The path to the generated file. Must be either absolute or relative to the build root.
|
||||
/// This value must be set in the `fn make()` of the `step` and must not be `null` afterwards.
|
||||
path: ?[]const u8 = null,
|
||||
|
||||
pub fn getPath(self: GeneratedFile) []const u8 {
|
||||
return self.path orelse std.debug.panic(
|
||||
"getPath() was called on a GeneratedFile that wasn't build yet. Is there a missing Step dependency on step '{s}'?",
|
||||
.{self.step.name},
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/// A file source is a reference to an existing or future file.
|
||||
///
|
||||
pub const FileSource = union(enum) {
|
||||
/// A plain file path, relative to build root or absolute.
|
||||
path: []const u8,
|
||||
|
||||
/// A file that is generated by an interface. Those files usually are
|
||||
/// not available until built by a build step.
|
||||
generated: *const GeneratedFile,
|
||||
|
||||
/// Returns a new file source that will have a relative path to the build root guaranteed.
|
||||
/// This should be preferred over setting `.path` directly as it documents that the files are in the project directory.
|
||||
pub fn relative(path: []const u8) FileSource {
|
||||
std.debug.assert(!std.fs.path.isAbsolute(path));
|
||||
return FileSource{ .path = path };
|
||||
}
|
||||
|
||||
/// Returns a string that can be shown to represent the file source.
|
||||
/// Either returns the path or `"generated"`.
|
||||
pub fn getDisplayName(self: FileSource) []const u8 {
|
||||
return switch (self) {
|
||||
.path => self.path,
|
||||
.generated => "generated",
|
||||
};
|
||||
}
|
||||
|
||||
/// Adds dependencies this file source implies to the given step.
|
||||
pub fn addStepDependencies(self: FileSource, other_step: *Step) void {
|
||||
switch (self) {
|
||||
.path => {},
|
||||
.generated => |gen| other_step.dependOn(gen.step),
|
||||
}
|
||||
}
|
||||
|
||||
/// Should only be called during make(), returns a path relative to the build root or absolute.
|
||||
pub fn getPath(self: FileSource, builder: *Build) []const u8 {
|
||||
const path = switch (self) {
|
||||
.path => |p| builder.pathFromRoot(p),
|
||||
.generated => |gen| gen.getPath(),
|
||||
};
|
||||
return path;
|
||||
}
|
||||
|
||||
/// Duplicates the file source for a given builder.
|
||||
pub fn dupe(self: FileSource, b: *Build) FileSource {
|
||||
return switch (self) {
|
||||
.path => |p| .{ .path = b.dupePath(p) },
|
||||
.generated => |gen| .{ .generated = gen },
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Allocates a new string for assigning a value to a named macro.
|
||||
/// If the value is omitted, it is set to 1.
|
||||
/// `name` and `value` need not live longer than the function call.
|
||||
pub fn constructCMacro(allocator: Allocator, name: []const u8, value: ?[]const u8) []const u8 {
|
||||
var macro = allocator.alloc(
|
||||
u8,
|
||||
name.len + if (value) |value_slice| value_slice.len + 1 else 0,
|
||||
) catch |err| if (err == error.OutOfMemory) @panic("Out of memory") else unreachable;
|
||||
mem.copy(u8, macro, name);
|
||||
if (value) |value_slice| {
|
||||
macro[name.len] = '=';
|
||||
mem.copy(u8, macro[name.len + 1 ..], value_slice);
|
||||
}
|
||||
return macro;
|
||||
}
|
||||
|
||||
pub const VcpkgRoot = union(VcpkgRootStatus) {
|
||||
unattempted: void,
|
||||
not_found: void,
|
||||
found: []const u8,
|
||||
};
|
||||
|
||||
pub const VcpkgRootStatus = enum {
|
||||
unattempted,
|
||||
not_found,
|
||||
found,
|
||||
};
|
||||
|
||||
pub const InstallDir = union(enum) {
|
||||
prefix: void,
|
||||
lib: void,
|
||||
bin: void,
|
||||
header: void,
|
||||
/// A path relative to the prefix
|
||||
custom: []const u8,
|
||||
|
||||
/// Duplicates the install directory including the path if set to custom.
|
||||
pub fn dupe(self: InstallDir, builder: *Build) InstallDir {
|
||||
if (self == .custom) {
|
||||
// Written with this temporary to avoid RLS problems
|
||||
const duped_path = builder.dupe(self.custom);
|
||||
return .{ .custom = duped_path };
|
||||
} else {
|
||||
return self;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub const InstalledFile = struct {
|
||||
dir: InstallDir,
|
||||
path: []const u8,
|
||||
|
||||
/// Duplicates the installed file path and directory.
|
||||
pub fn dupe(self: InstalledFile, builder: *Build) InstalledFile {
|
||||
return .{
|
||||
.dir = self.dir.dupe(builder),
|
||||
.path = builder.dupe(self.path),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn serializeCpu(allocator: Allocator, cpu: std.Target.Cpu) ![]const u8 {
|
||||
// TODO this logic can disappear if cpu model + features becomes part of the target triple
|
||||
const all_features = cpu.arch.allFeaturesList();
|
||||
var populated_cpu_features = cpu.model.features;
|
||||
populated_cpu_features.populateDependencies(all_features);
|
||||
|
||||
if (populated_cpu_features.eql(cpu.features)) {
|
||||
// The CPU name alone is sufficient.
|
||||
return cpu.model.name;
|
||||
} else {
|
||||
var mcpu_buffer = ArrayList(u8).init(allocator);
|
||||
try mcpu_buffer.appendSlice(cpu.model.name);
|
||||
|
||||
for (all_features) |feature, i_usize| {
|
||||
const i = @intCast(std.Target.Cpu.Feature.Set.Index, i_usize);
|
||||
const in_cpu_set = populated_cpu_features.isEnabled(i);
|
||||
const in_actual_set = cpu.features.isEnabled(i);
|
||||
if (in_cpu_set and !in_actual_set) {
|
||||
try mcpu_buffer.writer().print("-{s}", .{feature.name});
|
||||
} else if (!in_cpu_set and in_actual_set) {
|
||||
try mcpu_buffer.writer().print("+{s}", .{feature.name});
|
||||
}
|
||||
}
|
||||
|
||||
return try mcpu_buffer.toOwnedSlice();
|
||||
}
|
||||
}
|
||||
|
||||
test "dupePkg()" {
|
||||
if (builtin.os.tag == .wasi) return error.SkipZigTest;
|
||||
|
||||
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
||||
defer arena.deinit();
|
||||
|
||||
const host = try NativeTargetInfo.detect(.{});
|
||||
|
||||
var builder = try Build.create(
|
||||
arena.allocator(),
|
||||
"test",
|
||||
"test",
|
||||
"test",
|
||||
"test",
|
||||
host,
|
||||
);
|
||||
defer builder.destroy();
|
||||
|
||||
var pkg_dep = Pkg{
|
||||
.name = "pkg_dep",
|
||||
.source = .{ .path = "/not/a/pkg_dep.zig" },
|
||||
};
|
||||
var pkg_top = Pkg{
|
||||
.name = "pkg_top",
|
||||
.source = .{ .path = "/not/a/pkg_top.zig" },
|
||||
.dependencies = &[_]Pkg{pkg_dep},
|
||||
};
|
||||
const duped = builder.dupePkg(pkg_top);
|
||||
|
||||
const original_deps = pkg_top.dependencies.?;
|
||||
const dupe_deps = duped.dependencies.?;
|
||||
|
||||
// probably the same top level package details
|
||||
try std.testing.expectEqualStrings(pkg_top.name, duped.name);
|
||||
|
||||
// probably the same dependencies
|
||||
try std.testing.expectEqual(original_deps.len, dupe_deps.len);
|
||||
try std.testing.expectEqual(original_deps[0].name, pkg_dep.name);
|
||||
|
||||
// could segfault otherwise if pointers in duplicated package's fields are
|
||||
// the same as those in stack allocated package's fields
|
||||
try std.testing.expect(dupe_deps.ptr != original_deps.ptr);
|
||||
try std.testing.expect(duped.name.ptr != pkg_top.name.ptr);
|
||||
try std.testing.expect(duped.source.path.ptr != pkg_top.source.path.ptr);
|
||||
try std.testing.expect(dupe_deps[0].name.ptr != pkg_dep.name.ptr);
|
||||
try std.testing.expect(dupe_deps[0].source.path.ptr != pkg_dep.source.path.ptr);
|
||||
}
|
||||
|
||||
test {
|
||||
_ = CheckFileStep;
|
||||
_ = CheckObjectStep;
|
||||
_ = EmulatableRunStep;
|
||||
_ = FmtStep;
|
||||
_ = InstallArtifactStep;
|
||||
_ = InstallDirStep;
|
||||
_ = InstallFileStep;
|
||||
_ = InstallRawStep;
|
||||
_ = CompileStep;
|
||||
_ = LogStep;
|
||||
_ = OptionsStep;
|
||||
_ = RemoveDirStep;
|
||||
_ = RunStep;
|
||||
_ = TranslateCStep;
|
||||
_ = WriteFileStep;
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
const std = @import("../std.zig");
|
||||
const build = std.build;
|
||||
const Step = build.Step;
|
||||
const Builder = build.Builder;
|
||||
const Step = std.Build.Step;
|
||||
const fs = std.fs;
|
||||
const mem = std.mem;
|
||||
|
||||
@@ -10,17 +8,17 @@ const CheckFileStep = @This();
|
||||
pub const base_id = .check_file;
|
||||
|
||||
step: Step,
|
||||
builder: *Builder,
|
||||
builder: *std.Build,
|
||||
expected_matches: []const []const u8,
|
||||
source: build.FileSource,
|
||||
source: std.Build.FileSource,
|
||||
max_bytes: usize = 20 * 1024 * 1024,
|
||||
|
||||
pub fn create(
|
||||
builder: *Builder,
|
||||
source: build.FileSource,
|
||||
builder: *std.Build,
|
||||
source: std.Build.FileSource,
|
||||
expected_matches: []const []const u8,
|
||||
) *CheckFileStep {
|
||||
const self = builder.allocator.create(CheckFileStep) catch unreachable;
|
||||
const self = builder.allocator.create(CheckFileStep) catch @panic("OOM");
|
||||
self.* = CheckFileStep{
|
||||
.builder = builder,
|
||||
.step = Step.init(.check_file, "CheckFile", builder.allocator, make),
|
||||
@@ -1,6 +1,5 @@
|
||||
const std = @import("../std.zig");
|
||||
const assert = std.debug.assert;
|
||||
const build = std.build;
|
||||
const fs = std.fs;
|
||||
const macho = std.macho;
|
||||
const math = std.math;
|
||||
@@ -10,23 +9,22 @@ const testing = std.testing;
|
||||
const CheckObjectStep = @This();
|
||||
|
||||
const Allocator = mem.Allocator;
|
||||
const Builder = build.Builder;
|
||||
const Step = build.Step;
|
||||
const EmulatableRunStep = build.EmulatableRunStep;
|
||||
const Step = std.Build.Step;
|
||||
const EmulatableRunStep = std.Build.EmulatableRunStep;
|
||||
|
||||
pub const base_id = .check_object;
|
||||
|
||||
step: Step,
|
||||
builder: *Builder,
|
||||
source: build.FileSource,
|
||||
builder: *std.Build,
|
||||
source: std.Build.FileSource,
|
||||
max_bytes: usize = 20 * 1024 * 1024,
|
||||
checks: std.ArrayList(Check),
|
||||
dump_symtab: bool = false,
|
||||
obj_format: std.Target.ObjectFormat,
|
||||
|
||||
pub fn create(builder: *Builder, source: build.FileSource, obj_format: std.Target.ObjectFormat) *CheckObjectStep {
|
||||
pub fn create(builder: *std.Build, source: std.Build.FileSource, obj_format: std.Target.ObjectFormat) *CheckObjectStep {
|
||||
const gpa = builder.allocator;
|
||||
const self = gpa.create(CheckObjectStep) catch unreachable;
|
||||
const self = gpa.create(CheckObjectStep) catch @panic("OOM");
|
||||
self.* = .{
|
||||
.builder = builder,
|
||||
.step = Step.init(.check_file, "CheckObject", gpa, make),
|
||||
@@ -44,7 +42,7 @@ pub fn runAndCompare(self: *CheckObjectStep) *EmulatableRunStep {
|
||||
const dependencies_len = self.step.dependencies.items.len;
|
||||
assert(dependencies_len > 0);
|
||||
const exe_step = self.step.dependencies.items[dependencies_len - 1];
|
||||
const exe = exe_step.cast(std.build.LibExeObjStep).?;
|
||||
const exe = exe_step.cast(std.Build.CompileStep).?;
|
||||
const emulatable_step = EmulatableRunStep.create(self.builder, "EmulatableRun", exe);
|
||||
emulatable_step.step.dependOn(&self.step);
|
||||
return emulatable_step;
|
||||
@@ -216,10 +214,10 @@ const ComputeCompareExpected = struct {
|
||||
};
|
||||
|
||||
const Check = struct {
|
||||
builder: *Builder,
|
||||
builder: *std.Build,
|
||||
actions: std.ArrayList(Action),
|
||||
|
||||
fn create(b: *Builder) Check {
|
||||
fn create(b: *std.Build) Check {
|
||||
return .{
|
||||
.builder = b,
|
||||
.actions = std.ArrayList(Action).init(b.allocator),
|
||||
@@ -230,14 +228,14 @@ const Check = struct {
|
||||
self.actions.append(.{
|
||||
.tag = .match,
|
||||
.phrase = self.builder.dupe(phrase),
|
||||
}) catch unreachable;
|
||||
}) catch @panic("OOM");
|
||||
}
|
||||
|
||||
fn notPresent(self: *Check, phrase: []const u8) void {
|
||||
self.actions.append(.{
|
||||
.tag = .not_present,
|
||||
.phrase = self.builder.dupe(phrase),
|
||||
}) catch unreachable;
|
||||
}) catch @panic("OOM");
|
||||
}
|
||||
|
||||
fn computeCmp(self: *Check, phrase: []const u8, expected: ComputeCompareExpected) void {
|
||||
@@ -245,7 +243,7 @@ const Check = struct {
|
||||
.tag = .compute_cmp,
|
||||
.phrase = self.builder.dupe(phrase),
|
||||
.expected = expected,
|
||||
}) catch unreachable;
|
||||
}) catch @panic("OOM");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -253,7 +251,7 @@ const Check = struct {
|
||||
pub fn checkStart(self: *CheckObjectStep, phrase: []const u8) void {
|
||||
var new_check = Check.create(self.builder);
|
||||
new_check.match(phrase);
|
||||
self.checks.append(new_check) catch unreachable;
|
||||
self.checks.append(new_check) catch @panic("OOM");
|
||||
}
|
||||
|
||||
/// Adds another searched phrase to the latest created Check with `CheckObjectStep.checkStart(...)`.
|
||||
@@ -295,7 +293,7 @@ pub fn checkComputeCompare(
|
||||
) void {
|
||||
var new_check = Check.create(self.builder);
|
||||
new_check.computeCmp(program, expected);
|
||||
self.checks.append(new_check) catch unreachable;
|
||||
self.checks.append(new_check) catch @panic("OOM");
|
||||
}
|
||||
|
||||
fn make(step: *Step) !void {
|
||||
@@ -9,41 +9,39 @@ const ArrayList = std.ArrayList;
|
||||
const StringHashMap = std.StringHashMap;
|
||||
const Sha256 = std.crypto.hash.sha2.Sha256;
|
||||
const Allocator = mem.Allocator;
|
||||
const build = @import("../build.zig");
|
||||
const Step = build.Step;
|
||||
const Builder = build.Builder;
|
||||
const Step = std.Build.Step;
|
||||
const CrossTarget = std.zig.CrossTarget;
|
||||
const NativeTargetInfo = std.zig.system.NativeTargetInfo;
|
||||
const FileSource = std.build.FileSource;
|
||||
const PkgConfigPkg = Builder.PkgConfigPkg;
|
||||
const PkgConfigError = Builder.PkgConfigError;
|
||||
const ExecError = Builder.ExecError;
|
||||
const Pkg = std.build.Pkg;
|
||||
const VcpkgRoot = std.build.VcpkgRoot;
|
||||
const InstallDir = std.build.InstallDir;
|
||||
const InstallArtifactStep = std.build.InstallArtifactStep;
|
||||
const GeneratedFile = std.build.GeneratedFile;
|
||||
const InstallRawStep = std.build.InstallRawStep;
|
||||
const EmulatableRunStep = std.build.EmulatableRunStep;
|
||||
const CheckObjectStep = std.build.CheckObjectStep;
|
||||
const RunStep = std.build.RunStep;
|
||||
const OptionsStep = std.build.OptionsStep;
|
||||
const ConfigHeaderStep = std.build.ConfigHeaderStep;
|
||||
const LibExeObjStep = @This();
|
||||
const FileSource = std.Build.FileSource;
|
||||
const PkgConfigPkg = std.Build.PkgConfigPkg;
|
||||
const PkgConfigError = std.Build.PkgConfigError;
|
||||
const ExecError = std.Build.ExecError;
|
||||
const Pkg = std.Build.Pkg;
|
||||
const VcpkgRoot = std.Build.VcpkgRoot;
|
||||
const InstallDir = std.Build.InstallDir;
|
||||
const InstallArtifactStep = std.Build.InstallArtifactStep;
|
||||
const GeneratedFile = std.Build.GeneratedFile;
|
||||
const InstallRawStep = std.Build.InstallRawStep;
|
||||
const EmulatableRunStep = std.Build.EmulatableRunStep;
|
||||
const CheckObjectStep = std.Build.CheckObjectStep;
|
||||
const RunStep = std.Build.RunStep;
|
||||
const OptionsStep = std.Build.OptionsStep;
|
||||
const ConfigHeaderStep = std.Build.ConfigHeaderStep;
|
||||
const CompileStep = @This();
|
||||
|
||||
pub const base_id = .lib_exe_obj;
|
||||
pub const base_id: Step.Id = .compile;
|
||||
|
||||
step: Step,
|
||||
builder: *Builder,
|
||||
builder: *std.Build,
|
||||
name: []const u8,
|
||||
target: CrossTarget = CrossTarget{},
|
||||
target: CrossTarget,
|
||||
target_info: NativeTargetInfo,
|
||||
optimize: std.builtin.Mode,
|
||||
linker_script: ?FileSource = null,
|
||||
version_script: ?[]const u8 = null,
|
||||
out_filename: []const u8,
|
||||
linkage: ?Linkage = null,
|
||||
version: ?std.builtin.Version,
|
||||
build_mode: std.builtin.Mode,
|
||||
kind: Kind,
|
||||
major_only_filename: ?[]const u8,
|
||||
name_only_filename: ?[]const u8,
|
||||
@@ -84,7 +82,7 @@ initial_memory: ?u64 = null,
|
||||
max_memory: ?u64 = null,
|
||||
shared_memory: bool = false,
|
||||
global_base: ?u64 = null,
|
||||
c_std: Builder.CStd,
|
||||
c_std: std.Build.CStd,
|
||||
override_lib_dir: ?[]const u8,
|
||||
main_pkg_path: ?[]const u8,
|
||||
exec_cmd_args: ?[]const ?[]const u8,
|
||||
@@ -108,7 +106,7 @@ object_src: []const u8,
|
||||
link_objects: ArrayList(LinkObject),
|
||||
include_dirs: ArrayList(IncludeDir),
|
||||
c_macros: ArrayList([]const u8),
|
||||
installed_headers: ArrayList(*std.build.Step),
|
||||
installed_headers: ArrayList(*Step),
|
||||
output_dir: ?[]const u8,
|
||||
is_linking_libc: bool = false,
|
||||
is_linking_libcpp: bool = false,
|
||||
@@ -226,7 +224,7 @@ pub const CSourceFile = struct {
|
||||
source: FileSource,
|
||||
args: []const []const u8,
|
||||
|
||||
pub fn dupe(self: CSourceFile, b: *Builder) CSourceFile {
|
||||
pub fn dupe(self: CSourceFile, b: *std.Build) CSourceFile {
|
||||
return .{
|
||||
.source = self.source.dupe(b),
|
||||
.args = b.dupeStrings(self.args),
|
||||
@@ -236,7 +234,7 @@ pub const CSourceFile = struct {
|
||||
|
||||
pub const LinkObject = union(enum) {
|
||||
static_path: FileSource,
|
||||
other_step: *LibExeObjStep,
|
||||
other_step: *CompileStep,
|
||||
system_lib: SystemLib,
|
||||
assembly_file: FileSource,
|
||||
c_source_file: *CSourceFile,
|
||||
@@ -267,10 +265,20 @@ const FrameworkLinkInfo = struct {
|
||||
pub const IncludeDir = union(enum) {
|
||||
raw_path: []const u8,
|
||||
raw_path_system: []const u8,
|
||||
other_step: *LibExeObjStep,
|
||||
other_step: *CompileStep,
|
||||
config_header_step: *ConfigHeaderStep,
|
||||
};
|
||||
|
||||
pub const Options = struct {
|
||||
name: []const u8,
|
||||
root_source_file: ?FileSource = null,
|
||||
target: CrossTarget,
|
||||
optimize: std.builtin.Mode,
|
||||
kind: Kind,
|
||||
linkage: ?Linkage = null,
|
||||
version: ?std.builtin.Version = null,
|
||||
};
|
||||
|
||||
pub const Kind = enum {
|
||||
exe,
|
||||
lib,
|
||||
@@ -279,11 +287,6 @@ pub const Kind = enum {
|
||||
test_exe,
|
||||
};
|
||||
|
||||
pub const SharedLibKind = union(enum) {
|
||||
versioned: std.builtin.Version,
|
||||
unversioned: void,
|
||||
};
|
||||
|
||||
pub const Linkage = enum { dynamic, static };
|
||||
|
||||
pub const EmitOption = union(enum) {
|
||||
@@ -292,7 +295,7 @@ pub const EmitOption = union(enum) {
|
||||
emit: void,
|
||||
emit_to: []const u8,
|
||||
|
||||
fn getArg(self: @This(), b: *Builder, arg_name: []const u8) ?[]const u8 {
|
||||
fn getArg(self: @This(), b: *std.Build, arg_name: []const u8) ?[]const u8 {
|
||||
return switch (self) {
|
||||
.no_emit => b.fmt("-fno-{s}", .{arg_name}),
|
||||
.default => null,
|
||||
@@ -302,62 +305,29 @@ pub const EmitOption = union(enum) {
|
||||
}
|
||||
};
|
||||
|
||||
pub fn createSharedLibrary(builder: *Builder, name: []const u8, root_src: ?FileSource, kind: SharedLibKind) *LibExeObjStep {
|
||||
return initExtraArgs(builder, name, root_src, .lib, .dynamic, switch (kind) {
|
||||
.versioned => |ver| ver,
|
||||
.unversioned => null,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn createStaticLibrary(builder: *Builder, name: []const u8, root_src: ?FileSource) *LibExeObjStep {
|
||||
return initExtraArgs(builder, name, root_src, .lib, .static, null);
|
||||
}
|
||||
|
||||
pub fn createObject(builder: *Builder, name: []const u8, root_src: ?FileSource) *LibExeObjStep {
|
||||
return initExtraArgs(builder, name, root_src, .obj, null, null);
|
||||
}
|
||||
|
||||
pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?FileSource) *LibExeObjStep {
|
||||
return initExtraArgs(builder, name, root_src, .exe, null, null);
|
||||
}
|
||||
|
||||
pub fn createTest(builder: *Builder, name: []const u8, root_src: FileSource) *LibExeObjStep {
|
||||
return initExtraArgs(builder, name, root_src, .@"test", null, null);
|
||||
}
|
||||
|
||||
pub fn createTestExe(builder: *Builder, name: []const u8, root_src: FileSource) *LibExeObjStep {
|
||||
return initExtraArgs(builder, name, root_src, .test_exe, null, null);
|
||||
}
|
||||
|
||||
fn initExtraArgs(
|
||||
builder: *Builder,
|
||||
name_raw: []const u8,
|
||||
root_src_raw: ?FileSource,
|
||||
kind: Kind,
|
||||
linkage: ?Linkage,
|
||||
ver: ?std.builtin.Version,
|
||||
) *LibExeObjStep {
|
||||
const name = builder.dupe(name_raw);
|
||||
const root_src: ?FileSource = if (root_src_raw) |rsrc| rsrc.dupe(builder) else null;
|
||||
pub fn create(builder: *std.Build, options: Options) *CompileStep {
|
||||
const name = builder.dupe(options.name);
|
||||
const root_src: ?FileSource = if (options.root_source_file) |rsrc| rsrc.dupe(builder) else null;
|
||||
if (mem.indexOf(u8, name, "/") != null or mem.indexOf(u8, name, "\\") != null) {
|
||||
panic("invalid name: '{s}'. It looks like a file path, but it is supposed to be the library or application name.", .{name});
|
||||
}
|
||||
|
||||
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
|
||||
self.* = LibExeObjStep{
|
||||
const self = builder.allocator.create(CompileStep) catch @panic("OOM");
|
||||
self.* = CompileStep{
|
||||
.strip = null,
|
||||
.unwind_tables = null,
|
||||
.builder = builder,
|
||||
.verbose_link = false,
|
||||
.verbose_cc = false,
|
||||
.build_mode = std.builtin.Mode.Debug,
|
||||
.linkage = linkage,
|
||||
.kind = kind,
|
||||
.optimize = options.optimize,
|
||||
.target = options.target,
|
||||
.linkage = options.linkage,
|
||||
.kind = options.kind,
|
||||
.root_src = root_src,
|
||||
.name = name,
|
||||
.frameworks = StringHashMap(FrameworkLinkInfo).init(builder.allocator),
|
||||
.step = Step.init(base_id, name, builder.allocator, make),
|
||||
.version = ver,
|
||||
.version = options.version,
|
||||
.out_filename = undefined,
|
||||
.out_h_filename = builder.fmt("{s}.h", .{name}),
|
||||
.out_lib_filename = undefined,
|
||||
@@ -371,9 +341,9 @@ fn initExtraArgs(
|
||||
.lib_paths = ArrayList([]const u8).init(builder.allocator),
|
||||
.rpaths = ArrayList([]const u8).init(builder.allocator),
|
||||
.framework_dirs = ArrayList([]const u8).init(builder.allocator),
|
||||
.installed_headers = ArrayList(*std.build.Step).init(builder.allocator),
|
||||
.installed_headers = ArrayList(*Step).init(builder.allocator),
|
||||
.object_src = undefined,
|
||||
.c_std = Builder.CStd.C99,
|
||||
.c_std = std.Build.CStd.C99,
|
||||
.override_lib_dir = null,
|
||||
.main_pkg_path = null,
|
||||
.exec_cmd_args = null,
|
||||
@@ -394,17 +364,14 @@ fn initExtraArgs(
|
||||
.output_h_path_source = GeneratedFile{ .step = &self.step },
|
||||
.output_pdb_path_source = GeneratedFile{ .step = &self.step },
|
||||
|
||||
.target_info = undefined, // populated in computeOutFileNames
|
||||
.target_info = NativeTargetInfo.detect(self.target) catch @panic("unhandled error"),
|
||||
};
|
||||
self.computeOutFileNames();
|
||||
if (root_src) |rs| rs.addStepDependencies(&self.step);
|
||||
return self;
|
||||
}
|
||||
|
||||
fn computeOutFileNames(self: *LibExeObjStep) void {
|
||||
self.target_info = NativeTargetInfo.detect(self.target) catch
|
||||
unreachable;
|
||||
|
||||
fn computeOutFileNames(self: *CompileStep) void {
|
||||
const target = self.target_info.target;
|
||||
|
||||
self.out_filename = std.zig.binNameAlloc(self.builder.allocator, .{
|
||||
@@ -420,7 +387,7 @@ fn computeOutFileNames(self: *LibExeObjStep) void {
|
||||
.static => .Static,
|
||||
}) else null,
|
||||
.version = self.version,
|
||||
}) catch unreachable;
|
||||
}) catch @panic("OOM");
|
||||
|
||||
if (self.kind == .lib) {
|
||||
if (self.linkage != null and self.linkage.? == .static) {
|
||||
@@ -457,31 +424,26 @@ fn computeOutFileNames(self: *LibExeObjStep) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setTarget(self: *LibExeObjStep, target: CrossTarget) void {
|
||||
self.target = target;
|
||||
self.computeOutFileNames();
|
||||
}
|
||||
|
||||
pub fn setOutputDir(self: *LibExeObjStep, dir: []const u8) void {
|
||||
pub fn setOutputDir(self: *CompileStep, dir: []const u8) void {
|
||||
self.output_dir = self.builder.dupePath(dir);
|
||||
}
|
||||
|
||||
pub fn install(self: *LibExeObjStep) void {
|
||||
pub fn install(self: *CompileStep) void {
|
||||
self.builder.installArtifact(self);
|
||||
}
|
||||
|
||||
pub fn installRaw(self: *LibExeObjStep, dest_filename: []const u8, options: InstallRawStep.CreateOptions) *InstallRawStep {
|
||||
pub fn installRaw(self: *CompileStep, dest_filename: []const u8, options: InstallRawStep.CreateOptions) *InstallRawStep {
|
||||
return self.builder.installRaw(self, dest_filename, options);
|
||||
}
|
||||
|
||||
pub fn installHeader(a: *LibExeObjStep, src_path: []const u8, dest_rel_path: []const u8) void {
|
||||
pub fn installHeader(a: *CompileStep, src_path: []const u8, dest_rel_path: []const u8) void {
|
||||
const install_file = a.builder.addInstallHeaderFile(src_path, dest_rel_path);
|
||||
a.builder.getInstallStep().dependOn(&install_file.step);
|
||||
a.installed_headers.append(&install_file.step) catch unreachable;
|
||||
a.installed_headers.append(&install_file.step) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn installHeadersDirectory(
|
||||
a: *LibExeObjStep,
|
||||
a: *CompileStep,
|
||||
src_dir_path: []const u8,
|
||||
dest_rel_path: []const u8,
|
||||
) void {
|
||||
@@ -493,15 +455,15 @@ pub fn installHeadersDirectory(
|
||||
}
|
||||
|
||||
pub fn installHeadersDirectoryOptions(
|
||||
a: *LibExeObjStep,
|
||||
options: std.build.InstallDirStep.Options,
|
||||
a: *CompileStep,
|
||||
options: std.Build.InstallDirStep.Options,
|
||||
) void {
|
||||
const install_dir = a.builder.addInstallDirectory(options);
|
||||
a.builder.getInstallStep().dependOn(&install_dir.step);
|
||||
a.installed_headers.append(&install_dir.step) catch unreachable;
|
||||
a.installed_headers.append(&install_dir.step) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn installLibraryHeaders(a: *LibExeObjStep, l: *LibExeObjStep) void {
|
||||
pub fn installLibraryHeaders(a: *CompileStep, l: *CompileStep) void {
|
||||
assert(l.kind == .lib);
|
||||
const install_step = a.builder.getInstallStep();
|
||||
// Copy each element from installed_headers, modifying the builder
|
||||
@@ -510,7 +472,7 @@ pub fn installLibraryHeaders(a: *LibExeObjStep, l: *LibExeObjStep) void {
|
||||
const step_copy = switch (step.id) {
|
||||
inline .install_file, .install_dir => |id| blk: {
|
||||
const T = id.Type();
|
||||
const ptr = a.builder.allocator.create(T) catch unreachable;
|
||||
const ptr = a.builder.allocator.create(T) catch @panic("OOM");
|
||||
ptr.* = step.cast(T).?.*;
|
||||
ptr.override_source_builder = ptr.builder;
|
||||
ptr.builder = a.builder;
|
||||
@@ -518,15 +480,15 @@ pub fn installLibraryHeaders(a: *LibExeObjStep, l: *LibExeObjStep) void {
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
a.installed_headers.append(step_copy) catch unreachable;
|
||||
a.installed_headers.append(step_copy) catch @panic("OOM");
|
||||
install_step.dependOn(step_copy);
|
||||
}
|
||||
a.installed_headers.appendSlice(l.installed_headers.items) catch unreachable;
|
||||
a.installed_headers.appendSlice(l.installed_headers.items) catch @panic("OOM");
|
||||
}
|
||||
|
||||
/// Creates a `RunStep` with an executable built with `addExecutable`.
|
||||
/// Add command line arguments with `addArg`.
|
||||
pub fn run(exe: *LibExeObjStep) *RunStep {
|
||||
pub fn run(exe: *CompileStep) *RunStep {
|
||||
assert(exe.kind == .exe or exe.kind == .test_exe);
|
||||
|
||||
// It doesn't have to be native. We catch that if you actually try to run it.
|
||||
@@ -550,7 +512,7 @@ pub fn run(exe: *LibExeObjStep) *RunStep {
|
||||
/// Allows running foreign binaries through emulation platforms such as Qemu or Rosetta.
|
||||
/// When a binary cannot be ran through emulation or the option is disabled, a warning
|
||||
/// will be printed and the binary will *NOT* be ran.
|
||||
pub fn runEmulatable(exe: *LibExeObjStep) *EmulatableRunStep {
|
||||
pub fn runEmulatable(exe: *CompileStep) *EmulatableRunStep {
|
||||
assert(exe.kind == .exe or exe.kind == .test_exe);
|
||||
|
||||
const run_step = EmulatableRunStep.create(exe.builder, exe.builder.fmt("run {s}", .{exe.step.name}), exe);
|
||||
@@ -560,33 +522,33 @@ pub fn runEmulatable(exe: *LibExeObjStep) *EmulatableRunStep {
|
||||
return run_step;
|
||||
}
|
||||
|
||||
pub fn checkObject(self: *LibExeObjStep, obj_format: std.Target.ObjectFormat) *CheckObjectStep {
|
||||
pub fn checkObject(self: *CompileStep, obj_format: std.Target.ObjectFormat) *CheckObjectStep {
|
||||
return CheckObjectStep.create(self.builder, self.getOutputSource(), obj_format);
|
||||
}
|
||||
|
||||
pub fn setLinkerScriptPath(self: *LibExeObjStep, source: FileSource) void {
|
||||
pub fn setLinkerScriptPath(self: *CompileStep, source: FileSource) void {
|
||||
self.linker_script = source.dupe(self.builder);
|
||||
source.addStepDependencies(&self.step);
|
||||
}
|
||||
|
||||
pub fn linkFramework(self: *LibExeObjStep, framework_name: []const u8) void {
|
||||
self.frameworks.put(self.builder.dupe(framework_name), .{}) catch unreachable;
|
||||
pub fn linkFramework(self: *CompileStep, framework_name: []const u8) void {
|
||||
self.frameworks.put(self.builder.dupe(framework_name), .{}) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn linkFrameworkNeeded(self: *LibExeObjStep, framework_name: []const u8) void {
|
||||
pub fn linkFrameworkNeeded(self: *CompileStep, framework_name: []const u8) void {
|
||||
self.frameworks.put(self.builder.dupe(framework_name), .{
|
||||
.needed = true,
|
||||
}) catch unreachable;
|
||||
}) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn linkFrameworkWeak(self: *LibExeObjStep, framework_name: []const u8) void {
|
||||
pub fn linkFrameworkWeak(self: *CompileStep, framework_name: []const u8) void {
|
||||
self.frameworks.put(self.builder.dupe(framework_name), .{
|
||||
.weak = true,
|
||||
}) catch unreachable;
|
||||
}) catch @panic("OOM");
|
||||
}
|
||||
|
||||
/// Returns whether the library, executable, or object depends on a particular system library.
|
||||
pub fn dependsOnSystemLibrary(self: LibExeObjStep, name: []const u8) bool {
|
||||
pub fn dependsOnSystemLibrary(self: CompileStep, name: []const u8) bool {
|
||||
if (isLibCLibrary(name)) {
|
||||
return self.is_linking_libc;
|
||||
}
|
||||
@@ -602,49 +564,49 @@ pub fn dependsOnSystemLibrary(self: LibExeObjStep, name: []const u8) bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn linkLibrary(self: *LibExeObjStep, lib: *LibExeObjStep) void {
|
||||
pub fn linkLibrary(self: *CompileStep, lib: *CompileStep) void {
|
||||
assert(lib.kind == .lib);
|
||||
self.linkLibraryOrObject(lib);
|
||||
}
|
||||
|
||||
pub fn isDynamicLibrary(self: *LibExeObjStep) bool {
|
||||
pub fn isDynamicLibrary(self: *CompileStep) bool {
|
||||
return self.kind == .lib and self.linkage == Linkage.dynamic;
|
||||
}
|
||||
|
||||
pub fn isStaticLibrary(self: *LibExeObjStep) bool {
|
||||
pub fn isStaticLibrary(self: *CompileStep) bool {
|
||||
return self.kind == .lib and self.linkage != Linkage.dynamic;
|
||||
}
|
||||
|
||||
pub fn producesPdbFile(self: *LibExeObjStep) bool {
|
||||
pub fn producesPdbFile(self: *CompileStep) bool {
|
||||
if (!self.target.isWindows() and !self.target.isUefi()) return false;
|
||||
if (self.target.getObjectFormat() == .c) return false;
|
||||
if (self.strip == true) return false;
|
||||
return self.isDynamicLibrary() or self.kind == .exe or self.kind == .test_exe;
|
||||
}
|
||||
|
||||
pub fn linkLibC(self: *LibExeObjStep) void {
|
||||
pub fn linkLibC(self: *CompileStep) void {
|
||||
self.is_linking_libc = true;
|
||||
}
|
||||
|
||||
pub fn linkLibCpp(self: *LibExeObjStep) void {
|
||||
pub fn linkLibCpp(self: *CompileStep) void {
|
||||
self.is_linking_libcpp = true;
|
||||
}
|
||||
|
||||
/// If the value is omitted, it is set to 1.
|
||||
/// `name` and `value` need not live longer than the function call.
|
||||
pub fn defineCMacro(self: *LibExeObjStep, name: []const u8, value: ?[]const u8) void {
|
||||
const macro = std.build.constructCMacro(self.builder.allocator, name, value);
|
||||
self.c_macros.append(macro) catch unreachable;
|
||||
pub fn defineCMacro(self: *CompileStep, name: []const u8, value: ?[]const u8) void {
|
||||
const macro = std.Build.constructCMacro(self.builder.allocator, name, value);
|
||||
self.c_macros.append(macro) catch @panic("OOM");
|
||||
}
|
||||
|
||||
/// name_and_value looks like [name]=[value]. If the value is omitted, it is set to 1.
|
||||
pub fn defineCMacroRaw(self: *LibExeObjStep, name_and_value: []const u8) void {
|
||||
self.c_macros.append(self.builder.dupe(name_and_value)) catch unreachable;
|
||||
pub fn defineCMacroRaw(self: *CompileStep, name_and_value: []const u8) void {
|
||||
self.c_macros.append(self.builder.dupe(name_and_value)) catch @panic("OOM");
|
||||
}
|
||||
|
||||
/// This one has no integration with anything, it just puts -lname on the command line.
|
||||
/// Prefer to use `linkSystemLibrary` instead.
|
||||
pub fn linkSystemLibraryName(self: *LibExeObjStep, name: []const u8) void {
|
||||
pub fn linkSystemLibraryName(self: *CompileStep, name: []const u8) void {
|
||||
self.link_objects.append(.{
|
||||
.system_lib = .{
|
||||
.name = self.builder.dupe(name),
|
||||
@@ -652,12 +614,12 @@ pub fn linkSystemLibraryName(self: *LibExeObjStep, name: []const u8) void {
|
||||
.weak = false,
|
||||
.use_pkg_config = .no,
|
||||
},
|
||||
}) catch unreachable;
|
||||
}) catch @panic("OOM");
|
||||
}
|
||||
|
||||
/// This one has no integration with anything, it just puts -needed-lname on the command line.
|
||||
/// Prefer to use `linkSystemLibraryNeeded` instead.
|
||||
pub fn linkSystemLibraryNeededName(self: *LibExeObjStep, name: []const u8) void {
|
||||
pub fn linkSystemLibraryNeededName(self: *CompileStep, name: []const u8) void {
|
||||
self.link_objects.append(.{
|
||||
.system_lib = .{
|
||||
.name = self.builder.dupe(name),
|
||||
@@ -665,12 +627,12 @@ pub fn linkSystemLibraryNeededName(self: *LibExeObjStep, name: []const u8) void
|
||||
.weak = false,
|
||||
.use_pkg_config = .no,
|
||||
},
|
||||
}) catch unreachable;
|
||||
}) catch @panic("OOM");
|
||||
}
|
||||
|
||||
/// Darwin-only. This one has no integration with anything, it just puts -weak-lname on the
|
||||
/// command line. Prefer to use `linkSystemLibraryWeak` instead.
|
||||
pub fn linkSystemLibraryWeakName(self: *LibExeObjStep, name: []const u8) void {
|
||||
pub fn linkSystemLibraryWeakName(self: *CompileStep, name: []const u8) void {
|
||||
self.link_objects.append(.{
|
||||
.system_lib = .{
|
||||
.name = self.builder.dupe(name),
|
||||
@@ -678,12 +640,12 @@ pub fn linkSystemLibraryWeakName(self: *LibExeObjStep, name: []const u8) void {
|
||||
.weak = true,
|
||||
.use_pkg_config = .no,
|
||||
},
|
||||
}) catch unreachable;
|
||||
}) catch @panic("OOM");
|
||||
}
|
||||
|
||||
/// This links against a system library, exclusively using pkg-config to find the library.
|
||||
/// Prefer to use `linkSystemLibrary` instead.
|
||||
pub fn linkSystemLibraryPkgConfigOnly(self: *LibExeObjStep, lib_name: []const u8) void {
|
||||
pub fn linkSystemLibraryPkgConfigOnly(self: *CompileStep, lib_name: []const u8) void {
|
||||
self.link_objects.append(.{
|
||||
.system_lib = .{
|
||||
.name = self.builder.dupe(lib_name),
|
||||
@@ -691,12 +653,12 @@ pub fn linkSystemLibraryPkgConfigOnly(self: *LibExeObjStep, lib_name: []const u8
|
||||
.weak = false,
|
||||
.use_pkg_config = .force,
|
||||
},
|
||||
}) catch unreachable;
|
||||
}) catch @panic("OOM");
|
||||
}
|
||||
|
||||
/// This links against a system library, exclusively using pkg-config to find the library.
|
||||
/// Prefer to use `linkSystemLibraryNeeded` instead.
|
||||
pub fn linkSystemLibraryNeededPkgConfigOnly(self: *LibExeObjStep, lib_name: []const u8) void {
|
||||
pub fn linkSystemLibraryNeededPkgConfigOnly(self: *CompileStep, lib_name: []const u8) void {
|
||||
self.link_objects.append(.{
|
||||
.system_lib = .{
|
||||
.name = self.builder.dupe(lib_name),
|
||||
@@ -704,12 +666,12 @@ pub fn linkSystemLibraryNeededPkgConfigOnly(self: *LibExeObjStep, lib_name: []co
|
||||
.weak = false,
|
||||
.use_pkg_config = .force,
|
||||
},
|
||||
}) catch unreachable;
|
||||
}) catch @panic("OOM");
|
||||
}
|
||||
|
||||
/// Run pkg-config for the given library name and parse the output, returning the arguments
|
||||
/// that should be passed to zig to link the given library.
|
||||
pub fn runPkgConfig(self: *LibExeObjStep, lib_name: []const u8) ![]const []const u8 {
|
||||
pub fn runPkgConfig(self: *CompileStep, lib_name: []const u8) ![]const []const u8 {
|
||||
const pkg_name = match: {
|
||||
// First we have to map the library name to pkg config name. Unfortunately,
|
||||
// there are several examples where this is not straightforward:
|
||||
@@ -803,19 +765,19 @@ pub fn runPkgConfig(self: *LibExeObjStep, lib_name: []const u8) ![]const []const
|
||||
return zig_args.toOwnedSlice();
|
||||
}
|
||||
|
||||
pub fn linkSystemLibrary(self: *LibExeObjStep, name: []const u8) void {
|
||||
pub fn linkSystemLibrary(self: *CompileStep, name: []const u8) void {
|
||||
self.linkSystemLibraryInner(name, .{});
|
||||
}
|
||||
|
||||
pub fn linkSystemLibraryNeeded(self: *LibExeObjStep, name: []const u8) void {
|
||||
pub fn linkSystemLibraryNeeded(self: *CompileStep, name: []const u8) void {
|
||||
self.linkSystemLibraryInner(name, .{ .needed = true });
|
||||
}
|
||||
|
||||
pub fn linkSystemLibraryWeak(self: *LibExeObjStep, name: []const u8) void {
|
||||
pub fn linkSystemLibraryWeak(self: *CompileStep, name: []const u8) void {
|
||||
self.linkSystemLibraryInner(name, .{ .weak = true });
|
||||
}
|
||||
|
||||
fn linkSystemLibraryInner(self: *LibExeObjStep, name: []const u8, opts: struct {
|
||||
fn linkSystemLibraryInner(self: *CompileStep, name: []const u8, opts: struct {
|
||||
needed: bool = false,
|
||||
weak: bool = false,
|
||||
}) void {
|
||||
@@ -835,27 +797,27 @@ fn linkSystemLibraryInner(self: *LibExeObjStep, name: []const u8, opts: struct {
|
||||
.weak = opts.weak,
|
||||
.use_pkg_config = .yes,
|
||||
},
|
||||
}) catch unreachable;
|
||||
}) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn setNamePrefix(self: *LibExeObjStep, text: []const u8) void {
|
||||
pub fn setNamePrefix(self: *CompileStep, text: []const u8) void {
|
||||
assert(self.kind == .@"test" or self.kind == .test_exe);
|
||||
self.name_prefix = self.builder.dupe(text);
|
||||
}
|
||||
|
||||
pub fn setFilter(self: *LibExeObjStep, text: ?[]const u8) void {
|
||||
pub fn setFilter(self: *CompileStep, text: ?[]const u8) void {
|
||||
assert(self.kind == .@"test" or self.kind == .test_exe);
|
||||
self.filter = if (text) |t| self.builder.dupe(t) else null;
|
||||
}
|
||||
|
||||
pub fn setTestRunner(self: *LibExeObjStep, path: ?[]const u8) void {
|
||||
pub fn setTestRunner(self: *CompileStep, path: ?[]const u8) void {
|
||||
assert(self.kind == .@"test" or self.kind == .test_exe);
|
||||
self.test_runner = if (path) |p| self.builder.dupePath(p) else null;
|
||||
}
|
||||
|
||||
/// Handy when you have many C/C++ source files and want them all to have the same flags.
|
||||
pub fn addCSourceFiles(self: *LibExeObjStep, files: []const []const u8, flags: []const []const u8) void {
|
||||
const c_source_files = self.builder.allocator.create(CSourceFiles) catch unreachable;
|
||||
pub fn addCSourceFiles(self: *CompileStep, files: []const []const u8, flags: []const []const u8) void {
|
||||
const c_source_files = self.builder.allocator.create(CSourceFiles) catch @panic("OOM");
|
||||
|
||||
const files_copy = self.builder.dupeStrings(files);
|
||||
const flags_copy = self.builder.dupeStrings(flags);
|
||||
@@ -864,96 +826,92 @@ pub fn addCSourceFiles(self: *LibExeObjStep, files: []const []const u8, flags: [
|
||||
.files = files_copy,
|
||||
.flags = flags_copy,
|
||||
};
|
||||
self.link_objects.append(.{ .c_source_files = c_source_files }) catch unreachable;
|
||||
self.link_objects.append(.{ .c_source_files = c_source_files }) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn addCSourceFile(self: *LibExeObjStep, file: []const u8, flags: []const []const u8) void {
|
||||
pub fn addCSourceFile(self: *CompileStep, file: []const u8, flags: []const []const u8) void {
|
||||
self.addCSourceFileSource(.{
|
||||
.args = flags,
|
||||
.source = .{ .path = file },
|
||||
});
|
||||
}
|
||||
|
||||
pub fn addCSourceFileSource(self: *LibExeObjStep, source: CSourceFile) void {
|
||||
const c_source_file = self.builder.allocator.create(CSourceFile) catch unreachable;
|
||||
pub fn addCSourceFileSource(self: *CompileStep, source: CSourceFile) void {
|
||||
const c_source_file = self.builder.allocator.create(CSourceFile) catch @panic("OOM");
|
||||
c_source_file.* = source.dupe(self.builder);
|
||||
self.link_objects.append(.{ .c_source_file = c_source_file }) catch unreachable;
|
||||
self.link_objects.append(.{ .c_source_file = c_source_file }) catch @panic("OOM");
|
||||
source.source.addStepDependencies(&self.step);
|
||||
}
|
||||
|
||||
pub fn setVerboseLink(self: *LibExeObjStep, value: bool) void {
|
||||
pub fn setVerboseLink(self: *CompileStep, value: bool) void {
|
||||
self.verbose_link = value;
|
||||
}
|
||||
|
||||
pub fn setVerboseCC(self: *LibExeObjStep, value: bool) void {
|
||||
pub fn setVerboseCC(self: *CompileStep, value: bool) void {
|
||||
self.verbose_cc = value;
|
||||
}
|
||||
|
||||
pub fn setBuildMode(self: *LibExeObjStep, mode: std.builtin.Mode) void {
|
||||
self.build_mode = mode;
|
||||
}
|
||||
|
||||
pub fn overrideZigLibDir(self: *LibExeObjStep, dir_path: []const u8) void {
|
||||
pub fn overrideZigLibDir(self: *CompileStep, dir_path: []const u8) void {
|
||||
self.override_lib_dir = self.builder.dupePath(dir_path);
|
||||
}
|
||||
|
||||
pub fn setMainPkgPath(self: *LibExeObjStep, dir_path: []const u8) void {
|
||||
pub fn setMainPkgPath(self: *CompileStep, dir_path: []const u8) void {
|
||||
self.main_pkg_path = self.builder.dupePath(dir_path);
|
||||
}
|
||||
|
||||
pub fn setLibCFile(self: *LibExeObjStep, libc_file: ?FileSource) void {
|
||||
pub fn setLibCFile(self: *CompileStep, libc_file: ?FileSource) void {
|
||||
self.libc_file = if (libc_file) |f| f.dupe(self.builder) else null;
|
||||
}
|
||||
|
||||
/// Returns the generated executable, library or object file.
|
||||
/// To run an executable built with zig build, use `run`, or create an install step and invoke it.
|
||||
pub fn getOutputSource(self: *LibExeObjStep) FileSource {
|
||||
pub fn getOutputSource(self: *CompileStep) FileSource {
|
||||
return FileSource{ .generated = &self.output_path_source };
|
||||
}
|
||||
|
||||
/// Returns the generated import library. This function can only be called for libraries.
|
||||
pub fn getOutputLibSource(self: *LibExeObjStep) FileSource {
|
||||
pub fn getOutputLibSource(self: *CompileStep) FileSource {
|
||||
assert(self.kind == .lib);
|
||||
return FileSource{ .generated = &self.output_lib_path_source };
|
||||
}
|
||||
|
||||
/// Returns the generated header file.
|
||||
/// This function can only be called for libraries or object files which have `emit_h` set.
|
||||
pub fn getOutputHSource(self: *LibExeObjStep) FileSource {
|
||||
pub fn getOutputHSource(self: *CompileStep) FileSource {
|
||||
assert(self.kind != .exe and self.kind != .test_exe and self.kind != .@"test");
|
||||
assert(self.emit_h);
|
||||
return FileSource{ .generated = &self.output_h_path_source };
|
||||
}
|
||||
|
||||
/// Returns the generated PDB file. This function can only be called for Windows and UEFI.
|
||||
pub fn getOutputPdbSource(self: *LibExeObjStep) FileSource {
|
||||
pub fn getOutputPdbSource(self: *CompileStep) FileSource {
|
||||
// TODO: Is this right? Isn't PDB for *any* PE/COFF file?
|
||||
assert(self.target.isWindows() or self.target.isUefi());
|
||||
return FileSource{ .generated = &self.output_pdb_path_source };
|
||||
}
|
||||
|
||||
pub fn addAssemblyFile(self: *LibExeObjStep, path: []const u8) void {
|
||||
pub fn addAssemblyFile(self: *CompileStep, path: []const u8) void {
|
||||
self.link_objects.append(.{
|
||||
.assembly_file = .{ .path = self.builder.dupe(path) },
|
||||
}) catch unreachable;
|
||||
}) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn addAssemblyFileSource(self: *LibExeObjStep, source: FileSource) void {
|
||||
pub fn addAssemblyFileSource(self: *CompileStep, source: FileSource) void {
|
||||
const source_duped = source.dupe(self.builder);
|
||||
self.link_objects.append(.{ .assembly_file = source_duped }) catch unreachable;
|
||||
self.link_objects.append(.{ .assembly_file = source_duped }) catch @panic("OOM");
|
||||
source_duped.addStepDependencies(&self.step);
|
||||
}
|
||||
|
||||
pub fn addObjectFile(self: *LibExeObjStep, source_file: []const u8) void {
|
||||
pub fn addObjectFile(self: *CompileStep, source_file: []const u8) void {
|
||||
self.addObjectFileSource(.{ .path = source_file });
|
||||
}
|
||||
|
||||
pub fn addObjectFileSource(self: *LibExeObjStep, source: FileSource) void {
|
||||
self.link_objects.append(.{ .static_path = source.dupe(self.builder) }) catch unreachable;
|
||||
pub fn addObjectFileSource(self: *CompileStep, source: FileSource) void {
|
||||
self.link_objects.append(.{ .static_path = source.dupe(self.builder) }) catch @panic("OOM");
|
||||
source.addStepDependencies(&self.step);
|
||||
}
|
||||
|
||||
pub fn addObject(self: *LibExeObjStep, obj: *LibExeObjStep) void {
|
||||
pub fn addObject(self: *CompileStep, obj: *CompileStep) void {
|
||||
assert(obj.kind == .obj);
|
||||
self.linkLibraryOrObject(obj);
|
||||
}
|
||||
@@ -963,41 +921,41 @@ pub const addIncludeDir = @compileError("deprecated; use addIncludePath");
|
||||
pub const addLibPath = @compileError("deprecated, use addLibraryPath");
|
||||
pub const addFrameworkDir = @compileError("deprecated, use addFrameworkPath");
|
||||
|
||||
pub fn addSystemIncludePath(self: *LibExeObjStep, path: []const u8) void {
|
||||
self.include_dirs.append(IncludeDir{ .raw_path_system = self.builder.dupe(path) }) catch unreachable;
|
||||
pub fn addSystemIncludePath(self: *CompileStep, path: []const u8) void {
|
||||
self.include_dirs.append(IncludeDir{ .raw_path_system = self.builder.dupe(path) }) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn addIncludePath(self: *LibExeObjStep, path: []const u8) void {
|
||||
self.include_dirs.append(IncludeDir{ .raw_path = self.builder.dupe(path) }) catch unreachable;
|
||||
pub fn addIncludePath(self: *CompileStep, path: []const u8) void {
|
||||
self.include_dirs.append(IncludeDir{ .raw_path = self.builder.dupe(path) }) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn addConfigHeader(self: *LibExeObjStep, config_header: *ConfigHeaderStep) void {
|
||||
pub fn addConfigHeader(self: *CompileStep, config_header: *ConfigHeaderStep) void {
|
||||
self.step.dependOn(&config_header.step);
|
||||
self.include_dirs.append(.{ .config_header_step = config_header }) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn addLibraryPath(self: *LibExeObjStep, path: []const u8) void {
|
||||
self.lib_paths.append(self.builder.dupe(path)) catch unreachable;
|
||||
pub fn addLibraryPath(self: *CompileStep, path: []const u8) void {
|
||||
self.lib_paths.append(self.builder.dupe(path)) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn addRPath(self: *LibExeObjStep, path: []const u8) void {
|
||||
self.rpaths.append(self.builder.dupe(path)) catch unreachable;
|
||||
pub fn addRPath(self: *CompileStep, path: []const u8) void {
|
||||
self.rpaths.append(self.builder.dupe(path)) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn addFrameworkPath(self: *LibExeObjStep, dir_path: []const u8) void {
|
||||
self.framework_dirs.append(self.builder.dupe(dir_path)) catch unreachable;
|
||||
pub fn addFrameworkPath(self: *CompileStep, dir_path: []const u8) void {
|
||||
self.framework_dirs.append(self.builder.dupe(dir_path)) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn addPackage(self: *LibExeObjStep, package: Pkg) void {
|
||||
self.packages.append(self.builder.dupePkg(package)) catch unreachable;
|
||||
pub fn addPackage(self: *CompileStep, package: Pkg) void {
|
||||
self.packages.append(self.builder.dupePkg(package)) catch @panic("OOM");
|
||||
self.addRecursiveBuildDeps(package);
|
||||
}
|
||||
|
||||
pub fn addOptions(self: *LibExeObjStep, package_name: []const u8, options: *OptionsStep) void {
|
||||
pub fn addOptions(self: *CompileStep, package_name: []const u8, options: *OptionsStep) void {
|
||||
self.addPackage(options.getPackage(package_name));
|
||||
}
|
||||
|
||||
fn addRecursiveBuildDeps(self: *LibExeObjStep, package: Pkg) void {
|
||||
fn addRecursiveBuildDeps(self: *CompileStep, package: Pkg) void {
|
||||
package.source.addStepDependencies(&self.step);
|
||||
if (package.dependencies) |deps| {
|
||||
for (deps) |dep| {
|
||||
@@ -1006,7 +964,7 @@ fn addRecursiveBuildDeps(self: *LibExeObjStep, package: Pkg) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addPackagePath(self: *LibExeObjStep, name: []const u8, pkg_index_path: []const u8) void {
|
||||
pub fn addPackagePath(self: *CompileStep, name: []const u8, pkg_index_path: []const u8) void {
|
||||
self.addPackage(Pkg{
|
||||
.name = self.builder.dupe(name),
|
||||
.source = .{ .path = self.builder.dupe(pkg_index_path) },
|
||||
@@ -1015,7 +973,7 @@ pub fn addPackagePath(self: *LibExeObjStep, name: []const u8, pkg_index_path: []
|
||||
|
||||
/// If Vcpkg was found on the system, it will be added to include and lib
|
||||
/// paths for the specified target.
|
||||
pub fn addVcpkgPaths(self: *LibExeObjStep, linkage: LibExeObjStep.Linkage) !void {
|
||||
pub fn addVcpkgPaths(self: *CompileStep, linkage: CompileStep.Linkage) !void {
|
||||
// Ideally in the Unattempted case we would call the function recursively
|
||||
// after findVcpkgRoot and have only one switch statement, but the compiler
|
||||
// cannot resolve the error set.
|
||||
@@ -1050,22 +1008,22 @@ pub fn addVcpkgPaths(self: *LibExeObjStep, linkage: LibExeObjStep.Linkage) !void
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setExecCmd(self: *LibExeObjStep, args: []const ?[]const u8) void {
|
||||
pub fn setExecCmd(self: *CompileStep, args: []const ?[]const u8) void {
|
||||
assert(self.kind == .@"test");
|
||||
const duped_args = self.builder.allocator.alloc(?[]u8, args.len) catch unreachable;
|
||||
const duped_args = self.builder.allocator.alloc(?[]u8, args.len) catch @panic("OOM");
|
||||
for (args) |arg, i| {
|
||||
duped_args[i] = if (arg) |a| self.builder.dupe(a) else null;
|
||||
}
|
||||
self.exec_cmd_args = duped_args;
|
||||
}
|
||||
|
||||
fn linkLibraryOrObject(self: *LibExeObjStep, other: *LibExeObjStep) void {
|
||||
fn linkLibraryOrObject(self: *CompileStep, other: *CompileStep) void {
|
||||
self.step.dependOn(&other.step);
|
||||
self.link_objects.append(.{ .other_step = other }) catch unreachable;
|
||||
self.include_dirs.append(.{ .other_step = other }) catch unreachable;
|
||||
self.link_objects.append(.{ .other_step = other }) catch @panic("OOM");
|
||||
self.include_dirs.append(.{ .other_step = other }) catch @panic("OOM");
|
||||
}
|
||||
|
||||
fn makePackageCmd(self: *LibExeObjStep, pkg: Pkg, zig_args: *ArrayList([]const u8)) error{OutOfMemory}!void {
|
||||
fn makePackageCmd(self: *CompileStep, pkg: Pkg, zig_args: *ArrayList([]const u8)) error{OutOfMemory}!void {
|
||||
const builder = self.builder;
|
||||
|
||||
try zig_args.append("--pkg-begin");
|
||||
@@ -1082,7 +1040,7 @@ fn makePackageCmd(self: *LibExeObjStep, pkg: Pkg, zig_args: *ArrayList([]const u
|
||||
}
|
||||
|
||||
fn make(step: *Step) !void {
|
||||
const self = @fieldParentPtr(LibExeObjStep, "step", step);
|
||||
const self = @fieldParentPtr(CompileStep, "step", step);
|
||||
const builder = self.builder;
|
||||
|
||||
if (self.root_src == null and self.link_objects.items.len == 0) {
|
||||
@@ -1093,7 +1051,7 @@ fn make(step: *Step) !void {
|
||||
var zig_args = ArrayList([]const u8).init(builder.allocator);
|
||||
defer zig_args.deinit();
|
||||
|
||||
zig_args.append(builder.zig_exe) catch unreachable;
|
||||
try zig_args.append(builder.zig_exe);
|
||||
|
||||
const cmd = switch (self.kind) {
|
||||
.lib => "build-lib",
|
||||
@@ -1102,7 +1060,7 @@ fn make(step: *Step) !void {
|
||||
.@"test" => "test",
|
||||
.test_exe => "test",
|
||||
};
|
||||
zig_args.append(cmd) catch unreachable;
|
||||
try zig_args.append(cmd);
|
||||
|
||||
if (builder.color != .auto) {
|
||||
try zig_args.append("--color");
|
||||
@@ -1307,12 +1265,12 @@ fn make(step: *Step) !void {
|
||||
try zig_args.append("--debug-compile-errors");
|
||||
}
|
||||
|
||||
if (builder.verbose_cimport) zig_args.append("--verbose-cimport") catch unreachable;
|
||||
if (builder.verbose_air) zig_args.append("--verbose-air") catch unreachable;
|
||||
if (builder.verbose_llvm_ir) zig_args.append("--verbose-llvm-ir") catch unreachable;
|
||||
if (builder.verbose_link or self.verbose_link) zig_args.append("--verbose-link") catch unreachable;
|
||||
if (builder.verbose_cc or self.verbose_cc) zig_args.append("--verbose-cc") catch unreachable;
|
||||
if (builder.verbose_llvm_cpu_features) zig_args.append("--verbose-llvm-cpu-features") catch unreachable;
|
||||
if (builder.verbose_cimport) try zig_args.append("--verbose-cimport");
|
||||
if (builder.verbose_air) try zig_args.append("--verbose-air");
|
||||
if (builder.verbose_llvm_ir) try zig_args.append("--verbose-llvm-ir");
|
||||
if (builder.verbose_link or self.verbose_link) try zig_args.append("--verbose-link");
|
||||
if (builder.verbose_cc or self.verbose_cc) try zig_args.append("--verbose-cc");
|
||||
if (builder.verbose_llvm_cpu_features) try zig_args.append("--verbose-llvm-cpu-features");
|
||||
|
||||
if (self.emit_analysis.getArg(builder, "emit-analysis")) |arg| try zig_args.append(arg);
|
||||
if (self.emit_asm.getArg(builder, "emit-asm")) |arg| try zig_args.append(arg);
|
||||
@@ -1376,9 +1334,9 @@ fn make(step: *Step) !void {
|
||||
try zig_args.append(libc_file);
|
||||
}
|
||||
|
||||
switch (self.build_mode) {
|
||||
switch (self.optimize) {
|
||||
.Debug => {}, // Skip since it's the default.
|
||||
else => zig_args.append(builder.fmt("-O{s}", .{@tagName(self.build_mode)})) catch unreachable,
|
||||
else => try zig_args.append(builder.fmt("-O{s}", .{@tagName(self.optimize)})),
|
||||
}
|
||||
|
||||
try zig_args.append("--cache-dir");
|
||||
@@ -1387,8 +1345,8 @@ fn make(step: *Step) !void {
|
||||
try zig_args.append("--global-cache-dir");
|
||||
try zig_args.append(builder.pathFromRoot(builder.global_cache_root));
|
||||
|
||||
zig_args.append("--name") catch unreachable;
|
||||
zig_args.append(self.name) catch unreachable;
|
||||
try zig_args.append("--name");
|
||||
try zig_args.append(self.name);
|
||||
|
||||
if (self.linkage) |some| switch (some) {
|
||||
.dynamic => try zig_args.append("-dynamic"),
|
||||
@@ -1396,8 +1354,8 @@ fn make(step: *Step) !void {
|
||||
};
|
||||
if (self.kind == .lib and self.linkage != null and self.linkage.? == .dynamic) {
|
||||
if (self.version) |version| {
|
||||
zig_args.append("--version") catch unreachable;
|
||||
zig_args.append(builder.fmt("{}", .{version})) catch unreachable;
|
||||
try zig_args.append("--version");
|
||||
try zig_args.append(builder.fmt("{}", .{version}));
|
||||
}
|
||||
|
||||
if (self.target.isDarwin()) {
|
||||
@@ -1495,37 +1453,10 @@ fn make(step: *Step) !void {
|
||||
}
|
||||
|
||||
if (!self.target.isNative()) {
|
||||
try zig_args.append("-target");
|
||||
try zig_args.append(try self.target.zigTriple(builder.allocator));
|
||||
|
||||
// TODO this logic can disappear if cpu model + features becomes part of the target triple
|
||||
const cross = self.target.toTarget();
|
||||
const all_features = cross.cpu.arch.allFeaturesList();
|
||||
var populated_cpu_features = cross.cpu.model.features;
|
||||
populated_cpu_features.populateDependencies(all_features);
|
||||
|
||||
if (populated_cpu_features.eql(cross.cpu.features)) {
|
||||
// The CPU name alone is sufficient.
|
||||
try zig_args.append("-mcpu");
|
||||
try zig_args.append(cross.cpu.model.name);
|
||||
} else {
|
||||
var mcpu_buffer = ArrayList(u8).init(builder.allocator);
|
||||
|
||||
try mcpu_buffer.writer().print("-mcpu={s}", .{cross.cpu.model.name});
|
||||
|
||||
for (all_features) |feature, i_usize| {
|
||||
const i = @intCast(std.Target.Cpu.Feature.Set.Index, i_usize);
|
||||
const in_cpu_set = populated_cpu_features.isEnabled(i);
|
||||
const in_actual_set = cross.cpu.features.isEnabled(i);
|
||||
if (in_cpu_set and !in_actual_set) {
|
||||
try mcpu_buffer.writer().print("-{s}", .{feature.name});
|
||||
} else if (!in_cpu_set and in_actual_set) {
|
||||
try mcpu_buffer.writer().print("+{s}", .{feature.name});
|
||||
}
|
||||
}
|
||||
|
||||
try zig_args.append(try mcpu_buffer.toOwnedSlice());
|
||||
}
|
||||
try zig_args.appendSlice(&.{
|
||||
"-target", try self.target.zigTriple(builder.allocator),
|
||||
"-mcpu", try std.Build.serializeCpu(builder.allocator, self.target.getCpu()),
|
||||
});
|
||||
|
||||
if (self.target.dynamic_linker.get()) |dynamic_linker| {
|
||||
try zig_args.append("--dynamic-linker");
|
||||
@@ -1720,13 +1651,13 @@ fn make(step: *Step) !void {
|
||||
const name = entry.key_ptr.*;
|
||||
const info = entry.value_ptr.*;
|
||||
if (info.needed) {
|
||||
zig_args.append("-needed_framework") catch unreachable;
|
||||
try zig_args.append("-needed_framework");
|
||||
} else if (info.weak) {
|
||||
zig_args.append("-weak_framework") catch unreachable;
|
||||
try zig_args.append("-weak_framework");
|
||||
} else {
|
||||
zig_args.append("-framework") catch unreachable;
|
||||
try zig_args.append("-framework");
|
||||
}
|
||||
zig_args.append(name) catch unreachable;
|
||||
try zig_args.append(name);
|
||||
}
|
||||
} else {
|
||||
if (self.framework_dirs.items.len > 0) {
|
||||
@@ -1817,7 +1748,7 @@ fn make(step: *Step) !void {
|
||||
// Slow path for arguments that need to be escaped. We'll need to allocate and copy
|
||||
var escaped = try ArrayList(u8).initCapacity(args_arena.allocator(), arg.len + 1);
|
||||
const writer = escaped.writer();
|
||||
writer.writeAll(arg[0..arg_idx]) catch unreachable;
|
||||
try writer.writeAll(arg[0..arg_idx]);
|
||||
for (arg[arg_idx..]) |to_escape| {
|
||||
if (to_escape == '\\' or to_escape == '"') try writer.writeByte('\\');
|
||||
try writer.writeByte(to_escape);
|
||||
@@ -1943,30 +1874,35 @@ fn findVcpkgRoot(allocator: Allocator) !?[]const u8 {
|
||||
return vcpkg_path;
|
||||
}
|
||||
|
||||
pub fn doAtomicSymLinks(allocator: Allocator, output_path: []const u8, filename_major_only: []const u8, filename_name_only: []const u8) !void {
|
||||
pub fn doAtomicSymLinks(
|
||||
allocator: Allocator,
|
||||
output_path: []const u8,
|
||||
filename_major_only: []const u8,
|
||||
filename_name_only: []const u8,
|
||||
) !void {
|
||||
const out_dir = fs.path.dirname(output_path) orelse ".";
|
||||
const out_basename = fs.path.basename(output_path);
|
||||
// sym link for libfoo.so.1 to libfoo.so.1.2.3
|
||||
const major_only_path = fs.path.join(
|
||||
const major_only_path = try fs.path.join(
|
||||
allocator,
|
||||
&[_][]const u8{ out_dir, filename_major_only },
|
||||
) catch unreachable;
|
||||
);
|
||||
fs.atomicSymLink(allocator, out_basename, major_only_path) catch |err| {
|
||||
log.err("Unable to symlink {s} -> {s}", .{ major_only_path, out_basename });
|
||||
return err;
|
||||
};
|
||||
// sym link for libfoo.so to libfoo.so.1
|
||||
const name_only_path = fs.path.join(
|
||||
const name_only_path = try fs.path.join(
|
||||
allocator,
|
||||
&[_][]const u8{ out_dir, filename_name_only },
|
||||
) catch unreachable;
|
||||
);
|
||||
fs.atomicSymLink(allocator, filename_major_only, name_only_path) catch |err| {
|
||||
log.err("Unable to symlink {s} -> {s}", .{ name_only_path, filename_major_only });
|
||||
return err;
|
||||
};
|
||||
}
|
||||
|
||||
fn execPkgConfigList(self: *Builder, out_code: *u8) (PkgConfigError || ExecError)![]const PkgConfigPkg {
|
||||
fn execPkgConfigList(self: *std.Build, out_code: *u8) (PkgConfigError || ExecError)![]const PkgConfigPkg {
|
||||
const stdout = try self.execAllowFail(&[_][]const u8{ "pkg-config", "--list-all" }, out_code, .Ignore);
|
||||
var list = ArrayList(PkgConfigPkg).init(self.allocator);
|
||||
errdefer list.deinit();
|
||||
@@ -1982,7 +1918,7 @@ fn execPkgConfigList(self: *Builder, out_code: *u8) (PkgConfigError || ExecError
|
||||
return list.toOwnedSlice();
|
||||
}
|
||||
|
||||
fn getPkgConfigList(self: *Builder) ![]const PkgConfigPkg {
|
||||
fn getPkgConfigList(self: *std.Build) ![]const PkgConfigPkg {
|
||||
if (self.pkg_config_pkg_list) |res| {
|
||||
return res;
|
||||
}
|
||||
@@ -2012,12 +1948,15 @@ test "addPackage" {
|
||||
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
||||
defer arena.deinit();
|
||||
|
||||
var builder = try Builder.create(
|
||||
const host = try NativeTargetInfo.detect(.{});
|
||||
|
||||
var builder = try std.Build.create(
|
||||
arena.allocator(),
|
||||
"test",
|
||||
"test",
|
||||
"test",
|
||||
"test",
|
||||
host,
|
||||
);
|
||||
defer builder.destroy();
|
||||
|
||||
@@ -2031,7 +1970,10 @@ test "addPackage" {
|
||||
.dependencies = &[_]Pkg{pkg_dep},
|
||||
};
|
||||
|
||||
var exe = builder.addExecutable("not_an_executable", "/not/an/executable.zig");
|
||||
var exe = builder.addExecutable(.{
|
||||
.name = "not_an_executable",
|
||||
.root_source_file = .{ .path = "/not/an/executable.zig" },
|
||||
});
|
||||
exe.addPackage(pkg_top);
|
||||
|
||||
try std.testing.expectEqual(@as(usize, 1), exe.packages.items.len);
|
||||
@@ -2070,7 +2012,7 @@ const TransitiveDeps = struct {
|
||||
}
|
||||
}
|
||||
|
||||
fn addInner(td: *TransitiveDeps, other: *LibExeObjStep, dyn: bool) !void {
|
||||
fn addInner(td: *TransitiveDeps, other: *CompileStep, dyn: bool) !void {
|
||||
// Inherit dependency on libc and libc++
|
||||
td.is_linking_libcpp = td.is_linking_libcpp or other.is_linking_libcpp;
|
||||
td.is_linking_libc = td.is_linking_libc or other.is_linking_libc;
|
||||
@@ -1,7 +1,6 @@
|
||||
const std = @import("../std.zig");
|
||||
const ConfigHeaderStep = @This();
|
||||
const Step = std.build.Step;
|
||||
const Builder = std.build.Builder;
|
||||
const Step = std.Build.Step;
|
||||
|
||||
pub const base_id: Step.Id = .config_header;
|
||||
|
||||
@@ -24,15 +23,15 @@ pub const Value = union(enum) {
|
||||
};
|
||||
|
||||
step: Step,
|
||||
builder: *Builder,
|
||||
source: std.build.FileSource,
|
||||
builder: *std.Build,
|
||||
source: std.Build.FileSource,
|
||||
style: Style,
|
||||
values: std.StringHashMap(Value),
|
||||
max_bytes: usize = 2 * 1024 * 1024,
|
||||
output_dir: []const u8,
|
||||
output_basename: []const u8,
|
||||
|
||||
pub fn create(builder: *Builder, source: std.build.FileSource, style: Style) *ConfigHeaderStep {
|
||||
pub fn create(builder: *std.Build, source: std.Build.FileSource, style: Style) *ConfigHeaderStep {
|
||||
const self = builder.allocator.create(ConfigHeaderStep) catch @panic("OOM");
|
||||
const name = builder.fmt("configure header {s}", .{source.getDisplayName()});
|
||||
self.* = .{
|
||||
@@ -62,39 +61,51 @@ pub fn addValues(self: *ConfigHeaderStep, values: anytype) void {
|
||||
|
||||
fn addValuesInner(self: *ConfigHeaderStep, values: anytype) !void {
|
||||
inline for (@typeInfo(@TypeOf(values)).Struct.fields) |field| {
|
||||
switch (@typeInfo(field.type)) {
|
||||
.Null => {
|
||||
try self.values.put(field.name, .undef);
|
||||
},
|
||||
.Void => {
|
||||
try self.values.put(field.name, .defined);
|
||||
},
|
||||
.Bool => {
|
||||
try self.values.put(field.name, .{ .boolean = @field(values, field.name) });
|
||||
},
|
||||
.ComptimeInt => {
|
||||
try self.values.put(field.name, .{ .int = @field(values, field.name) });
|
||||
},
|
||||
.EnumLiteral => {
|
||||
try self.values.put(field.name, .{ .ident = @tagName(@field(values, field.name)) });
|
||||
},
|
||||
.Pointer => |ptr| {
|
||||
switch (@typeInfo(ptr.child)) {
|
||||
.Array => |array| {
|
||||
if (ptr.size == .One and array.child == u8) {
|
||||
try self.values.put(field.name, .{ .string = @field(values, field.name) });
|
||||
continue;
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
try putValue(self, field.name, field.type, @field(values, field.name));
|
||||
}
|
||||
}
|
||||
|
||||
@compileError("unsupported ConfigHeaderStep value type: " ++
|
||||
@typeName(field.type));
|
||||
},
|
||||
else => @compileError("unsupported ConfigHeaderStep value type: " ++
|
||||
@typeName(field.type)),
|
||||
}
|
||||
fn putValue(self: *ConfigHeaderStep, field_name: []const u8, comptime T: type, v: T) !void {
|
||||
switch (@typeInfo(T)) {
|
||||
.Null => {
|
||||
try self.values.put(field_name, .undef);
|
||||
},
|
||||
.Void => {
|
||||
try self.values.put(field_name, .defined);
|
||||
},
|
||||
.Bool => {
|
||||
try self.values.put(field_name, .{ .boolean = v });
|
||||
},
|
||||
.Int => {
|
||||
try self.values.put(field_name, .{ .int = v });
|
||||
},
|
||||
.ComptimeInt => {
|
||||
try self.values.put(field_name, .{ .int = v });
|
||||
},
|
||||
.EnumLiteral => {
|
||||
try self.values.put(field_name, .{ .ident = @tagName(v) });
|
||||
},
|
||||
.Optional => {
|
||||
if (v) |x| {
|
||||
return putValue(self, field_name, @TypeOf(x), x);
|
||||
} else {
|
||||
try self.values.put(field_name, .undef);
|
||||
}
|
||||
},
|
||||
.Pointer => |ptr| {
|
||||
switch (@typeInfo(ptr.child)) {
|
||||
.Array => |array| {
|
||||
if (ptr.size == .One and array.child == u8) {
|
||||
try self.values.put(field_name, .{ .string = v });
|
||||
return;
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
||||
@compileError("unsupported ConfigHeaderStep value type: " ++ @typeName(T));
|
||||
},
|
||||
else => @compileError("unsupported ConfigHeaderStep value type: " ++ @typeName(T)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,9 @@
|
||||
//! without having to verify if it's possible to be ran against.
|
||||
|
||||
const std = @import("../std.zig");
|
||||
const build = std.build;
|
||||
const Step = std.build.Step;
|
||||
const Builder = std.build.Builder;
|
||||
const LibExeObjStep = std.build.LibExeObjStep;
|
||||
const RunStep = std.build.RunStep;
|
||||
const Step = std.Build.Step;
|
||||
const CompileStep = std.Build.CompileStep;
|
||||
const RunStep = std.Build.RunStep;
|
||||
|
||||
const fs = std.fs;
|
||||
const process = std.process;
|
||||
@@ -22,10 +20,10 @@ pub const base_id = .emulatable_run;
|
||||
const max_stdout_size = 1 * 1024 * 1024; // 1 MiB
|
||||
|
||||
step: Step,
|
||||
builder: *Builder,
|
||||
builder: *std.Build,
|
||||
|
||||
/// The artifact (executable) to be run by this step
|
||||
exe: *LibExeObjStep,
|
||||
exe: *CompileStep,
|
||||
|
||||
/// Set this to `null` to ignore the exit code for the purpose of determining a successful execution
|
||||
expected_exit_code: ?u8 = 0,
|
||||
@@ -47,9 +45,9 @@ hide_foreign_binaries_warning: bool,
|
||||
/// binary through emulation when any of the emulation options such as `enable_rosetta` are set to true.
|
||||
/// When set to false, and the binary is foreign, running the executable is skipped.
|
||||
/// Asserts given artifact is an executable.
|
||||
pub fn create(builder: *Builder, name: []const u8, artifact: *LibExeObjStep) *EmulatableRunStep {
|
||||
pub fn create(builder: *std.Build, name: []const u8, artifact: *CompileStep) *EmulatableRunStep {
|
||||
std.debug.assert(artifact.kind == .exe or artifact.kind == .test_exe);
|
||||
const self = builder.allocator.create(EmulatableRunStep) catch unreachable;
|
||||
const self = builder.allocator.create(EmulatableRunStep) catch @panic("OOM");
|
||||
|
||||
const option_name = "hide-foreign-warnings";
|
||||
const hide_warnings = if (builder.available_options_map.get(option_name) == null) warn: {
|
||||
@@ -156,9 +154,9 @@ fn warnAboutForeignBinaries(step: *EmulatableRunStep) void {
|
||||
const builder = step.builder;
|
||||
const artifact = step.exe;
|
||||
|
||||
const host_name = builder.host.target.zigTriple(builder.allocator) catch unreachable;
|
||||
const foreign_name = artifact.target.zigTriple(builder.allocator) catch unreachable;
|
||||
const target_info = std.zig.system.NativeTargetInfo.detect(artifact.target) catch unreachable;
|
||||
const host_name = builder.host.target.zigTriple(builder.allocator) catch @panic("unhandled error");
|
||||
const foreign_name = artifact.target.zigTriple(builder.allocator) catch @panic("unhandled error");
|
||||
const target_info = std.zig.system.NativeTargetInfo.detect(artifact.target) catch @panic("unhandled error");
|
||||
const need_cross_glibc = artifact.target.isGnuLibC() and artifact.is_linking_libc;
|
||||
switch (builder.host.getExternalExecutor(target_info, .{
|
||||
.qemu_fixes_dl = need_cross_glibc and builder.glibc_runtimes_dir != null,
|
||||
@@ -1,25 +1,20 @@
|
||||
const std = @import("../std.zig");
|
||||
const build = @import("../build.zig");
|
||||
const Step = build.Step;
|
||||
const Builder = build.Builder;
|
||||
const BufMap = std.BufMap;
|
||||
const mem = std.mem;
|
||||
|
||||
const Step = std.Build.Step;
|
||||
const FmtStep = @This();
|
||||
|
||||
pub const base_id = .fmt;
|
||||
|
||||
step: Step,
|
||||
builder: *Builder,
|
||||
builder: *std.Build,
|
||||
argv: [][]const u8,
|
||||
|
||||
pub fn create(builder: *Builder, paths: []const []const u8) *FmtStep {
|
||||
const self = builder.allocator.create(FmtStep) catch unreachable;
|
||||
pub fn create(builder: *std.Build, paths: []const []const u8) *FmtStep {
|
||||
const self = builder.allocator.create(FmtStep) catch @panic("OOM");
|
||||
const name = "zig fmt";
|
||||
self.* = FmtStep{
|
||||
.step = Step.init(.fmt, name, builder.allocator, make),
|
||||
.builder = builder,
|
||||
.argv = builder.allocator.alloc([]u8, paths.len + 2) catch unreachable,
|
||||
.argv = builder.allocator.alloc([]u8, paths.len + 2) catch @panic("OOM"),
|
||||
};
|
||||
|
||||
self.argv[0] = builder.zig_exe;
|
||||
@@ -1,26 +1,23 @@
|
||||
const std = @import("../std.zig");
|
||||
const build = @import("../build.zig");
|
||||
const Step = build.Step;
|
||||
const Builder = build.Builder;
|
||||
const LibExeObjStep = std.build.LibExeObjStep;
|
||||
const InstallDir = std.build.InstallDir;
|
||||
const Step = std.Build.Step;
|
||||
const CompileStep = std.Build.CompileStep;
|
||||
const InstallDir = std.Build.InstallDir;
|
||||
const InstallArtifactStep = @This();
|
||||
|
||||
pub const base_id = .install_artifact;
|
||||
|
||||
step: Step,
|
||||
builder: *Builder,
|
||||
artifact: *LibExeObjStep,
|
||||
builder: *std.Build,
|
||||
artifact: *CompileStep,
|
||||
dest_dir: InstallDir,
|
||||
pdb_dir: ?InstallDir,
|
||||
h_dir: ?InstallDir,
|
||||
|
||||
const Self = @This();
|
||||
|
||||
pub fn create(builder: *Builder, artifact: *LibExeObjStep) *Self {
|
||||
pub fn create(builder: *std.Build, artifact: *CompileStep) *InstallArtifactStep {
|
||||
if (artifact.install_step) |s| return s;
|
||||
|
||||
const self = builder.allocator.create(Self) catch unreachable;
|
||||
self.* = Self{
|
||||
const self = builder.allocator.create(InstallArtifactStep) catch @panic("OOM");
|
||||
self.* = InstallArtifactStep{
|
||||
.builder = builder,
|
||||
.step = Step.init(.install_artifact, builder.fmt("install {s}", .{artifact.step.name}), builder.allocator, make),
|
||||
.artifact = artifact,
|
||||
@@ -64,13 +61,13 @@ pub fn create(builder: *Builder, artifact: *LibExeObjStep) *Self {
|
||||
}
|
||||
|
||||
fn make(step: *Step) !void {
|
||||
const self = @fieldParentPtr(Self, "step", step);
|
||||
const self = @fieldParentPtr(InstallArtifactStep, "step", step);
|
||||
const builder = self.builder;
|
||||
|
||||
const full_dest_path = builder.getInstallPath(self.dest_dir, self.artifact.out_filename);
|
||||
try builder.updateFile(self.artifact.getOutputSource().getPath(builder), full_dest_path);
|
||||
if (self.artifact.isDynamicLibrary() and self.artifact.version != null and self.artifact.target.wantSharedLibSymLinks()) {
|
||||
try LibExeObjStep.doAtomicSymLinks(builder.allocator, full_dest_path, self.artifact.major_only_filename.?, self.artifact.name_only_filename.?);
|
||||
try CompileStep.doAtomicSymLinks(builder.allocator, full_dest_path, self.artifact.major_only_filename.?, self.artifact.name_only_filename.?);
|
||||
}
|
||||
if (self.artifact.isDynamicLibrary() and self.artifact.target.isWindows() and self.artifact.emit_implib != .no_emit) {
|
||||
const full_implib_path = builder.getInstallPath(self.dest_dir, self.artifact.out_lib_filename);
|
||||
@@ -1,19 +1,17 @@
|
||||
const std = @import("../std.zig");
|
||||
const mem = std.mem;
|
||||
const fs = std.fs;
|
||||
const build = @import("../build.zig");
|
||||
const Step = build.Step;
|
||||
const Builder = build.Builder;
|
||||
const InstallDir = std.build.InstallDir;
|
||||
const Step = std.Build.Step;
|
||||
const InstallDir = std.Build.InstallDir;
|
||||
const InstallDirStep = @This();
|
||||
const log = std.log;
|
||||
|
||||
step: Step,
|
||||
builder: *Builder,
|
||||
builder: *std.Build,
|
||||
options: Options,
|
||||
/// This is used by the build system when a file being installed comes from one
|
||||
/// package but is being installed by another.
|
||||
override_source_builder: ?*Builder = null,
|
||||
override_source_builder: ?*std.Build = null,
|
||||
|
||||
pub const base_id = .install_dir;
|
||||
|
||||
@@ -31,7 +29,7 @@ pub const Options = struct {
|
||||
/// `@import("test.zig")` would be a compile error.
|
||||
blank_extensions: []const []const u8 = &.{},
|
||||
|
||||
fn dupe(self: Options, b: *Builder) Options {
|
||||
fn dupe(self: Options, b: *std.Build) Options {
|
||||
return .{
|
||||
.source_dir = b.dupe(self.source_dir),
|
||||
.install_dir = self.install_dir.dupe(b),
|
||||
@@ -43,7 +41,7 @@ pub const Options = struct {
|
||||
};
|
||||
|
||||
pub fn init(
|
||||
builder: *Builder,
|
||||
builder: *std.Build,
|
||||
options: Options,
|
||||
) InstallDirStep {
|
||||
builder.pushInstalledFile(options.install_dir, options.install_subdir);
|
||||
@@ -1,24 +1,22 @@
|
||||
const std = @import("../std.zig");
|
||||
const build = @import("../build.zig");
|
||||
const Step = build.Step;
|
||||
const Builder = build.Builder;
|
||||
const FileSource = std.build.FileSource;
|
||||
const InstallDir = std.build.InstallDir;
|
||||
const Step = std.Build.Step;
|
||||
const FileSource = std.Build.FileSource;
|
||||
const InstallDir = std.Build.InstallDir;
|
||||
const InstallFileStep = @This();
|
||||
|
||||
pub const base_id = .install_file;
|
||||
|
||||
step: Step,
|
||||
builder: *Builder,
|
||||
builder: *std.Build,
|
||||
source: FileSource,
|
||||
dir: InstallDir,
|
||||
dest_rel_path: []const u8,
|
||||
/// This is used by the build system when a file being installed comes from one
|
||||
/// package but is being installed by another.
|
||||
override_source_builder: ?*Builder = null,
|
||||
override_source_builder: ?*std.Build = null,
|
||||
|
||||
pub fn init(
|
||||
builder: *Builder,
|
||||
builder: *std.Build,
|
||||
source: FileSource,
|
||||
dir: InstallDir,
|
||||
dest_rel_path: []const u8,
|
||||
@@ -7,11 +7,10 @@ const InstallRawStep = @This();
|
||||
const Allocator = std.mem.Allocator;
|
||||
const ArenaAllocator = std.heap.ArenaAllocator;
|
||||
const ArrayListUnmanaged = std.ArrayListUnmanaged;
|
||||
const Builder = std.build.Builder;
|
||||
const File = std.fs.File;
|
||||
const InstallDir = std.build.InstallDir;
|
||||
const LibExeObjStep = std.build.LibExeObjStep;
|
||||
const Step = std.build.Step;
|
||||
const InstallDir = std.Build.InstallDir;
|
||||
const CompileStep = std.Build.CompileStep;
|
||||
const Step = std.Build.Step;
|
||||
const elf = std.elf;
|
||||
const fs = std.fs;
|
||||
const io = std.io;
|
||||
@@ -25,12 +24,12 @@ pub const RawFormat = enum {
|
||||
};
|
||||
|
||||
step: Step,
|
||||
builder: *Builder,
|
||||
artifact: *LibExeObjStep,
|
||||
builder: *std.Build,
|
||||
artifact: *CompileStep,
|
||||
dest_dir: InstallDir,
|
||||
dest_filename: []const u8,
|
||||
options: CreateOptions,
|
||||
output_file: std.build.GeneratedFile,
|
||||
output_file: std.Build.GeneratedFile,
|
||||
|
||||
pub const CreateOptions = struct {
|
||||
format: ?RawFormat = null,
|
||||
@@ -39,8 +38,13 @@ pub const CreateOptions = struct {
|
||||
pad_to: ?u64 = null,
|
||||
};
|
||||
|
||||
pub fn create(builder: *Builder, artifact: *LibExeObjStep, dest_filename: []const u8, options: CreateOptions) *InstallRawStep {
|
||||
const self = builder.allocator.create(InstallRawStep) catch unreachable;
|
||||
pub fn create(
|
||||
builder: *std.Build,
|
||||
artifact: *CompileStep,
|
||||
dest_filename: []const u8,
|
||||
options: CreateOptions,
|
||||
) *InstallRawStep {
|
||||
const self = builder.allocator.create(InstallRawStep) catch @panic("OOM");
|
||||
self.* = InstallRawStep{
|
||||
.step = Step.init(.install_raw, builder.fmt("install raw binary {s}", .{artifact.step.name}), builder.allocator, make),
|
||||
.builder = builder,
|
||||
@@ -53,7 +57,7 @@ pub fn create(builder: *Builder, artifact: *LibExeObjStep, dest_filename: []cons
|
||||
},
|
||||
.dest_filename = dest_filename,
|
||||
.options = options,
|
||||
.output_file = std.build.GeneratedFile{ .step = &self.step },
|
||||
.output_file = std.Build.GeneratedFile{ .step = &self.step },
|
||||
};
|
||||
self.step.dependOn(&artifact.step);
|
||||
|
||||
@@ -61,8 +65,8 @@ pub fn create(builder: *Builder, artifact: *LibExeObjStep, dest_filename: []cons
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn getOutputSource(self: *const InstallRawStep) std.build.FileSource {
|
||||
return std.build.FileSource{ .generated = &self.output_file };
|
||||
pub fn getOutputSource(self: *const InstallRawStep) std.Build.FileSource {
|
||||
return std.Build.FileSource{ .generated = &self.output_file };
|
||||
}
|
||||
|
||||
fn make(step: *Step) !void {
|
||||
@@ -78,7 +82,7 @@ fn make(step: *Step) !void {
|
||||
const full_dest_path = b.getInstallPath(self.dest_dir, self.dest_filename);
|
||||
self.output_file.path = full_dest_path;
|
||||
|
||||
fs.cwd().makePath(b.getInstallPath(self.dest_dir, "")) catch unreachable;
|
||||
try fs.cwd().makePath(b.getInstallPath(self.dest_dir, ""));
|
||||
|
||||
var argv_list = std.ArrayList([]const u8).init(b.allocator);
|
||||
try argv_list.appendSlice(&.{ b.zig_exe, "objcopy" });
|
||||
@@ -1,17 +1,15 @@
|
||||
const std = @import("../std.zig");
|
||||
const log = std.log;
|
||||
const build = @import("../build.zig");
|
||||
const Step = build.Step;
|
||||
const Builder = build.Builder;
|
||||
const Step = std.Build.Step;
|
||||
const LogStep = @This();
|
||||
|
||||
pub const base_id = .log;
|
||||
|
||||
step: Step,
|
||||
builder: *Builder,
|
||||
builder: *std.Build,
|
||||
data: []const u8,
|
||||
|
||||
pub fn init(builder: *Builder, data: []const u8) LogStep {
|
||||
pub fn init(builder: *std.Build, data: []const u8) LogStep {
|
||||
return LogStep{
|
||||
.builder = builder,
|
||||
.step = Step.init(.log, builder.fmt("log {s}", .{data}), builder.allocator, make),
|
||||
@@ -1,12 +1,10 @@
|
||||
const std = @import("../std.zig");
|
||||
const builtin = @import("builtin");
|
||||
const build = std.build;
|
||||
const fs = std.fs;
|
||||
const Step = build.Step;
|
||||
const Builder = build.Builder;
|
||||
const GeneratedFile = build.GeneratedFile;
|
||||
const LibExeObjStep = build.LibExeObjStep;
|
||||
const FileSource = build.FileSource;
|
||||
const Step = std.Build.Step;
|
||||
const GeneratedFile = std.Build.GeneratedFile;
|
||||
const CompileStep = std.Build.CompileStep;
|
||||
const FileSource = std.Build.FileSource;
|
||||
|
||||
const OptionsStep = @This();
|
||||
|
||||
@@ -14,14 +12,14 @@ pub const base_id = .options;
|
||||
|
||||
step: Step,
|
||||
generated_file: GeneratedFile,
|
||||
builder: *Builder,
|
||||
builder: *std.Build,
|
||||
|
||||
contents: std.ArrayList(u8),
|
||||
artifact_args: std.ArrayList(OptionArtifactArg),
|
||||
file_source_args: std.ArrayList(OptionFileSourceArg),
|
||||
|
||||
pub fn create(builder: *Builder) *OptionsStep {
|
||||
const self = builder.allocator.create(OptionsStep) catch unreachable;
|
||||
pub fn create(builder: *std.Build) *OptionsStep {
|
||||
const self = builder.allocator.create(OptionsStep) catch @panic("OOM");
|
||||
self.* = .{
|
||||
.builder = builder,
|
||||
.step = Step.init(.options, "options", builder.allocator, make),
|
||||
@@ -36,44 +34,48 @@ pub fn create(builder: *Builder) *OptionsStep {
|
||||
}
|
||||
|
||||
pub fn addOption(self: *OptionsStep, comptime T: type, name: []const u8, value: T) void {
|
||||
return addOptionFallible(self, T, name, value) catch @panic("unhandled error");
|
||||
}
|
||||
|
||||
fn addOptionFallible(self: *OptionsStep, comptime T: type, name: []const u8, value: T) !void {
|
||||
const out = self.contents.writer();
|
||||
switch (T) {
|
||||
[]const []const u8 => {
|
||||
out.print("pub const {}: []const []const u8 = &[_][]const u8{{\n", .{std.zig.fmtId(name)}) catch unreachable;
|
||||
try out.print("pub const {}: []const []const u8 = &[_][]const u8{{\n", .{std.zig.fmtId(name)});
|
||||
for (value) |slice| {
|
||||
out.print(" \"{}\",\n", .{std.zig.fmtEscapes(slice)}) catch unreachable;
|
||||
try out.print(" \"{}\",\n", .{std.zig.fmtEscapes(slice)});
|
||||
}
|
||||
out.writeAll("};\n") catch unreachable;
|
||||
try out.writeAll("};\n");
|
||||
return;
|
||||
},
|
||||
[:0]const u8 => {
|
||||
out.print("pub const {}: [:0]const u8 = \"{}\";\n", .{ std.zig.fmtId(name), std.zig.fmtEscapes(value) }) catch unreachable;
|
||||
try out.print("pub const {}: [:0]const u8 = \"{}\";\n", .{ std.zig.fmtId(name), std.zig.fmtEscapes(value) });
|
||||
return;
|
||||
},
|
||||
[]const u8 => {
|
||||
out.print("pub const {}: []const u8 = \"{}\";\n", .{ std.zig.fmtId(name), std.zig.fmtEscapes(value) }) catch unreachable;
|
||||
try out.print("pub const {}: []const u8 = \"{}\";\n", .{ std.zig.fmtId(name), std.zig.fmtEscapes(value) });
|
||||
return;
|
||||
},
|
||||
?[:0]const u8 => {
|
||||
out.print("pub const {}: ?[:0]const u8 = ", .{std.zig.fmtId(name)}) catch unreachable;
|
||||
try out.print("pub const {}: ?[:0]const u8 = ", .{std.zig.fmtId(name)});
|
||||
if (value) |payload| {
|
||||
out.print("\"{}\";\n", .{std.zig.fmtEscapes(payload)}) catch unreachable;
|
||||
try out.print("\"{}\";\n", .{std.zig.fmtEscapes(payload)});
|
||||
} else {
|
||||
out.writeAll("null;\n") catch unreachable;
|
||||
try out.writeAll("null;\n");
|
||||
}
|
||||
return;
|
||||
},
|
||||
?[]const u8 => {
|
||||
out.print("pub const {}: ?[]const u8 = ", .{std.zig.fmtId(name)}) catch unreachable;
|
||||
try out.print("pub const {}: ?[]const u8 = ", .{std.zig.fmtId(name)});
|
||||
if (value) |payload| {
|
||||
out.print("\"{}\";\n", .{std.zig.fmtEscapes(payload)}) catch unreachable;
|
||||
try out.print("\"{}\";\n", .{std.zig.fmtEscapes(payload)});
|
||||
} else {
|
||||
out.writeAll("null;\n") catch unreachable;
|
||||
try out.writeAll("null;\n");
|
||||
}
|
||||
return;
|
||||
},
|
||||
std.builtin.Version => {
|
||||
out.print(
|
||||
try out.print(
|
||||
\\pub const {}: @import("std").builtin.Version = .{{
|
||||
\\ .major = {d},
|
||||
\\ .minor = {d},
|
||||
@@ -86,11 +88,11 @@ pub fn addOption(self: *OptionsStep, comptime T: type, name: []const u8, value:
|
||||
value.major,
|
||||
value.minor,
|
||||
value.patch,
|
||||
}) catch unreachable;
|
||||
});
|
||||
return;
|
||||
},
|
||||
std.SemanticVersion => {
|
||||
out.print(
|
||||
try out.print(
|
||||
\\pub const {}: @import("std").SemanticVersion = .{{
|
||||
\\ .major = {d},
|
||||
\\ .minor = {d},
|
||||
@@ -102,38 +104,38 @@ pub fn addOption(self: *OptionsStep, comptime T: type, name: []const u8, value:
|
||||
value.major,
|
||||
value.minor,
|
||||
value.patch,
|
||||
}) catch unreachable;
|
||||
});
|
||||
if (value.pre) |some| {
|
||||
out.print(" .pre = \"{}\",\n", .{std.zig.fmtEscapes(some)}) catch unreachable;
|
||||
try out.print(" .pre = \"{}\",\n", .{std.zig.fmtEscapes(some)});
|
||||
}
|
||||
if (value.build) |some| {
|
||||
out.print(" .build = \"{}\",\n", .{std.zig.fmtEscapes(some)}) catch unreachable;
|
||||
try out.print(" .build = \"{}\",\n", .{std.zig.fmtEscapes(some)});
|
||||
}
|
||||
out.writeAll("};\n") catch unreachable;
|
||||
try out.writeAll("};\n");
|
||||
return;
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
switch (@typeInfo(T)) {
|
||||
.Enum => |enum_info| {
|
||||
out.print("pub const {} = enum {{\n", .{std.zig.fmtId(@typeName(T))}) catch unreachable;
|
||||
try out.print("pub const {} = enum {{\n", .{std.zig.fmtId(@typeName(T))});
|
||||
inline for (enum_info.fields) |field| {
|
||||
out.print(" {},\n", .{std.zig.fmtId(field.name)}) catch unreachable;
|
||||
try out.print(" {},\n", .{std.zig.fmtId(field.name)});
|
||||
}
|
||||
out.writeAll("};\n") catch unreachable;
|
||||
out.print("pub const {}: {s} = {s}.{s};\n", .{
|
||||
try out.writeAll("};\n");
|
||||
try out.print("pub const {}: {s} = {s}.{s};\n", .{
|
||||
std.zig.fmtId(name),
|
||||
std.zig.fmtId(@typeName(T)),
|
||||
std.zig.fmtId(@typeName(T)),
|
||||
std.zig.fmtId(@tagName(value)),
|
||||
}) catch unreachable;
|
||||
});
|
||||
return;
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
out.print("pub const {}: {s} = ", .{ std.zig.fmtId(name), @typeName(T) }) catch unreachable;
|
||||
printLiteral(out, value, 0) catch unreachable;
|
||||
out.writeAll(";\n") catch unreachable;
|
||||
try out.print("pub const {}: {s} = ", .{ std.zig.fmtId(name), @typeName(T) });
|
||||
try printLiteral(out, value, 0);
|
||||
try out.writeAll(";\n");
|
||||
}
|
||||
|
||||
// TODO: non-recursive?
|
||||
@@ -191,18 +193,18 @@ pub fn addOptionFileSource(
|
||||
self.file_source_args.append(.{
|
||||
.name = name,
|
||||
.source = source.dupe(self.builder),
|
||||
}) catch unreachable;
|
||||
}) catch @panic("OOM");
|
||||
source.addStepDependencies(&self.step);
|
||||
}
|
||||
|
||||
/// The value is the path in the cache dir.
|
||||
/// Adds a dependency automatically.
|
||||
pub fn addOptionArtifact(self: *OptionsStep, name: []const u8, artifact: *LibExeObjStep) void {
|
||||
self.artifact_args.append(.{ .name = self.builder.dupe(name), .artifact = artifact }) catch unreachable;
|
||||
pub fn addOptionArtifact(self: *OptionsStep, name: []const u8, artifact: *CompileStep) void {
|
||||
self.artifact_args.append(.{ .name = self.builder.dupe(name), .artifact = artifact }) catch @panic("OOM");
|
||||
self.step.dependOn(&artifact.step);
|
||||
}
|
||||
|
||||
pub fn getPackage(self: *OptionsStep, package_name: []const u8) build.Pkg {
|
||||
pub fn getPackage(self: *OptionsStep, package_name: []const u8) std.Build.Pkg {
|
||||
return .{ .name = package_name, .source = self.getSource() };
|
||||
}
|
||||
|
||||
@@ -268,7 +270,7 @@ fn hashContentsToFileName(self: *OptionsStep) [64]u8 {
|
||||
|
||||
const OptionArtifactArg = struct {
|
||||
name: []const u8,
|
||||
artifact: *LibExeObjStep,
|
||||
artifact: *CompileStep,
|
||||
};
|
||||
|
||||
const OptionFileSourceArg = struct {
|
||||
@@ -281,12 +283,16 @@ test "OptionsStep" {
|
||||
|
||||
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
||||
defer arena.deinit();
|
||||
var builder = try Builder.create(
|
||||
|
||||
const host = try std.zig.system.NativeTargetInfo.detect(.{});
|
||||
|
||||
var builder = try std.Build.create(
|
||||
arena.allocator(),
|
||||
"test",
|
||||
"test",
|
||||
"test",
|
||||
"test",
|
||||
host,
|
||||
);
|
||||
defer builder.destroy();
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
const std = @import("../std.zig");
|
||||
const log = std.log;
|
||||
const fs = std.fs;
|
||||
const build = @import("../build.zig");
|
||||
const Step = build.Step;
|
||||
const Builder = build.Builder;
|
||||
const Step = std.Build.Step;
|
||||
const RemoveDirStep = @This();
|
||||
|
||||
pub const base_id = .remove_dir;
|
||||
|
||||
step: Step,
|
||||
builder: *Builder,
|
||||
builder: *std.Build,
|
||||
dir_path: []const u8,
|
||||
|
||||
pub fn init(builder: *Builder, dir_path: []const u8) RemoveDirStep {
|
||||
pub fn init(builder: *std.Build, dir_path: []const u8) RemoveDirStep {
|
||||
return RemoveDirStep{
|
||||
.builder = builder,
|
||||
.step = Step.init(.remove_dir, builder.fmt("RemoveDir {s}", .{dir_path}), builder.allocator, make),
|
||||
@@ -1,17 +1,15 @@
|
||||
const std = @import("../std.zig");
|
||||
const builtin = @import("builtin");
|
||||
const build = std.build;
|
||||
const Step = build.Step;
|
||||
const Builder = build.Builder;
|
||||
const LibExeObjStep = build.LibExeObjStep;
|
||||
const WriteFileStep = build.WriteFileStep;
|
||||
const Step = std.Build.Step;
|
||||
const CompileStep = std.Build.CompileStep;
|
||||
const WriteFileStep = std.Build.WriteFileStep;
|
||||
const fs = std.fs;
|
||||
const mem = std.mem;
|
||||
const process = std.process;
|
||||
const ArrayList = std.ArrayList;
|
||||
const EnvMap = process.EnvMap;
|
||||
const Allocator = mem.Allocator;
|
||||
const ExecError = build.Builder.ExecError;
|
||||
const ExecError = std.Build.ExecError;
|
||||
|
||||
const max_stdout_size = 1 * 1024 * 1024; // 1 MiB
|
||||
|
||||
@@ -20,7 +18,7 @@ const RunStep = @This();
|
||||
pub const base_id: Step.Id = .run;
|
||||
|
||||
step: Step,
|
||||
builder: *Builder,
|
||||
builder: *std.Build,
|
||||
|
||||
/// See also addArg and addArgs to modifying this directly
|
||||
argv: ArrayList(Arg),
|
||||
@@ -50,13 +48,13 @@ pub const StdIoAction = union(enum) {
|
||||
};
|
||||
|
||||
pub const Arg = union(enum) {
|
||||
artifact: *LibExeObjStep,
|
||||
file_source: build.FileSource,
|
||||
artifact: *CompileStep,
|
||||
file_source: std.Build.FileSource,
|
||||
bytes: []u8,
|
||||
};
|
||||
|
||||
pub fn create(builder: *Builder, name: []const u8) *RunStep {
|
||||
const self = builder.allocator.create(RunStep) catch unreachable;
|
||||
pub fn create(builder: *std.Build, name: []const u8) *RunStep {
|
||||
const self = builder.allocator.create(RunStep) catch @panic("OOM");
|
||||
self.* = RunStep{
|
||||
.builder = builder,
|
||||
.step = Step.init(base_id, name, builder.allocator, make),
|
||||
@@ -68,20 +66,20 @@ pub fn create(builder: *Builder, name: []const u8) *RunStep {
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn addArtifactArg(self: *RunStep, artifact: *LibExeObjStep) void {
|
||||
self.argv.append(Arg{ .artifact = artifact }) catch unreachable;
|
||||
pub fn addArtifactArg(self: *RunStep, artifact: *CompileStep) void {
|
||||
self.argv.append(Arg{ .artifact = artifact }) catch @panic("OOM");
|
||||
self.step.dependOn(&artifact.step);
|
||||
}
|
||||
|
||||
pub fn addFileSourceArg(self: *RunStep, file_source: build.FileSource) void {
|
||||
pub fn addFileSourceArg(self: *RunStep, file_source: std.Build.FileSource) void {
|
||||
self.argv.append(Arg{
|
||||
.file_source = file_source.dupe(self.builder),
|
||||
}) catch unreachable;
|
||||
}) catch @panic("OOM");
|
||||
file_source.addStepDependencies(&self.step);
|
||||
}
|
||||
|
||||
pub fn addArg(self: *RunStep, arg: []const u8) void {
|
||||
self.argv.append(Arg{ .bytes = self.builder.dupe(arg) }) catch unreachable;
|
||||
self.argv.append(Arg{ .bytes = self.builder.dupe(arg) }) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn addArgs(self: *RunStep, args: []const []const u8) void {
|
||||
@@ -91,7 +89,7 @@ pub fn addArgs(self: *RunStep, args: []const []const u8) void {
|
||||
}
|
||||
|
||||
pub fn clearEnvironment(self: *RunStep) void {
|
||||
const new_env_map = self.builder.allocator.create(EnvMap) catch unreachable;
|
||||
const new_env_map = self.builder.allocator.create(EnvMap) catch @panic("OOM");
|
||||
new_env_map.* = EnvMap.init(self.builder.allocator);
|
||||
self.env_map = new_env_map;
|
||||
}
|
||||
@@ -101,7 +99,7 @@ pub fn addPathDir(self: *RunStep, search_path: []const u8) void {
|
||||
}
|
||||
|
||||
/// For internal use only, users of `RunStep` should use `addPathDir` directly.
|
||||
pub fn addPathDirInternal(step: *Step, builder: *Builder, search_path: []const u8) void {
|
||||
pub fn addPathDirInternal(step: *Step, builder: *std.Build, search_path: []const u8) void {
|
||||
const env_map = getEnvMapInternal(step, builder.allocator);
|
||||
|
||||
const key = "PATH";
|
||||
@@ -109,9 +107,9 @@ pub fn addPathDirInternal(step: *Step, builder: *Builder, search_path: []const u
|
||||
|
||||
if (prev_path) |pp| {
|
||||
const new_path = builder.fmt("{s}" ++ [1]u8{fs.path.delimiter} ++ "{s}", .{ pp, search_path });
|
||||
env_map.put(key, new_path) catch unreachable;
|
||||
env_map.put(key, new_path) catch @panic("OOM");
|
||||
} else {
|
||||
env_map.put(key, builder.dupePath(search_path)) catch unreachable;
|
||||
env_map.put(key, builder.dupePath(search_path)) catch @panic("OOM");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,12 +120,12 @@ pub fn getEnvMap(self: *RunStep) *EnvMap {
|
||||
fn getEnvMapInternal(step: *Step, allocator: Allocator) *EnvMap {
|
||||
const maybe_env_map = switch (step.id) {
|
||||
.run => step.cast(RunStep).?.env_map,
|
||||
.emulatable_run => step.cast(build.EmulatableRunStep).?.env_map,
|
||||
.emulatable_run => step.cast(std.Build.EmulatableRunStep).?.env_map,
|
||||
else => unreachable,
|
||||
};
|
||||
return maybe_env_map orelse {
|
||||
const env_map = allocator.create(EnvMap) catch unreachable;
|
||||
env_map.* = process.getEnvMap(allocator) catch unreachable;
|
||||
const env_map = allocator.create(EnvMap) catch @panic("OOM");
|
||||
env_map.* = process.getEnvMap(allocator) catch @panic("unhandled error");
|
||||
switch (step.id) {
|
||||
.run => step.cast(RunStep).?.env_map = env_map,
|
||||
.emulatable_run => step.cast(RunStep).?.env_map = env_map,
|
||||
@@ -142,7 +140,7 @@ pub fn setEnvironmentVariable(self: *RunStep, key: []const u8, value: []const u8
|
||||
env_map.put(
|
||||
self.builder.dupe(key),
|
||||
self.builder.dupe(value),
|
||||
) catch unreachable;
|
||||
) catch @panic("unhandled error");
|
||||
}
|
||||
|
||||
pub fn expectStdErrEqual(self: *RunStep, bytes: []const u8) void {
|
||||
@@ -195,7 +193,7 @@ fn make(step: *Step) !void {
|
||||
|
||||
pub fn runCommand(
|
||||
argv: []const []const u8,
|
||||
builder: *Builder,
|
||||
builder: *std.Build,
|
||||
expected_exit_code: ?u8,
|
||||
stdout_action: StdIoAction,
|
||||
stderr_action: StdIoAction,
|
||||
@@ -236,7 +234,7 @@ pub fn runCommand(
|
||||
|
||||
switch (stdout_action) {
|
||||
.expect_exact, .expect_matches => {
|
||||
stdout = child.stdout.?.reader().readAllAlloc(builder.allocator, max_stdout_size) catch unreachable;
|
||||
stdout = try child.stdout.?.reader().readAllAlloc(builder.allocator, max_stdout_size);
|
||||
},
|
||||
.inherit, .ignore => {},
|
||||
}
|
||||
@@ -246,7 +244,7 @@ pub fn runCommand(
|
||||
|
||||
switch (stderr_action) {
|
||||
.expect_exact, .expect_matches => {
|
||||
stderr = child.stderr.?.reader().readAllAlloc(builder.allocator, max_stdout_size) catch unreachable;
|
||||
stderr = try child.stderr.?.reader().readAllAlloc(builder.allocator, max_stdout_size);
|
||||
},
|
||||
.inherit, .ignore => {},
|
||||
}
|
||||
@@ -357,13 +355,13 @@ fn printCmd(cwd: ?[]const u8, argv: []const []const u8) void {
|
||||
std.debug.print("\n", .{});
|
||||
}
|
||||
|
||||
fn addPathForDynLibs(self: *RunStep, artifact: *LibExeObjStep) void {
|
||||
fn addPathForDynLibs(self: *RunStep, artifact: *CompileStep) void {
|
||||
addPathForDynLibsInternal(&self.step, self.builder, artifact);
|
||||
}
|
||||
|
||||
/// This should only be used for internal usage, this is called automatically
|
||||
/// for the user.
|
||||
pub fn addPathForDynLibsInternal(step: *Step, builder: *Builder, artifact: *LibExeObjStep) void {
|
||||
pub fn addPathForDynLibsInternal(step: *Step, builder: *std.Build, artifact: *CompileStep) void {
|
||||
for (artifact.link_objects.items) |link_object| {
|
||||
switch (link_object) {
|
||||
.other_step => |other| {
|
||||
@@ -0,0 +1,97 @@
|
||||
id: Id,
|
||||
name: []const u8,
|
||||
makeFn: *const fn (self: *Step) anyerror!void,
|
||||
dependencies: std.ArrayList(*Step),
|
||||
loop_flag: bool,
|
||||
done_flag: bool,
|
||||
|
||||
pub const Id = enum {
|
||||
top_level,
|
||||
compile,
|
||||
install_artifact,
|
||||
install_file,
|
||||
install_dir,
|
||||
log,
|
||||
remove_dir,
|
||||
fmt,
|
||||
translate_c,
|
||||
write_file,
|
||||
run,
|
||||
emulatable_run,
|
||||
check_file,
|
||||
check_object,
|
||||
config_header,
|
||||
install_raw,
|
||||
options,
|
||||
custom,
|
||||
|
||||
pub fn Type(comptime id: Id) type {
|
||||
return switch (id) {
|
||||
.top_level => Build.TopLevelStep,
|
||||
.compile => Build.CompileStep,
|
||||
.install_artifact => Build.InstallArtifactStep,
|
||||
.install_file => Build.InstallFileStep,
|
||||
.install_dir => Build.InstallDirStep,
|
||||
.log => Build.LogStep,
|
||||
.remove_dir => Build.RemoveDirStep,
|
||||
.fmt => Build.FmtStep,
|
||||
.translate_c => Build.TranslateCStep,
|
||||
.write_file => Build.WriteFileStep,
|
||||
.run => Build.RunStep,
|
||||
.emulatable_run => Build.EmulatableRunStep,
|
||||
.check_file => Build.CheckFileStep,
|
||||
.check_object => Build.CheckObjectStep,
|
||||
.config_header => Build.ConfigHeaderStep,
|
||||
.install_raw => Build.InstallRawStep,
|
||||
.options => Build.OptionsStep,
|
||||
.custom => @compileError("no type available for custom step"),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn init(
|
||||
id: Id,
|
||||
name: []const u8,
|
||||
allocator: Allocator,
|
||||
makeFn: *const fn (self: *Step) anyerror!void,
|
||||
) Step {
|
||||
return Step{
|
||||
.id = id,
|
||||
.name = allocator.dupe(u8, name) catch @panic("OOM"),
|
||||
.makeFn = makeFn,
|
||||
.dependencies = std.ArrayList(*Step).init(allocator),
|
||||
.loop_flag = false,
|
||||
.done_flag = false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn initNoOp(id: Id, name: []const u8, allocator: Allocator) Step {
|
||||
return init(id, name, allocator, makeNoOp);
|
||||
}
|
||||
|
||||
pub fn make(self: *Step) !void {
|
||||
if (self.done_flag) return;
|
||||
|
||||
try self.makeFn(self);
|
||||
self.done_flag = true;
|
||||
}
|
||||
|
||||
pub fn dependOn(self: *Step, other: *Step) void {
|
||||
self.dependencies.append(other) catch @panic("OOM");
|
||||
}
|
||||
|
||||
fn makeNoOp(self: *Step) anyerror!void {
|
||||
_ = self;
|
||||
}
|
||||
|
||||
pub fn cast(step: *Step, comptime T: type) ?*T {
|
||||
if (step.id == T.base_id) {
|
||||
return @fieldParentPtr(T, "step", step);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const Step = @This();
|
||||
const std = @import("../std.zig");
|
||||
const Build = std.Build;
|
||||
const Allocator = std.mem.Allocator;
|
||||
@@ -1,9 +1,7 @@
|
||||
const std = @import("../std.zig");
|
||||
const build = std.build;
|
||||
const Step = build.Step;
|
||||
const Builder = build.Builder;
|
||||
const LibExeObjStep = build.LibExeObjStep;
|
||||
const CheckFileStep = build.CheckFileStep;
|
||||
const Step = std.Build.Step;
|
||||
const CompileStep = std.Build.CompileStep;
|
||||
const CheckFileStep = std.Build.CheckFileStep;
|
||||
const fs = std.fs;
|
||||
const mem = std.mem;
|
||||
const CrossTarget = std.zig.CrossTarget;
|
||||
@@ -13,17 +11,25 @@ const TranslateCStep = @This();
|
||||
pub const base_id = .translate_c;
|
||||
|
||||
step: Step,
|
||||
builder: *Builder,
|
||||
source: build.FileSource,
|
||||
builder: *std.Build,
|
||||
source: std.Build.FileSource,
|
||||
include_dirs: std.ArrayList([]const u8),
|
||||
c_macros: std.ArrayList([]const u8),
|
||||
output_dir: ?[]const u8,
|
||||
out_basename: []const u8,
|
||||
target: CrossTarget = CrossTarget{},
|
||||
output_file: build.GeneratedFile,
|
||||
target: CrossTarget,
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
output_file: std.Build.GeneratedFile,
|
||||
|
||||
pub fn create(builder: *Builder, source: build.FileSource) *TranslateCStep {
|
||||
const self = builder.allocator.create(TranslateCStep) catch unreachable;
|
||||
pub const Options = struct {
|
||||
source_file: std.Build.FileSource,
|
||||
target: CrossTarget,
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
};
|
||||
|
||||
pub fn create(builder: *std.Build, options: Options) *TranslateCStep {
|
||||
const self = builder.allocator.create(TranslateCStep) catch @panic("OOM");
|
||||
const source = options.source_file.dupe(builder);
|
||||
self.* = TranslateCStep{
|
||||
.step = Step.init(.translate_c, "translate-c", builder.allocator, make),
|
||||
.builder = builder,
|
||||
@@ -32,23 +38,36 @@ pub fn create(builder: *Builder, source: build.FileSource) *TranslateCStep {
|
||||
.c_macros = std.ArrayList([]const u8).init(builder.allocator),
|
||||
.output_dir = null,
|
||||
.out_basename = undefined,
|
||||
.output_file = build.GeneratedFile{ .step = &self.step },
|
||||
.target = options.target,
|
||||
.optimize = options.optimize,
|
||||
.output_file = std.Build.GeneratedFile{ .step = &self.step },
|
||||
};
|
||||
source.addStepDependencies(&self.step);
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn setTarget(self: *TranslateCStep, target: CrossTarget) void {
|
||||
self.target = target;
|
||||
}
|
||||
pub const AddExecutableOptions = struct {
|
||||
name: ?[]const u8 = null,
|
||||
version: ?std.builtin.Version = null,
|
||||
target: ?CrossTarget = null,
|
||||
optimize: ?std.builtin.Mode = null,
|
||||
linkage: ?CompileStep.Linkage = null,
|
||||
};
|
||||
|
||||
/// Creates a step to build an executable from the translated source.
|
||||
pub fn addExecutable(self: *TranslateCStep) *LibExeObjStep {
|
||||
return self.builder.addExecutableSource("translated_c", build.FileSource{ .generated = &self.output_file });
|
||||
pub fn addExecutable(self: *TranslateCStep, options: AddExecutableOptions) *CompileStep {
|
||||
return self.builder.addExecutable(.{
|
||||
.root_source_file = .{ .generated = &self.output_file },
|
||||
.name = options.name orelse "translated_c",
|
||||
.version = options.version,
|
||||
.target = options.target orelse self.target,
|
||||
.optimize = options.optimize orelse self.optimize,
|
||||
.linkage = options.linkage,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn addIncludeDir(self: *TranslateCStep, include_dir: []const u8) void {
|
||||
self.include_dirs.append(self.builder.dupePath(include_dir)) catch unreachable;
|
||||
self.include_dirs.append(self.builder.dupePath(include_dir)) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn addCheckFile(self: *TranslateCStep, expected_matches: []const []const u8) *CheckFileStep {
|
||||
@@ -58,13 +77,13 @@ pub fn addCheckFile(self: *TranslateCStep, expected_matches: []const []const u8)
|
||||
/// If the value is omitted, it is set to 1.
|
||||
/// `name` and `value` need not live longer than the function call.
|
||||
pub fn defineCMacro(self: *TranslateCStep, name: []const u8, value: ?[]const u8) void {
|
||||
const macro = build.constructCMacro(self.builder.allocator, name, value);
|
||||
self.c_macros.append(macro) catch unreachable;
|
||||
const macro = std.Build.constructCMacro(self.builder.allocator, name, value);
|
||||
self.c_macros.append(macro) catch @panic("OOM");
|
||||
}
|
||||
|
||||
/// name_and_value looks like [name]=[value]. If the value is omitted, it is set to 1.
|
||||
pub fn defineCMacroRaw(self: *TranslateCStep, name_and_value: []const u8) void {
|
||||
self.c_macros.append(self.builder.dupe(name_and_value)) catch unreachable;
|
||||
self.c_macros.append(self.builder.dupe(name_and_value)) catch @panic("OOM");
|
||||
}
|
||||
|
||||
fn make(step: *Step) !void {
|
||||
@@ -82,6 +101,11 @@ fn make(step: *Step) !void {
|
||||
try argv_list.append(try self.target.zigTriple(self.builder.allocator));
|
||||
}
|
||||
|
||||
switch (self.optimize) {
|
||||
.Debug => {}, // Skip since it's the default.
|
||||
else => try argv_list.append(self.builder.fmt("-O{s}", .{@tagName(self.optimize)})),
|
||||
}
|
||||
|
||||
for (self.include_dirs.items) |include_dir| {
|
||||
try argv_list.append("-I");
|
||||
try argv_list.append(include_dir);
|
||||
@@ -105,8 +129,8 @@ fn make(step: *Step) !void {
|
||||
self.output_dir = fs.path.dirname(output_path).?;
|
||||
}
|
||||
|
||||
self.output_file.path = fs.path.join(
|
||||
self.output_file.path = try fs.path.join(
|
||||
self.builder.allocator,
|
||||
&[_][]const u8{ self.output_dir.?, self.out_basename },
|
||||
) catch unreachable;
|
||||
);
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
const std = @import("../std.zig");
|
||||
const build = @import("../build.zig");
|
||||
const Step = build.Step;
|
||||
const Builder = build.Builder;
|
||||
const Step = std.Build.Step;
|
||||
const fs = std.fs;
|
||||
const ArrayList = std.ArrayList;
|
||||
|
||||
@@ -10,17 +8,17 @@ const WriteFileStep = @This();
|
||||
pub const base_id = .write_file;
|
||||
|
||||
step: Step,
|
||||
builder: *Builder,
|
||||
builder: *std.Build,
|
||||
output_dir: []const u8,
|
||||
files: std.TailQueue(File),
|
||||
|
||||
pub const File = struct {
|
||||
source: build.GeneratedFile,
|
||||
source: std.Build.GeneratedFile,
|
||||
basename: []const u8,
|
||||
bytes: []const u8,
|
||||
};
|
||||
|
||||
pub fn init(builder: *Builder) WriteFileStep {
|
||||
pub fn init(builder: *std.Build) WriteFileStep {
|
||||
return WriteFileStep{
|
||||
.builder = builder,
|
||||
.step = Step.init(.write_file, "writefile", builder.allocator, make),
|
||||
@@ -30,10 +28,10 @@ pub fn init(builder: *Builder) WriteFileStep {
|
||||
}
|
||||
|
||||
pub fn add(self: *WriteFileStep, basename: []const u8, bytes: []const u8) void {
|
||||
const node = self.builder.allocator.create(std.TailQueue(File).Node) catch unreachable;
|
||||
const node = self.builder.allocator.create(std.TailQueue(File).Node) catch @panic("unhandled error");
|
||||
node.* = .{
|
||||
.data = .{
|
||||
.source = build.GeneratedFile{ .step = &self.step },
|
||||
.source = std.Build.GeneratedFile{ .step = &self.step },
|
||||
.basename = self.builder.dupePath(basename),
|
||||
.bytes = self.builder.dupe(bytes),
|
||||
},
|
||||
@@ -43,11 +41,11 @@ pub fn add(self: *WriteFileStep, basename: []const u8, bytes: []const u8) void {
|
||||
}
|
||||
|
||||
/// Gets a file source for the given basename. If the file does not exist, returns `null`.
|
||||
pub fn getFileSource(step: *WriteFileStep, basename: []const u8) ?build.FileSource {
|
||||
pub fn getFileSource(step: *WriteFileStep, basename: []const u8) ?std.Build.FileSource {
|
||||
var it = step.files.first;
|
||||
while (it) |node| : (it = node.next) {
|
||||
if (std.mem.eql(u8, node.data.basename, basename))
|
||||
return build.FileSource{ .generated = &node.data.source };
|
||||
return std.Build.FileSource{ .generated = &node.data.source };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -108,10 +106,10 @@ fn make(step: *Step) !void {
|
||||
});
|
||||
return err;
|
||||
};
|
||||
node.data.source.path = fs.path.join(
|
||||
node.data.source.path = try fs.path.join(
|
||||
self.builder.allocator,
|
||||
&[_][]const u8{ self.output_dir, node.data.basename },
|
||||
) catch unreachable;
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
-1781
@@ -1,1781 +0,0 @@
|
||||
const std = @import("std.zig");
|
||||
const builtin = @import("builtin");
|
||||
const io = std.io;
|
||||
const fs = std.fs;
|
||||
const mem = std.mem;
|
||||
const debug = std.debug;
|
||||
const panic = std.debug.panic;
|
||||
const assert = debug.assert;
|
||||
const log = std.log;
|
||||
const ArrayList = std.ArrayList;
|
||||
const StringHashMap = std.StringHashMap;
|
||||
const Allocator = mem.Allocator;
|
||||
const process = std.process;
|
||||
const EnvMap = std.process.EnvMap;
|
||||
const fmt_lib = std.fmt;
|
||||
const File = std.fs.File;
|
||||
const CrossTarget = std.zig.CrossTarget;
|
||||
const NativeTargetInfo = std.zig.system.NativeTargetInfo;
|
||||
const Sha256 = std.crypto.hash.sha2.Sha256;
|
||||
const ThisModule = @This();
|
||||
|
||||
pub const CheckFileStep = @import("build/CheckFileStep.zig");
|
||||
pub const CheckObjectStep = @import("build/CheckObjectStep.zig");
|
||||
pub const ConfigHeaderStep = @import("build/ConfigHeaderStep.zig");
|
||||
pub const EmulatableRunStep = @import("build/EmulatableRunStep.zig");
|
||||
pub const FmtStep = @import("build/FmtStep.zig");
|
||||
pub const InstallArtifactStep = @import("build/InstallArtifactStep.zig");
|
||||
pub const InstallDirStep = @import("build/InstallDirStep.zig");
|
||||
pub const InstallFileStep = @import("build/InstallFileStep.zig");
|
||||
pub const InstallRawStep = @import("build/InstallRawStep.zig");
|
||||
pub const LibExeObjStep = @import("build/LibExeObjStep.zig");
|
||||
pub const LogStep = @import("build/LogStep.zig");
|
||||
pub const OptionsStep = @import("build/OptionsStep.zig");
|
||||
pub const RemoveDirStep = @import("build/RemoveDirStep.zig");
|
||||
pub const RunStep = @import("build/RunStep.zig");
|
||||
pub const TranslateCStep = @import("build/TranslateCStep.zig");
|
||||
pub const WriteFileStep = @import("build/WriteFileStep.zig");
|
||||
|
||||
pub const Builder = struct {
|
||||
install_tls: TopLevelStep,
|
||||
uninstall_tls: TopLevelStep,
|
||||
allocator: Allocator,
|
||||
user_input_options: UserInputOptionsMap,
|
||||
available_options_map: AvailableOptionsMap,
|
||||
available_options_list: ArrayList(AvailableOption),
|
||||
verbose: bool,
|
||||
verbose_link: bool,
|
||||
verbose_cc: bool,
|
||||
verbose_air: bool,
|
||||
verbose_llvm_ir: bool,
|
||||
verbose_cimport: bool,
|
||||
verbose_llvm_cpu_features: bool,
|
||||
/// The purpose of executing the command is for a human to read compile errors from the terminal
|
||||
prominent_compile_errors: bool,
|
||||
color: enum { auto, on, off } = .auto,
|
||||
reference_trace: ?u32 = null,
|
||||
invalid_user_input: bool,
|
||||
zig_exe: []const u8,
|
||||
default_step: *Step,
|
||||
env_map: *EnvMap,
|
||||
top_level_steps: ArrayList(*TopLevelStep),
|
||||
install_prefix: []const u8,
|
||||
dest_dir: ?[]const u8,
|
||||
lib_dir: []const u8,
|
||||
exe_dir: []const u8,
|
||||
h_dir: []const u8,
|
||||
install_path: []const u8,
|
||||
sysroot: ?[]const u8 = null,
|
||||
search_prefixes: ArrayList([]const u8),
|
||||
libc_file: ?[]const u8 = null,
|
||||
installed_files: ArrayList(InstalledFile),
|
||||
/// Path to the directory containing build.zig.
|
||||
build_root: []const u8,
|
||||
cache_root: []const u8,
|
||||
global_cache_root: []const u8,
|
||||
release_mode: ?std.builtin.Mode,
|
||||
is_release: bool,
|
||||
/// zig lib dir
|
||||
override_lib_dir: ?[]const u8,
|
||||
vcpkg_root: VcpkgRoot = .unattempted,
|
||||
pkg_config_pkg_list: ?(PkgConfigError![]const PkgConfigPkg) = null,
|
||||
args: ?[][]const u8 = null,
|
||||
debug_log_scopes: []const []const u8 = &.{},
|
||||
debug_compile_errors: bool = false,
|
||||
|
||||
/// Experimental. Use system Darling installation to run cross compiled macOS build artifacts.
|
||||
enable_darling: bool = false,
|
||||
/// Use system QEMU installation to run cross compiled foreign architecture build artifacts.
|
||||
enable_qemu: bool = false,
|
||||
/// Darwin. Use Rosetta to run x86_64 macOS build artifacts on arm64 macOS.
|
||||
enable_rosetta: bool = false,
|
||||
/// Use system Wasmtime installation to run cross compiled wasm/wasi build artifacts.
|
||||
enable_wasmtime: bool = false,
|
||||
/// Use system Wine installation to run cross compiled Windows build artifacts.
|
||||
enable_wine: bool = false,
|
||||
/// After following the steps in https://github.com/ziglang/zig/wiki/Updating-libc#glibc,
|
||||
/// this will be the directory $glibc-build-dir/install/glibcs
|
||||
/// Given the example of the aarch64 target, this is the directory
|
||||
/// that contains the path `aarch64-linux-gnu/lib/ld-linux-aarch64.so.1`.
|
||||
glibc_runtimes_dir: ?[]const u8 = null,
|
||||
|
||||
/// Information about the native target. Computed before build() is invoked.
|
||||
host: NativeTargetInfo,
|
||||
|
||||
dep_prefix: []const u8 = "",
|
||||
|
||||
pub const ExecError = error{
|
||||
ReadFailure,
|
||||
ExitCodeFailure,
|
||||
ProcessTerminated,
|
||||
ExecNotSupported,
|
||||
} || std.ChildProcess.SpawnError;
|
||||
|
||||
pub const PkgConfigError = error{
|
||||
PkgConfigCrashed,
|
||||
PkgConfigFailed,
|
||||
PkgConfigNotInstalled,
|
||||
PkgConfigInvalidOutput,
|
||||
};
|
||||
|
||||
pub const PkgConfigPkg = struct {
|
||||
name: []const u8,
|
||||
desc: []const u8,
|
||||
};
|
||||
|
||||
pub const CStd = enum {
|
||||
C89,
|
||||
C99,
|
||||
C11,
|
||||
};
|
||||
|
||||
const UserInputOptionsMap = StringHashMap(UserInputOption);
|
||||
const AvailableOptionsMap = StringHashMap(AvailableOption);
|
||||
|
||||
const AvailableOption = struct {
|
||||
name: []const u8,
|
||||
type_id: TypeId,
|
||||
description: []const u8,
|
||||
/// If the `type_id` is `enum` this provides the list of enum options
|
||||
enum_options: ?[]const []const u8,
|
||||
};
|
||||
|
||||
const UserInputOption = struct {
|
||||
name: []const u8,
|
||||
value: UserValue,
|
||||
used: bool,
|
||||
};
|
||||
|
||||
const UserValue = union(enum) {
|
||||
flag: void,
|
||||
scalar: []const u8,
|
||||
list: ArrayList([]const u8),
|
||||
};
|
||||
|
||||
const TypeId = enum {
|
||||
bool,
|
||||
int,
|
||||
float,
|
||||
@"enum",
|
||||
string,
|
||||
list,
|
||||
};
|
||||
|
||||
const TopLevelStep = struct {
|
||||
pub const base_id = .top_level;
|
||||
|
||||
step: Step,
|
||||
description: []const u8,
|
||||
};
|
||||
|
||||
pub const DirList = struct {
|
||||
lib_dir: ?[]const u8 = null,
|
||||
exe_dir: ?[]const u8 = null,
|
||||
include_dir: ?[]const u8 = null,
|
||||
};
|
||||
|
||||
pub fn create(
|
||||
allocator: Allocator,
|
||||
zig_exe: []const u8,
|
||||
build_root: []const u8,
|
||||
cache_root: []const u8,
|
||||
global_cache_root: []const u8,
|
||||
) !*Builder {
|
||||
const env_map = try allocator.create(EnvMap);
|
||||
env_map.* = try process.getEnvMap(allocator);
|
||||
|
||||
const host = try NativeTargetInfo.detect(.{});
|
||||
|
||||
const self = try allocator.create(Builder);
|
||||
self.* = Builder{
|
||||
.zig_exe = zig_exe,
|
||||
.build_root = build_root,
|
||||
.cache_root = try fs.path.relative(allocator, build_root, cache_root),
|
||||
.global_cache_root = global_cache_root,
|
||||
.verbose = false,
|
||||
.verbose_link = false,
|
||||
.verbose_cc = false,
|
||||
.verbose_air = false,
|
||||
.verbose_llvm_ir = false,
|
||||
.verbose_cimport = false,
|
||||
.verbose_llvm_cpu_features = false,
|
||||
.prominent_compile_errors = false,
|
||||
.invalid_user_input = false,
|
||||
.allocator = allocator,
|
||||
.user_input_options = UserInputOptionsMap.init(allocator),
|
||||
.available_options_map = AvailableOptionsMap.init(allocator),
|
||||
.available_options_list = ArrayList(AvailableOption).init(allocator),
|
||||
.top_level_steps = ArrayList(*TopLevelStep).init(allocator),
|
||||
.default_step = undefined,
|
||||
.env_map = env_map,
|
||||
.search_prefixes = ArrayList([]const u8).init(allocator),
|
||||
.install_prefix = undefined,
|
||||
.lib_dir = undefined,
|
||||
.exe_dir = undefined,
|
||||
.h_dir = undefined,
|
||||
.dest_dir = env_map.get("DESTDIR"),
|
||||
.installed_files = ArrayList(InstalledFile).init(allocator),
|
||||
.install_tls = TopLevelStep{
|
||||
.step = Step.initNoOp(.top_level, "install", allocator),
|
||||
.description = "Copy build artifacts to prefix path",
|
||||
},
|
||||
.uninstall_tls = TopLevelStep{
|
||||
.step = Step.init(.top_level, "uninstall", allocator, makeUninstall),
|
||||
.description = "Remove build artifacts from prefix path",
|
||||
},
|
||||
.release_mode = null,
|
||||
.is_release = false,
|
||||
.override_lib_dir = null,
|
||||
.install_path = undefined,
|
||||
.args = null,
|
||||
.host = host,
|
||||
};
|
||||
try self.top_level_steps.append(&self.install_tls);
|
||||
try self.top_level_steps.append(&self.uninstall_tls);
|
||||
self.default_step = &self.install_tls.step;
|
||||
return self;
|
||||
}
|
||||
|
||||
fn createChild(
|
||||
parent: *Builder,
|
||||
dep_name: []const u8,
|
||||
build_root: []const u8,
|
||||
args: anytype,
|
||||
) !*Builder {
|
||||
const child = try createChildOnly(parent, dep_name, build_root);
|
||||
try applyArgs(child, args);
|
||||
return child;
|
||||
}
|
||||
|
||||
fn createChildOnly(parent: *Builder, dep_name: []const u8, build_root: []const u8) !*Builder {
|
||||
const allocator = parent.allocator;
|
||||
const child = try allocator.create(Builder);
|
||||
child.* = .{
|
||||
.allocator = allocator,
|
||||
.install_tls = .{
|
||||
.step = Step.initNoOp(.top_level, "install", allocator),
|
||||
.description = "Copy build artifacts to prefix path",
|
||||
},
|
||||
.uninstall_tls = .{
|
||||
.step = Step.init(.top_level, "uninstall", allocator, makeUninstall),
|
||||
.description = "Remove build artifacts from prefix path",
|
||||
},
|
||||
.user_input_options = UserInputOptionsMap.init(allocator),
|
||||
.available_options_map = AvailableOptionsMap.init(allocator),
|
||||
.available_options_list = ArrayList(AvailableOption).init(allocator),
|
||||
.verbose = parent.verbose,
|
||||
.verbose_link = parent.verbose_link,
|
||||
.verbose_cc = parent.verbose_cc,
|
||||
.verbose_air = parent.verbose_air,
|
||||
.verbose_llvm_ir = parent.verbose_llvm_ir,
|
||||
.verbose_cimport = parent.verbose_cimport,
|
||||
.verbose_llvm_cpu_features = parent.verbose_llvm_cpu_features,
|
||||
.prominent_compile_errors = parent.prominent_compile_errors,
|
||||
.color = parent.color,
|
||||
.reference_trace = parent.reference_trace,
|
||||
.invalid_user_input = false,
|
||||
.zig_exe = parent.zig_exe,
|
||||
.default_step = undefined,
|
||||
.env_map = parent.env_map,
|
||||
.top_level_steps = ArrayList(*TopLevelStep).init(allocator),
|
||||
.install_prefix = undefined,
|
||||
.dest_dir = parent.dest_dir,
|
||||
.lib_dir = parent.lib_dir,
|
||||
.exe_dir = parent.exe_dir,
|
||||
.h_dir = parent.h_dir,
|
||||
.install_path = parent.install_path,
|
||||
.sysroot = parent.sysroot,
|
||||
.search_prefixes = ArrayList([]const u8).init(allocator),
|
||||
.libc_file = parent.libc_file,
|
||||
.installed_files = ArrayList(InstalledFile).init(allocator),
|
||||
.build_root = build_root,
|
||||
.cache_root = parent.cache_root,
|
||||
.global_cache_root = parent.global_cache_root,
|
||||
.release_mode = parent.release_mode,
|
||||
.is_release = parent.is_release,
|
||||
.override_lib_dir = parent.override_lib_dir,
|
||||
.debug_log_scopes = parent.debug_log_scopes,
|
||||
.debug_compile_errors = parent.debug_compile_errors,
|
||||
.enable_darling = parent.enable_darling,
|
||||
.enable_qemu = parent.enable_qemu,
|
||||
.enable_rosetta = parent.enable_rosetta,
|
||||
.enable_wasmtime = parent.enable_wasmtime,
|
||||
.enable_wine = parent.enable_wine,
|
||||
.glibc_runtimes_dir = parent.glibc_runtimes_dir,
|
||||
.host = parent.host,
|
||||
.dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }),
|
||||
};
|
||||
try child.top_level_steps.append(&child.install_tls);
|
||||
try child.top_level_steps.append(&child.uninstall_tls);
|
||||
child.default_step = &child.install_tls.step;
|
||||
return child;
|
||||
}
|
||||
|
||||
fn applyArgs(b: *Builder, args: anytype) !void {
|
||||
// TODO this function is the way that a build.zig file communicates
|
||||
// options to its dependencies. It is the programmatic way to give
|
||||
// command line arguments to a build.zig script.
|
||||
_ = args;
|
||||
const Hasher = std.crypto.auth.siphash.SipHash128(1, 3);
|
||||
// Random bytes to make unique. Refresh this with new random bytes when
|
||||
// implementation is modified in a non-backwards-compatible way.
|
||||
var hash = Hasher.init("ZaEsvQ5ClaA2IdH9");
|
||||
hash.update(b.dep_prefix);
|
||||
// TODO additionally update the hash with `args`.
|
||||
|
||||
var digest: [16]u8 = undefined;
|
||||
hash.final(&digest);
|
||||
var hash_basename: [digest.len * 2]u8 = undefined;
|
||||
_ = std.fmt.bufPrint(&hash_basename, "{s}", .{std.fmt.fmtSliceHexLower(&digest)}) catch
|
||||
unreachable;
|
||||
|
||||
const install_prefix = b.pathJoin(&.{ b.cache_root, "i", &hash_basename });
|
||||
b.resolveInstallPrefix(install_prefix, .{});
|
||||
}
|
||||
|
||||
pub fn destroy(self: *Builder) void {
|
||||
self.env_map.deinit();
|
||||
self.top_level_steps.deinit();
|
||||
self.allocator.destroy(self);
|
||||
}
|
||||
|
||||
/// This function is intended to be called by lib/build_runner.zig, not a build.zig file.
|
||||
pub fn resolveInstallPrefix(self: *Builder, install_prefix: ?[]const u8, dir_list: DirList) void {
|
||||
if (self.dest_dir) |dest_dir| {
|
||||
self.install_prefix = install_prefix orelse "/usr";
|
||||
self.install_path = self.pathJoin(&.{ dest_dir, self.install_prefix });
|
||||
} else {
|
||||
self.install_prefix = install_prefix orelse
|
||||
(self.pathJoin(&.{ self.build_root, "zig-out" }));
|
||||
self.install_path = self.install_prefix;
|
||||
}
|
||||
|
||||
var lib_list = [_][]const u8{ self.install_path, "lib" };
|
||||
var exe_list = [_][]const u8{ self.install_path, "bin" };
|
||||
var h_list = [_][]const u8{ self.install_path, "include" };
|
||||
|
||||
if (dir_list.lib_dir) |dir| {
|
||||
if (std.fs.path.isAbsolute(dir)) lib_list[0] = self.dest_dir orelse "";
|
||||
lib_list[1] = dir;
|
||||
}
|
||||
|
||||
if (dir_list.exe_dir) |dir| {
|
||||
if (std.fs.path.isAbsolute(dir)) exe_list[0] = self.dest_dir orelse "";
|
||||
exe_list[1] = dir;
|
||||
}
|
||||
|
||||
if (dir_list.include_dir) |dir| {
|
||||
if (std.fs.path.isAbsolute(dir)) h_list[0] = self.dest_dir orelse "";
|
||||
h_list[1] = dir;
|
||||
}
|
||||
|
||||
self.lib_dir = self.pathJoin(&lib_list);
|
||||
self.exe_dir = self.pathJoin(&exe_list);
|
||||
self.h_dir = self.pathJoin(&h_list);
|
||||
}
|
||||
|
||||
fn convertOptionalPathToFileSource(path: ?[]const u8) ?FileSource {
|
||||
return if (path) |p|
|
||||
FileSource{ .path = p }
|
||||
else
|
||||
null;
|
||||
}
|
||||
|
||||
pub fn addExecutable(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
|
||||
return addExecutableSource(self, name, convertOptionalPathToFileSource(root_src));
|
||||
}
|
||||
|
||||
pub fn addExecutableSource(builder: *Builder, name: []const u8, root_src: ?FileSource) *LibExeObjStep {
|
||||
return LibExeObjStep.createExecutable(builder, name, root_src);
|
||||
}
|
||||
|
||||
pub fn addOptions(self: *Builder) *OptionsStep {
|
||||
return OptionsStep.create(self);
|
||||
}
|
||||
|
||||
pub fn addObject(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
|
||||
return addObjectSource(self, name, convertOptionalPathToFileSource(root_src));
|
||||
}
|
||||
|
||||
pub fn addObjectSource(builder: *Builder, name: []const u8, root_src: ?FileSource) *LibExeObjStep {
|
||||
return LibExeObjStep.createObject(builder, name, root_src);
|
||||
}
|
||||
|
||||
pub fn addSharedLibrary(
|
||||
self: *Builder,
|
||||
name: []const u8,
|
||||
root_src: ?[]const u8,
|
||||
kind: LibExeObjStep.SharedLibKind,
|
||||
) *LibExeObjStep {
|
||||
return addSharedLibrarySource(self, name, convertOptionalPathToFileSource(root_src), kind);
|
||||
}
|
||||
|
||||
pub fn addSharedLibrarySource(
|
||||
self: *Builder,
|
||||
name: []const u8,
|
||||
root_src: ?FileSource,
|
||||
kind: LibExeObjStep.SharedLibKind,
|
||||
) *LibExeObjStep {
|
||||
return LibExeObjStep.createSharedLibrary(self, name, root_src, kind);
|
||||
}
|
||||
|
||||
pub fn addStaticLibrary(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
|
||||
return addStaticLibrarySource(self, name, convertOptionalPathToFileSource(root_src));
|
||||
}
|
||||
|
||||
pub fn addStaticLibrarySource(self: *Builder, name: []const u8, root_src: ?FileSource) *LibExeObjStep {
|
||||
return LibExeObjStep.createStaticLibrary(self, name, root_src);
|
||||
}
|
||||
|
||||
pub fn addTest(self: *Builder, root_src: []const u8) *LibExeObjStep {
|
||||
return LibExeObjStep.createTest(self, "test", .{ .path = root_src });
|
||||
}
|
||||
|
||||
pub fn addTestSource(self: *Builder, root_src: FileSource) *LibExeObjStep {
|
||||
return LibExeObjStep.createTest(self, "test", root_src.dupe(self));
|
||||
}
|
||||
|
||||
pub fn addTestExe(self: *Builder, name: []const u8, root_src: []const u8) *LibExeObjStep {
|
||||
return LibExeObjStep.createTestExe(self, name, .{ .path = root_src });
|
||||
}
|
||||
|
||||
pub fn addTestExeSource(self: *Builder, name: []const u8, root_src: FileSource) *LibExeObjStep {
|
||||
return LibExeObjStep.createTestExe(self, name, root_src.dupe(self));
|
||||
}
|
||||
|
||||
pub fn addAssemble(self: *Builder, name: []const u8, src: []const u8) *LibExeObjStep {
|
||||
return addAssembleSource(self, name, .{ .path = src });
|
||||
}
|
||||
|
||||
pub fn addAssembleSource(self: *Builder, name: []const u8, src: FileSource) *LibExeObjStep {
|
||||
const obj_step = LibExeObjStep.createObject(self, name, null);
|
||||
obj_step.addAssemblyFileSource(src.dupe(self));
|
||||
return obj_step;
|
||||
}
|
||||
|
||||
/// Initializes a RunStep with argv, which must at least have the path to the
|
||||
/// executable. More command line arguments can be added with `addArg`,
|
||||
/// `addArgs`, and `addArtifactArg`.
|
||||
/// Be careful using this function, as it introduces a system dependency.
|
||||
/// To run an executable built with zig build, see `LibExeObjStep.run`.
|
||||
pub fn addSystemCommand(self: *Builder, argv: []const []const u8) *RunStep {
|
||||
assert(argv.len >= 1);
|
||||
const run_step = RunStep.create(self, self.fmt("run {s}", .{argv[0]}));
|
||||
run_step.addArgs(argv);
|
||||
return run_step;
|
||||
}
|
||||
|
||||
pub fn addConfigHeader(
|
||||
b: *Builder,
|
||||
source: FileSource,
|
||||
style: ConfigHeaderStep.Style,
|
||||
values: anytype,
|
||||
) *ConfigHeaderStep {
|
||||
const config_header_step = ConfigHeaderStep.create(b, source, style);
|
||||
config_header_step.addValues(values);
|
||||
return config_header_step;
|
||||
}
|
||||
|
||||
/// Allocator.dupe without the need to handle out of memory.
|
||||
pub fn dupe(self: *Builder, bytes: []const u8) []u8 {
|
||||
return self.allocator.dupe(u8, bytes) catch unreachable;
|
||||
}
|
||||
|
||||
/// Duplicates an array of strings without the need to handle out of memory.
|
||||
pub fn dupeStrings(self: *Builder, strings: []const []const u8) [][]u8 {
|
||||
const array = self.allocator.alloc([]u8, strings.len) catch unreachable;
|
||||
for (strings) |s, i| {
|
||||
array[i] = self.dupe(s);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/// Duplicates a path and converts all slashes to the OS's canonical path separator.
|
||||
pub fn dupePath(self: *Builder, bytes: []const u8) []u8 {
|
||||
const the_copy = self.dupe(bytes);
|
||||
for (the_copy) |*byte| {
|
||||
switch (byte.*) {
|
||||
'/', '\\' => byte.* = fs.path.sep,
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
return the_copy;
|
||||
}
|
||||
|
||||
/// Duplicates a package recursively.
|
||||
pub fn dupePkg(self: *Builder, package: Pkg) Pkg {
|
||||
var the_copy = Pkg{
|
||||
.name = self.dupe(package.name),
|
||||
.source = package.source.dupe(self),
|
||||
};
|
||||
|
||||
if (package.dependencies) |dependencies| {
|
||||
const new_dependencies = self.allocator.alloc(Pkg, dependencies.len) catch unreachable;
|
||||
the_copy.dependencies = new_dependencies;
|
||||
|
||||
for (dependencies) |dep_package, i| {
|
||||
new_dependencies[i] = self.dupePkg(dep_package);
|
||||
}
|
||||
}
|
||||
return the_copy;
|
||||
}
|
||||
|
||||
pub fn addWriteFile(self: *Builder, file_path: []const u8, data: []const u8) *WriteFileStep {
|
||||
const write_file_step = self.addWriteFiles();
|
||||
write_file_step.add(file_path, data);
|
||||
return write_file_step;
|
||||
}
|
||||
|
||||
pub fn addWriteFiles(self: *Builder) *WriteFileStep {
|
||||
const write_file_step = self.allocator.create(WriteFileStep) catch unreachable;
|
||||
write_file_step.* = WriteFileStep.init(self);
|
||||
return write_file_step;
|
||||
}
|
||||
|
||||
pub fn addLog(self: *Builder, comptime format: []const u8, args: anytype) *LogStep {
|
||||
const data = self.fmt(format, args);
|
||||
const log_step = self.allocator.create(LogStep) catch unreachable;
|
||||
log_step.* = LogStep.init(self, data);
|
||||
return log_step;
|
||||
}
|
||||
|
||||
pub fn addRemoveDirTree(self: *Builder, dir_path: []const u8) *RemoveDirStep {
|
||||
const remove_dir_step = self.allocator.create(RemoveDirStep) catch unreachable;
|
||||
remove_dir_step.* = RemoveDirStep.init(self, dir_path);
|
||||
return remove_dir_step;
|
||||
}
|
||||
|
||||
pub fn addFmt(self: *Builder, paths: []const []const u8) *FmtStep {
|
||||
return FmtStep.create(self, paths);
|
||||
}
|
||||
|
||||
pub fn addTranslateC(self: *Builder, source: FileSource) *TranslateCStep {
|
||||
return TranslateCStep.create(self, source.dupe(self));
|
||||
}
|
||||
|
||||
pub fn version(self: *const Builder, major: u32, minor: u32, patch: u32) LibExeObjStep.SharedLibKind {
|
||||
_ = self;
|
||||
return .{
|
||||
.versioned = .{
|
||||
.major = major,
|
||||
.minor = minor,
|
||||
.patch = patch,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn make(self: *Builder, step_names: []const []const u8) !void {
|
||||
try self.makePath(self.cache_root);
|
||||
|
||||
var wanted_steps = ArrayList(*Step).init(self.allocator);
|
||||
defer wanted_steps.deinit();
|
||||
|
||||
if (step_names.len == 0) {
|
||||
try wanted_steps.append(self.default_step);
|
||||
} else {
|
||||
for (step_names) |step_name| {
|
||||
const s = try self.getTopLevelStepByName(step_name);
|
||||
try wanted_steps.append(s);
|
||||
}
|
||||
}
|
||||
|
||||
for (wanted_steps.items) |s| {
|
||||
try self.makeOneStep(s);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getInstallStep(self: *Builder) *Step {
|
||||
return &self.install_tls.step;
|
||||
}
|
||||
|
||||
pub fn getUninstallStep(self: *Builder) *Step {
|
||||
return &self.uninstall_tls.step;
|
||||
}
|
||||
|
||||
fn makeUninstall(uninstall_step: *Step) anyerror!void {
|
||||
const uninstall_tls = @fieldParentPtr(TopLevelStep, "step", uninstall_step);
|
||||
const self = @fieldParentPtr(Builder, "uninstall_tls", uninstall_tls);
|
||||
|
||||
for (self.installed_files.items) |installed_file| {
|
||||
const full_path = self.getInstallPath(installed_file.dir, installed_file.path);
|
||||
if (self.verbose) {
|
||||
log.info("rm {s}", .{full_path});
|
||||
}
|
||||
fs.cwd().deleteTree(full_path) catch {};
|
||||
}
|
||||
|
||||
// TODO remove empty directories
|
||||
}
|
||||
|
||||
fn makeOneStep(self: *Builder, s: *Step) anyerror!void {
|
||||
if (s.loop_flag) {
|
||||
log.err("Dependency loop detected:\n {s}", .{s.name});
|
||||
return error.DependencyLoopDetected;
|
||||
}
|
||||
s.loop_flag = true;
|
||||
|
||||
for (s.dependencies.items) |dep| {
|
||||
self.makeOneStep(dep) catch |err| {
|
||||
if (err == error.DependencyLoopDetected) {
|
||||
log.err(" {s}", .{s.name});
|
||||
}
|
||||
return err;
|
||||
};
|
||||
}
|
||||
|
||||
s.loop_flag = false;
|
||||
|
||||
try s.make();
|
||||
}
|
||||
|
||||
fn getTopLevelStepByName(self: *Builder, name: []const u8) !*Step {
|
||||
for (self.top_level_steps.items) |top_level_step| {
|
||||
if (mem.eql(u8, top_level_step.step.name, name)) {
|
||||
return &top_level_step.step;
|
||||
}
|
||||
}
|
||||
log.err("Cannot run step '{s}' because it does not exist", .{name});
|
||||
return error.InvalidStepName;
|
||||
}
|
||||
|
||||
pub fn option(self: *Builder, comptime T: type, name_raw: []const u8, description_raw: []const u8) ?T {
|
||||
const name = self.dupe(name_raw);
|
||||
const description = self.dupe(description_raw);
|
||||
const type_id = comptime typeToEnum(T);
|
||||
const enum_options = if (type_id == .@"enum") blk: {
|
||||
const fields = comptime std.meta.fields(T);
|
||||
var options = ArrayList([]const u8).initCapacity(self.allocator, fields.len) catch unreachable;
|
||||
|
||||
inline for (fields) |field| {
|
||||
options.appendAssumeCapacity(field.name);
|
||||
}
|
||||
|
||||
break :blk options.toOwnedSlice() catch unreachable;
|
||||
} else null;
|
||||
const available_option = AvailableOption{
|
||||
.name = name,
|
||||
.type_id = type_id,
|
||||
.description = description,
|
||||
.enum_options = enum_options,
|
||||
};
|
||||
if ((self.available_options_map.fetchPut(name, available_option) catch unreachable) != null) {
|
||||
panic("Option '{s}' declared twice", .{name});
|
||||
}
|
||||
self.available_options_list.append(available_option) catch unreachable;
|
||||
|
||||
const option_ptr = self.user_input_options.getPtr(name) orelse return null;
|
||||
option_ptr.used = true;
|
||||
switch (type_id) {
|
||||
.bool => switch (option_ptr.value) {
|
||||
.flag => return true,
|
||||
.scalar => |s| {
|
||||
if (mem.eql(u8, s, "true")) {
|
||||
return true;
|
||||
} else if (mem.eql(u8, s, "false")) {
|
||||
return false;
|
||||
} else {
|
||||
log.err("Expected -D{s} to be a boolean, but received '{s}'\n", .{ name, s });
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
}
|
||||
},
|
||||
.list => {
|
||||
log.err("Expected -D{s} to be a boolean, but received a list.\n", .{name});
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
},
|
||||
},
|
||||
.int => switch (option_ptr.value) {
|
||||
.flag => {
|
||||
log.err("Expected -D{s} to be an integer, but received a boolean.\n", .{name});
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
},
|
||||
.scalar => |s| {
|
||||
const n = std.fmt.parseInt(T, s, 10) catch |err| switch (err) {
|
||||
error.Overflow => {
|
||||
log.err("-D{s} value {s} cannot fit into type {s}.\n", .{ name, s, @typeName(T) });
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
},
|
||||
else => {
|
||||
log.err("Expected -D{s} to be an integer of type {s}.\n", .{ name, @typeName(T) });
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
},
|
||||
};
|
||||
return n;
|
||||
},
|
||||
.list => {
|
||||
log.err("Expected -D{s} to be an integer, but received a list.\n", .{name});
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
},
|
||||
},
|
||||
.float => switch (option_ptr.value) {
|
||||
.flag => {
|
||||
log.err("Expected -D{s} to be a float, but received a boolean.\n", .{name});
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
},
|
||||
.scalar => |s| {
|
||||
const n = std.fmt.parseFloat(T, s) catch {
|
||||
log.err("Expected -D{s} to be a float of type {s}.\n", .{ name, @typeName(T) });
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
};
|
||||
return n;
|
||||
},
|
||||
.list => {
|
||||
log.err("Expected -D{s} to be a float, but received a list.\n", .{name});
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
},
|
||||
},
|
||||
.@"enum" => switch (option_ptr.value) {
|
||||
.flag => {
|
||||
log.err("Expected -D{s} to be a string, but received a boolean.\n", .{name});
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
},
|
||||
.scalar => |s| {
|
||||
if (std.meta.stringToEnum(T, s)) |enum_lit| {
|
||||
return enum_lit;
|
||||
} else {
|
||||
log.err("Expected -D{s} to be of type {s}.\n", .{ name, @typeName(T) });
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
}
|
||||
},
|
||||
.list => {
|
||||
log.err("Expected -D{s} to be a string, but received a list.\n", .{name});
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
},
|
||||
},
|
||||
.string => switch (option_ptr.value) {
|
||||
.flag => {
|
||||
log.err("Expected -D{s} to be a string, but received a boolean.\n", .{name});
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
},
|
||||
.list => {
|
||||
log.err("Expected -D{s} to be a string, but received a list.\n", .{name});
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
},
|
||||
.scalar => |s| return s,
|
||||
},
|
||||
.list => switch (option_ptr.value) {
|
||||
.flag => {
|
||||
log.err("Expected -D{s} to be a list, but received a boolean.\n", .{name});
|
||||
self.markInvalidUserInput();
|
||||
return null;
|
||||
},
|
||||
.scalar => |s| {
|
||||
return self.allocator.dupe([]const u8, &[_][]const u8{s}) catch unreachable;
|
||||
},
|
||||
.list => |lst| return lst.items,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn step(self: *Builder, name: []const u8, description: []const u8) *Step {
|
||||
const step_info = self.allocator.create(TopLevelStep) catch unreachable;
|
||||
step_info.* = TopLevelStep{
|
||||
.step = Step.initNoOp(.top_level, name, self.allocator),
|
||||
.description = self.dupe(description),
|
||||
};
|
||||
self.top_level_steps.append(step_info) catch unreachable;
|
||||
return &step_info.step;
|
||||
}
|
||||
|
||||
/// This provides the -Drelease option to the build user and does not give them the choice.
|
||||
pub fn setPreferredReleaseMode(self: *Builder, mode: std.builtin.Mode) void {
|
||||
if (self.release_mode != null) {
|
||||
@panic("setPreferredReleaseMode must be called before standardReleaseOptions and may not be called twice");
|
||||
}
|
||||
const description = self.fmt("Create a release build ({s})", .{@tagName(mode)});
|
||||
self.is_release = self.option(bool, "release", description) orelse false;
|
||||
self.release_mode = if (self.is_release) mode else std.builtin.Mode.Debug;
|
||||
}
|
||||
|
||||
/// If you call this without first calling `setPreferredReleaseMode` then it gives the build user
|
||||
/// the choice of what kind of release.
|
||||
pub fn standardReleaseOptions(self: *Builder) std.builtin.Mode {
|
||||
if (self.release_mode) |mode| return mode;
|
||||
|
||||
const release_safe = self.option(bool, "release-safe", "Optimizations on and safety on") orelse false;
|
||||
const release_fast = self.option(bool, "release-fast", "Optimizations on and safety off") orelse false;
|
||||
const release_small = self.option(bool, "release-small", "Size optimizations on and safety off") orelse false;
|
||||
|
||||
const mode = if (release_safe and !release_fast and !release_small)
|
||||
std.builtin.Mode.ReleaseSafe
|
||||
else if (release_fast and !release_safe and !release_small)
|
||||
std.builtin.Mode.ReleaseFast
|
||||
else if (release_small and !release_fast and !release_safe)
|
||||
std.builtin.Mode.ReleaseSmall
|
||||
else if (!release_fast and !release_safe and !release_small)
|
||||
std.builtin.Mode.Debug
|
||||
else x: {
|
||||
log.err("Multiple release modes (of -Drelease-safe, -Drelease-fast and -Drelease-small)\n", .{});
|
||||
self.markInvalidUserInput();
|
||||
break :x std.builtin.Mode.Debug;
|
||||
};
|
||||
self.is_release = mode != .Debug;
|
||||
self.release_mode = mode;
|
||||
return mode;
|
||||
}
|
||||
|
||||
pub const StandardTargetOptionsArgs = struct {
|
||||
whitelist: ?[]const CrossTarget = null,
|
||||
|
||||
default_target: CrossTarget = CrossTarget{},
|
||||
};
|
||||
|
||||
/// Exposes standard `zig build` options for choosing a target.
|
||||
pub fn standardTargetOptions(self: *Builder, args: StandardTargetOptionsArgs) CrossTarget {
|
||||
const maybe_triple = self.option(
|
||||
[]const u8,
|
||||
"target",
|
||||
"The CPU architecture, OS, and ABI to build for",
|
||||
);
|
||||
const mcpu = self.option([]const u8, "cpu", "Target CPU features to add or subtract");
|
||||
|
||||
if (maybe_triple == null and mcpu == null) {
|
||||
return args.default_target;
|
||||
}
|
||||
|
||||
const triple = maybe_triple orelse "native";
|
||||
|
||||
var diags: CrossTarget.ParseOptions.Diagnostics = .{};
|
||||
const selected_target = CrossTarget.parse(.{
|
||||
.arch_os_abi = triple,
|
||||
.cpu_features = mcpu,
|
||||
.diagnostics = &diags,
|
||||
}) catch |err| switch (err) {
|
||||
error.UnknownCpuModel => {
|
||||
log.err("Unknown CPU: '{s}'\nAvailable CPUs for architecture '{s}':", .{
|
||||
diags.cpu_name.?,
|
||||
@tagName(diags.arch.?),
|
||||
});
|
||||
for (diags.arch.?.allCpuModels()) |cpu| {
|
||||
log.err(" {s}", .{cpu.name});
|
||||
}
|
||||
self.markInvalidUserInput();
|
||||
return args.default_target;
|
||||
},
|
||||
error.UnknownCpuFeature => {
|
||||
log.err(
|
||||
\\Unknown CPU feature: '{s}'
|
||||
\\Available CPU features for architecture '{s}':
|
||||
\\
|
||||
, .{
|
||||
diags.unknown_feature_name.?,
|
||||
@tagName(diags.arch.?),
|
||||
});
|
||||
for (diags.arch.?.allFeaturesList()) |feature| {
|
||||
log.err(" {s}: {s}", .{ feature.name, feature.description });
|
||||
}
|
||||
self.markInvalidUserInput();
|
||||
return args.default_target;
|
||||
},
|
||||
error.UnknownOperatingSystem => {
|
||||
log.err(
|
||||
\\Unknown OS: '{s}'
|
||||
\\Available operating systems:
|
||||
\\
|
||||
, .{diags.os_name.?});
|
||||
inline for (std.meta.fields(std.Target.Os.Tag)) |field| {
|
||||
log.err(" {s}", .{field.name});
|
||||
}
|
||||
self.markInvalidUserInput();
|
||||
return args.default_target;
|
||||
},
|
||||
else => |e| {
|
||||
log.err("Unable to parse target '{s}': {s}\n", .{ triple, @errorName(e) });
|
||||
self.markInvalidUserInput();
|
||||
return args.default_target;
|
||||
},
|
||||
};
|
||||
|
||||
const selected_canonicalized_triple = selected_target.zigTriple(self.allocator) catch unreachable;
|
||||
|
||||
if (args.whitelist) |list| whitelist_check: {
|
||||
// Make sure it's a match of one of the list.
|
||||
var mismatch_triple = true;
|
||||
var mismatch_cpu_features = true;
|
||||
var whitelist_item = CrossTarget{};
|
||||
for (list) |t| {
|
||||
mismatch_cpu_features = true;
|
||||
mismatch_triple = true;
|
||||
|
||||
const t_triple = t.zigTriple(self.allocator) catch unreachable;
|
||||
if (mem.eql(u8, t_triple, selected_canonicalized_triple)) {
|
||||
mismatch_triple = false;
|
||||
whitelist_item = t;
|
||||
if (t.getCpuFeatures().isSuperSetOf(selected_target.getCpuFeatures())) {
|
||||
mismatch_cpu_features = false;
|
||||
break :whitelist_check;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mismatch_triple) {
|
||||
log.err("Chosen target '{s}' does not match one of the supported targets:", .{
|
||||
selected_canonicalized_triple,
|
||||
});
|
||||
for (list) |t| {
|
||||
const t_triple = t.zigTriple(self.allocator) catch unreachable;
|
||||
log.err(" {s}", .{t_triple});
|
||||
}
|
||||
} else {
|
||||
assert(mismatch_cpu_features);
|
||||
const whitelist_cpu = whitelist_item.getCpu();
|
||||
const selected_cpu = selected_target.getCpu();
|
||||
log.err("Chosen CPU model '{s}' does not match one of the supported targets:", .{
|
||||
selected_cpu.model.name,
|
||||
});
|
||||
log.err(" Supported feature Set: ", .{});
|
||||
const all_features = whitelist_cpu.arch.allFeaturesList();
|
||||
var populated_cpu_features = whitelist_cpu.model.features;
|
||||
populated_cpu_features.populateDependencies(all_features);
|
||||
for (all_features) |feature, i_usize| {
|
||||
const i = @intCast(std.Target.Cpu.Feature.Set.Index, i_usize);
|
||||
const in_cpu_set = populated_cpu_features.isEnabled(i);
|
||||
if (in_cpu_set) {
|
||||
log.err("{s} ", .{feature.name});
|
||||
}
|
||||
}
|
||||
log.err(" Remove: ", .{});
|
||||
for (all_features) |feature, i_usize| {
|
||||
const i = @intCast(std.Target.Cpu.Feature.Set.Index, i_usize);
|
||||
const in_cpu_set = populated_cpu_features.isEnabled(i);
|
||||
const in_actual_set = selected_cpu.features.isEnabled(i);
|
||||
if (in_actual_set and !in_cpu_set) {
|
||||
log.err("{s} ", .{feature.name});
|
||||
}
|
||||
}
|
||||
}
|
||||
self.markInvalidUserInput();
|
||||
return args.default_target;
|
||||
}
|
||||
|
||||
return selected_target;
|
||||
}
|
||||
|
||||
pub fn addUserInputOption(self: *Builder, name_raw: []const u8, value_raw: []const u8) !bool {
|
||||
const name = self.dupe(name_raw);
|
||||
const value = self.dupe(value_raw);
|
||||
const gop = try self.user_input_options.getOrPut(name);
|
||||
if (!gop.found_existing) {
|
||||
gop.value_ptr.* = UserInputOption{
|
||||
.name = name,
|
||||
.value = .{ .scalar = value },
|
||||
.used = false,
|
||||
};
|
||||
return false;
|
||||
}
|
||||
|
||||
// option already exists
|
||||
switch (gop.value_ptr.value) {
|
||||
.scalar => |s| {
|
||||
// turn it into a list
|
||||
var list = ArrayList([]const u8).init(self.allocator);
|
||||
list.append(s) catch unreachable;
|
||||
list.append(value) catch unreachable;
|
||||
self.user_input_options.put(name, .{
|
||||
.name = name,
|
||||
.value = .{ .list = list },
|
||||
.used = false,
|
||||
}) catch unreachable;
|
||||
},
|
||||
.list => |*list| {
|
||||
// append to the list
|
||||
list.append(value) catch unreachable;
|
||||
self.user_input_options.put(name, .{
|
||||
.name = name,
|
||||
.value = .{ .list = list.* },
|
||||
.used = false,
|
||||
}) catch unreachable;
|
||||
},
|
||||
.flag => {
|
||||
log.warn("Option '-D{s}={s}' conflicts with flag '-D{s}'.", .{ name, value, name });
|
||||
return true;
|
||||
},
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn addUserInputFlag(self: *Builder, name_raw: []const u8) !bool {
|
||||
const name = self.dupe(name_raw);
|
||||
const gop = try self.user_input_options.getOrPut(name);
|
||||
if (!gop.found_existing) {
|
||||
gop.value_ptr.* = .{
|
||||
.name = name,
|
||||
.value = .{ .flag = {} },
|
||||
.used = false,
|
||||
};
|
||||
return false;
|
||||
}
|
||||
|
||||
// option already exists
|
||||
switch (gop.value_ptr.value) {
|
||||
.scalar => |s| {
|
||||
log.err("Flag '-D{s}' conflicts with option '-D{s}={s}'.", .{ name, name, s });
|
||||
return true;
|
||||
},
|
||||
.list => {
|
||||
log.err("Flag '-D{s}' conflicts with multiple options of the same name.", .{name});
|
||||
return true;
|
||||
},
|
||||
.flag => {},
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
fn typeToEnum(comptime T: type) TypeId {
|
||||
return switch (@typeInfo(T)) {
|
||||
.Int => .int,
|
||||
.Float => .float,
|
||||
.Bool => .bool,
|
||||
.Enum => .@"enum",
|
||||
else => switch (T) {
|
||||
[]const u8 => .string,
|
||||
[]const []const u8 => .list,
|
||||
else => @compileError("Unsupported type: " ++ @typeName(T)),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
fn markInvalidUserInput(self: *Builder) void {
|
||||
self.invalid_user_input = true;
|
||||
}
|
||||
|
||||
pub fn validateUserInputDidItFail(self: *Builder) bool {
|
||||
// make sure all args are used
|
||||
var it = self.user_input_options.iterator();
|
||||
while (it.next()) |entry| {
|
||||
if (!entry.value_ptr.used) {
|
||||
log.err("Invalid option: -D{s}\n", .{entry.key_ptr.*});
|
||||
self.markInvalidUserInput();
|
||||
}
|
||||
}
|
||||
|
||||
return self.invalid_user_input;
|
||||
}
|
||||
|
||||
pub fn spawnChild(self: *Builder, argv: []const []const u8) !void {
|
||||
return self.spawnChildEnvMap(null, self.env_map, argv);
|
||||
}
|
||||
|
||||
fn printCmd(cwd: ?[]const u8, argv: []const []const u8) void {
|
||||
if (cwd) |yes_cwd| std.debug.print("cd {s} && ", .{yes_cwd});
|
||||
for (argv) |arg| {
|
||||
std.debug.print("{s} ", .{arg});
|
||||
}
|
||||
std.debug.print("\n", .{});
|
||||
}
|
||||
|
||||
pub fn spawnChildEnvMap(self: *Builder, cwd: ?[]const u8, env_map: *const EnvMap, argv: []const []const u8) !void {
|
||||
if (self.verbose) {
|
||||
printCmd(cwd, argv);
|
||||
}
|
||||
|
||||
if (!std.process.can_spawn)
|
||||
return error.ExecNotSupported;
|
||||
|
||||
var child = std.ChildProcess.init(argv, self.allocator);
|
||||
child.cwd = cwd;
|
||||
child.env_map = env_map;
|
||||
|
||||
const term = child.spawnAndWait() catch |err| {
|
||||
log.err("Unable to spawn {s}: {s}", .{ argv[0], @errorName(err) });
|
||||
return err;
|
||||
};
|
||||
|
||||
switch (term) {
|
||||
.Exited => |code| {
|
||||
if (code != 0) {
|
||||
log.err("The following command exited with error code {}:", .{code});
|
||||
printCmd(cwd, argv);
|
||||
return error.UncleanExit;
|
||||
}
|
||||
},
|
||||
else => {
|
||||
log.err("The following command terminated unexpectedly:", .{});
|
||||
printCmd(cwd, argv);
|
||||
|
||||
return error.UncleanExit;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn makePath(self: *Builder, path: []const u8) !void {
|
||||
fs.cwd().makePath(self.pathFromRoot(path)) catch |err| {
|
||||
log.err("Unable to create path {s}: {s}", .{ path, @errorName(err) });
|
||||
return err;
|
||||
};
|
||||
}
|
||||
|
||||
pub fn installArtifact(self: *Builder, artifact: *LibExeObjStep) void {
|
||||
self.getInstallStep().dependOn(&self.addInstallArtifact(artifact).step);
|
||||
}
|
||||
|
||||
pub fn addInstallArtifact(self: *Builder, artifact: *LibExeObjStep) *InstallArtifactStep {
|
||||
return InstallArtifactStep.create(self, artifact);
|
||||
}
|
||||
|
||||
///`dest_rel_path` is relative to prefix path
|
||||
pub fn installFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) void {
|
||||
self.getInstallStep().dependOn(&self.addInstallFileWithDir(.{ .path = src_path }, .prefix, dest_rel_path).step);
|
||||
}
|
||||
|
||||
pub fn installDirectory(self: *Builder, options: InstallDirectoryOptions) void {
|
||||
self.getInstallStep().dependOn(&self.addInstallDirectory(options).step);
|
||||
}
|
||||
|
||||
///`dest_rel_path` is relative to bin path
|
||||
pub fn installBinFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) void {
|
||||
self.getInstallStep().dependOn(&self.addInstallFileWithDir(.{ .path = src_path }, .bin, dest_rel_path).step);
|
||||
}
|
||||
|
||||
///`dest_rel_path` is relative to lib path
|
||||
pub fn installLibFile(self: *Builder, src_path: []const u8, dest_rel_path: []const u8) void {
|
||||
self.getInstallStep().dependOn(&self.addInstallFileWithDir(.{ .path = src_path }, .lib, dest_rel_path).step);
|
||||
}
|
||||
|
||||
/// Output format (BIN vs Intel HEX) determined by filename
|
||||
pub fn installRaw(self: *Builder, artifact: *LibExeObjStep, dest_filename: []const u8, options: InstallRawStep.CreateOptions) *InstallRawStep {
|
||||
const raw = self.addInstallRaw(artifact, dest_filename, options);
|
||||
self.getInstallStep().dependOn(&raw.step);
|
||||
return raw;
|
||||
}
|
||||
|
||||
///`dest_rel_path` is relative to install prefix path
|
||||
pub fn addInstallFile(self: *Builder, source: FileSource, dest_rel_path: []const u8) *InstallFileStep {
|
||||
return self.addInstallFileWithDir(source.dupe(self), .prefix, dest_rel_path);
|
||||
}
|
||||
|
||||
///`dest_rel_path` is relative to bin path
|
||||
pub fn addInstallBinFile(self: *Builder, source: FileSource, dest_rel_path: []const u8) *InstallFileStep {
|
||||
return self.addInstallFileWithDir(source.dupe(self), .bin, dest_rel_path);
|
||||
}
|
||||
|
||||
///`dest_rel_path` is relative to lib path
|
||||
pub fn addInstallLibFile(self: *Builder, source: FileSource, dest_rel_path: []const u8) *InstallFileStep {
|
||||
return self.addInstallFileWithDir(source.dupe(self), .lib, dest_rel_path);
|
||||
}
|
||||
|
||||
pub fn addInstallHeaderFile(b: *Builder, src_path: []const u8, dest_rel_path: []const u8) *InstallFileStep {
|
||||
return b.addInstallFileWithDir(.{ .path = src_path }, .header, dest_rel_path);
|
||||
}
|
||||
|
||||
pub fn addInstallRaw(self: *Builder, artifact: *LibExeObjStep, dest_filename: []const u8, options: InstallRawStep.CreateOptions) *InstallRawStep {
|
||||
return InstallRawStep.create(self, artifact, dest_filename, options);
|
||||
}
|
||||
|
||||
pub fn addInstallFileWithDir(
|
||||
self: *Builder,
|
||||
source: FileSource,
|
||||
install_dir: InstallDir,
|
||||
dest_rel_path: []const u8,
|
||||
) *InstallFileStep {
|
||||
if (dest_rel_path.len == 0) {
|
||||
panic("dest_rel_path must be non-empty", .{});
|
||||
}
|
||||
const install_step = self.allocator.create(InstallFileStep) catch unreachable;
|
||||
install_step.* = InstallFileStep.init(self, source.dupe(self), install_dir, dest_rel_path);
|
||||
return install_step;
|
||||
}
|
||||
|
||||
pub fn addInstallDirectory(self: *Builder, options: InstallDirectoryOptions) *InstallDirStep {
|
||||
const install_step = self.allocator.create(InstallDirStep) catch unreachable;
|
||||
install_step.* = InstallDirStep.init(self, options);
|
||||
return install_step;
|
||||
}
|
||||
|
||||
pub fn pushInstalledFile(self: *Builder, dir: InstallDir, dest_rel_path: []const u8) void {
|
||||
const file = InstalledFile{
|
||||
.dir = dir,
|
||||
.path = dest_rel_path,
|
||||
};
|
||||
self.installed_files.append(file.dupe(self)) catch unreachable;
|
||||
}
|
||||
|
||||
pub fn updateFile(self: *Builder, source_path: []const u8, dest_path: []const u8) !void {
|
||||
if (self.verbose) {
|
||||
log.info("cp {s} {s} ", .{ source_path, dest_path });
|
||||
}
|
||||
const cwd = fs.cwd();
|
||||
const prev_status = try fs.Dir.updateFile(cwd, source_path, cwd, dest_path, .{});
|
||||
if (self.verbose) switch (prev_status) {
|
||||
.stale => log.info("# installed", .{}),
|
||||
.fresh => log.info("# up-to-date", .{}),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn truncateFile(self: *Builder, dest_path: []const u8) !void {
|
||||
if (self.verbose) {
|
||||
log.info("truncate {s}", .{dest_path});
|
||||
}
|
||||
const cwd = fs.cwd();
|
||||
var src_file = cwd.createFile(dest_path, .{}) catch |err| switch (err) {
|
||||
error.FileNotFound => blk: {
|
||||
if (fs.path.dirname(dest_path)) |dirname| {
|
||||
try cwd.makePath(dirname);
|
||||
}
|
||||
break :blk try cwd.createFile(dest_path, .{});
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
src_file.close();
|
||||
}
|
||||
|
||||
pub fn pathFromRoot(self: *Builder, rel_path: []const u8) []u8 {
|
||||
return fs.path.resolve(self.allocator, &[_][]const u8{ self.build_root, rel_path }) catch unreachable;
|
||||
}
|
||||
|
||||
/// Shorthand for `std.fs.path.join(builder.allocator, paths) catch unreachable`
|
||||
pub fn pathJoin(self: *Builder, paths: []const []const u8) []u8 {
|
||||
return fs.path.join(self.allocator, paths) catch unreachable;
|
||||
}
|
||||
|
||||
pub fn fmt(self: *Builder, comptime format: []const u8, args: anytype) []u8 {
|
||||
return fmt_lib.allocPrint(self.allocator, format, args) catch unreachable;
|
||||
}
|
||||
|
||||
pub fn findProgram(self: *Builder, names: []const []const u8, paths: []const []const u8) ![]const u8 {
|
||||
// TODO report error for ambiguous situations
|
||||
const exe_extension = @as(CrossTarget, .{}).exeFileExt();
|
||||
for (self.search_prefixes.items) |search_prefix| {
|
||||
for (names) |name| {
|
||||
if (fs.path.isAbsolute(name)) {
|
||||
return name;
|
||||
}
|
||||
const full_path = self.pathJoin(&.{
|
||||
search_prefix,
|
||||
"bin",
|
||||
self.fmt("{s}{s}", .{ name, exe_extension }),
|
||||
});
|
||||
return fs.realpathAlloc(self.allocator, full_path) catch continue;
|
||||
}
|
||||
}
|
||||
if (self.env_map.get("PATH")) |PATH| {
|
||||
for (names) |name| {
|
||||
if (fs.path.isAbsolute(name)) {
|
||||
return name;
|
||||
}
|
||||
var it = mem.tokenize(u8, PATH, &[_]u8{fs.path.delimiter});
|
||||
while (it.next()) |path| {
|
||||
const full_path = self.pathJoin(&.{
|
||||
path,
|
||||
self.fmt("{s}{s}", .{ name, exe_extension }),
|
||||
});
|
||||
return fs.realpathAlloc(self.allocator, full_path) catch continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (names) |name| {
|
||||
if (fs.path.isAbsolute(name)) {
|
||||
return name;
|
||||
}
|
||||
for (paths) |path| {
|
||||
const full_path = self.pathJoin(&.{
|
||||
path,
|
||||
self.fmt("{s}{s}", .{ name, exe_extension }),
|
||||
});
|
||||
return fs.realpathAlloc(self.allocator, full_path) catch continue;
|
||||
}
|
||||
}
|
||||
return error.FileNotFound;
|
||||
}
|
||||
|
||||
pub fn execAllowFail(
|
||||
self: *Builder,
|
||||
argv: []const []const u8,
|
||||
out_code: *u8,
|
||||
stderr_behavior: std.ChildProcess.StdIo,
|
||||
) ExecError![]u8 {
|
||||
assert(argv.len != 0);
|
||||
|
||||
if (!std.process.can_spawn)
|
||||
return error.ExecNotSupported;
|
||||
|
||||
const max_output_size = 400 * 1024;
|
||||
var child = std.ChildProcess.init(argv, self.allocator);
|
||||
child.stdin_behavior = .Ignore;
|
||||
child.stdout_behavior = .Pipe;
|
||||
child.stderr_behavior = stderr_behavior;
|
||||
child.env_map = self.env_map;
|
||||
|
||||
try child.spawn();
|
||||
|
||||
const stdout = child.stdout.?.reader().readAllAlloc(self.allocator, max_output_size) catch {
|
||||
return error.ReadFailure;
|
||||
};
|
||||
errdefer self.allocator.free(stdout);
|
||||
|
||||
const term = try child.wait();
|
||||
switch (term) {
|
||||
.Exited => |code| {
|
||||
if (code != 0) {
|
||||
out_code.* = @truncate(u8, code);
|
||||
return error.ExitCodeFailure;
|
||||
}
|
||||
return stdout;
|
||||
},
|
||||
.Signal, .Stopped, .Unknown => |code| {
|
||||
out_code.* = @truncate(u8, code);
|
||||
return error.ProcessTerminated;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn execFromStep(self: *Builder, argv: []const []const u8, src_step: ?*Step) ![]u8 {
|
||||
assert(argv.len != 0);
|
||||
|
||||
if (self.verbose) {
|
||||
printCmd(null, argv);
|
||||
}
|
||||
|
||||
if (!std.process.can_spawn) {
|
||||
if (src_step) |s| log.err("{s}...", .{s.name});
|
||||
log.err("Unable to spawn the following command: cannot spawn child process", .{});
|
||||
printCmd(null, argv);
|
||||
std.os.abort();
|
||||
}
|
||||
|
||||
var code: u8 = undefined;
|
||||
return self.execAllowFail(argv, &code, .Inherit) catch |err| switch (err) {
|
||||
error.ExecNotSupported => {
|
||||
if (src_step) |s| log.err("{s}...", .{s.name});
|
||||
log.err("Unable to spawn the following command: cannot spawn child process", .{});
|
||||
printCmd(null, argv);
|
||||
std.os.abort();
|
||||
},
|
||||
error.FileNotFound => {
|
||||
if (src_step) |s| log.err("{s}...", .{s.name});
|
||||
log.err("Unable to spawn the following command: file not found", .{});
|
||||
printCmd(null, argv);
|
||||
std.os.exit(@truncate(u8, code));
|
||||
},
|
||||
error.ExitCodeFailure => {
|
||||
if (src_step) |s| log.err("{s}...", .{s.name});
|
||||
if (self.prominent_compile_errors) {
|
||||
log.err("The step exited with error code {d}", .{code});
|
||||
} else {
|
||||
log.err("The following command exited with error code {d}:", .{code});
|
||||
printCmd(null, argv);
|
||||
}
|
||||
|
||||
std.os.exit(@truncate(u8, code));
|
||||
},
|
||||
error.ProcessTerminated => {
|
||||
if (src_step) |s| log.err("{s}...", .{s.name});
|
||||
log.err("The following command terminated unexpectedly:", .{});
|
||||
printCmd(null, argv);
|
||||
std.os.exit(@truncate(u8, code));
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn exec(self: *Builder, argv: []const []const u8) ![]u8 {
|
||||
return self.execFromStep(argv, null);
|
||||
}
|
||||
|
||||
pub fn addSearchPrefix(self: *Builder, search_prefix: []const u8) void {
|
||||
self.search_prefixes.append(self.dupePath(search_prefix)) catch unreachable;
|
||||
}
|
||||
|
||||
pub fn getInstallPath(self: *Builder, dir: InstallDir, dest_rel_path: []const u8) []const u8 {
|
||||
assert(!fs.path.isAbsolute(dest_rel_path)); // Install paths must be relative to the prefix
|
||||
const base_dir = switch (dir) {
|
||||
.prefix => self.install_path,
|
||||
.bin => self.exe_dir,
|
||||
.lib => self.lib_dir,
|
||||
.header => self.h_dir,
|
||||
.custom => |path| self.pathJoin(&.{ self.install_path, path }),
|
||||
};
|
||||
return fs.path.resolve(
|
||||
self.allocator,
|
||||
&[_][]const u8{ base_dir, dest_rel_path },
|
||||
) catch unreachable;
|
||||
}
|
||||
|
||||
pub const Dependency = struct {
|
||||
builder: *Builder,
|
||||
|
||||
pub fn artifact(d: *Dependency, name: []const u8) *LibExeObjStep {
|
||||
var found: ?*LibExeObjStep = null;
|
||||
for (d.builder.install_tls.step.dependencies.items) |dep_step| {
|
||||
const inst = dep_step.cast(InstallArtifactStep) orelse continue;
|
||||
if (mem.eql(u8, inst.artifact.name, name)) {
|
||||
if (found != null) panic("artifact name '{s}' is ambiguous", .{name});
|
||||
found = inst.artifact;
|
||||
}
|
||||
}
|
||||
return found orelse {
|
||||
for (d.builder.install_tls.step.dependencies.items) |dep_step| {
|
||||
const inst = dep_step.cast(InstallArtifactStep) orelse continue;
|
||||
log.info("available artifact: '{s}'", .{inst.artifact.name});
|
||||
}
|
||||
panic("unable to find artifact '{s}'", .{name});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn dependency(b: *Builder, name: []const u8, args: anytype) *Dependency {
|
||||
const build_runner = @import("root");
|
||||
const deps = build_runner.dependencies;
|
||||
|
||||
inline for (@typeInfo(deps.imports).Struct.decls) |decl| {
|
||||
if (mem.startsWith(u8, decl.name, b.dep_prefix) and
|
||||
mem.endsWith(u8, decl.name, name) and
|
||||
decl.name.len == b.dep_prefix.len + name.len)
|
||||
{
|
||||
const build_zig = @field(deps.imports, decl.name);
|
||||
const build_root = @field(deps.build_root, decl.name);
|
||||
return dependencyInner(b, name, build_root, build_zig, args);
|
||||
}
|
||||
}
|
||||
|
||||
const full_path = b.pathFromRoot("build.zig.ini");
|
||||
std.debug.print("no dependency named '{s}' in '{s}'\n", .{ name, full_path });
|
||||
std.process.exit(1);
|
||||
}
|
||||
|
||||
fn dependencyInner(
|
||||
b: *Builder,
|
||||
name: []const u8,
|
||||
build_root: []const u8,
|
||||
comptime build_zig: type,
|
||||
args: anytype,
|
||||
) *Dependency {
|
||||
const sub_builder = b.createChild(name, build_root, args) catch unreachable;
|
||||
sub_builder.runBuild(build_zig) catch unreachable;
|
||||
const dep = b.allocator.create(Dependency) catch unreachable;
|
||||
dep.* = .{ .builder = sub_builder };
|
||||
return dep;
|
||||
}
|
||||
|
||||
pub fn runBuild(b: *Builder, build_zig: anytype) anyerror!void {
|
||||
switch (@typeInfo(@typeInfo(@TypeOf(build_zig.build)).Fn.return_type.?)) {
|
||||
.Void => build_zig.build(b),
|
||||
.ErrorUnion => try build_zig.build(b),
|
||||
else => @compileError("expected return type of build to be 'void' or '!void'"),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
test "builder.findProgram compiles" {
|
||||
if (builtin.os.tag == .wasi) return error.SkipZigTest;
|
||||
|
||||
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
defer arena.deinit();
|
||||
|
||||
const builder = try Builder.create(
|
||||
arena.allocator(),
|
||||
"zig",
|
||||
"zig-cache",
|
||||
"zig-cache",
|
||||
"zig-cache",
|
||||
);
|
||||
defer builder.destroy();
|
||||
_ = builder.findProgram(&[_][]const u8{}, &[_][]const u8{}) catch null;
|
||||
}
|
||||
|
||||
pub const Pkg = struct {
|
||||
name: []const u8,
|
||||
source: FileSource,
|
||||
dependencies: ?[]const Pkg = null,
|
||||
};
|
||||
|
||||
/// A file that is generated by a build step.
|
||||
/// This struct is an interface that is meant to be used with `@fieldParentPtr` to implement the actual path logic.
|
||||
pub const GeneratedFile = struct {
|
||||
/// The step that generates the file
|
||||
step: *Step,
|
||||
|
||||
/// The path to the generated file. Must be either absolute or relative to the build root.
|
||||
/// This value must be set in the `fn make()` of the `step` and must not be `null` afterwards.
|
||||
path: ?[]const u8 = null,
|
||||
|
||||
pub fn getPath(self: GeneratedFile) []const u8 {
|
||||
return self.path orelse std.debug.panic(
|
||||
"getPath() was called on a GeneratedFile that wasn't build yet. Is there a missing Step dependency on step '{s}'?",
|
||||
.{self.step.name},
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/// A file source is a reference to an existing or future file.
|
||||
///
|
||||
pub const FileSource = union(enum) {
|
||||
/// A plain file path, relative to build root or absolute.
|
||||
path: []const u8,
|
||||
|
||||
/// A file that is generated by an interface. Those files usually are
|
||||
/// not available until built by a build step.
|
||||
generated: *const GeneratedFile,
|
||||
|
||||
/// Returns a new file source that will have a relative path to the build root guaranteed.
|
||||
/// This should be preferred over setting `.path` directly as it documents that the files are in the project directory.
|
||||
pub fn relative(path: []const u8) FileSource {
|
||||
std.debug.assert(!std.fs.path.isAbsolute(path));
|
||||
return FileSource{ .path = path };
|
||||
}
|
||||
|
||||
/// Returns a string that can be shown to represent the file source.
|
||||
/// Either returns the path or `"generated"`.
|
||||
pub fn getDisplayName(self: FileSource) []const u8 {
|
||||
return switch (self) {
|
||||
.path => self.path,
|
||||
.generated => "generated",
|
||||
};
|
||||
}
|
||||
|
||||
/// Adds dependencies this file source implies to the given step.
|
||||
pub fn addStepDependencies(self: FileSource, step: *Step) void {
|
||||
switch (self) {
|
||||
.path => {},
|
||||
.generated => |gen| step.dependOn(gen.step),
|
||||
}
|
||||
}
|
||||
|
||||
/// Should only be called during make(), returns a path relative to the build root or absolute.
|
||||
pub fn getPath(self: FileSource, builder: *Builder) []const u8 {
|
||||
const path = switch (self) {
|
||||
.path => |p| builder.pathFromRoot(p),
|
||||
.generated => |gen| gen.getPath(),
|
||||
};
|
||||
return path;
|
||||
}
|
||||
|
||||
/// Duplicates the file source for a given builder.
|
||||
pub fn dupe(self: FileSource, b: *Builder) FileSource {
|
||||
return switch (self) {
|
||||
.path => |p| .{ .path = b.dupePath(p) },
|
||||
.generated => |gen| .{ .generated = gen },
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Allocates a new string for assigning a value to a named macro.
|
||||
/// If the value is omitted, it is set to 1.
|
||||
/// `name` and `value` need not live longer than the function call.
|
||||
pub fn constructCMacro(allocator: Allocator, name: []const u8, value: ?[]const u8) []const u8 {
|
||||
var macro = allocator.alloc(
|
||||
u8,
|
||||
name.len + if (value) |value_slice| value_slice.len + 1 else 0,
|
||||
) catch |err| if (err == error.OutOfMemory) @panic("Out of memory") else unreachable;
|
||||
mem.copy(u8, macro, name);
|
||||
if (value) |value_slice| {
|
||||
macro[name.len] = '=';
|
||||
mem.copy(u8, macro[name.len + 1 ..], value_slice);
|
||||
}
|
||||
return macro;
|
||||
}
|
||||
|
||||
/// deprecated: use `InstallDirStep.Options`
|
||||
pub const InstallDirectoryOptions = InstallDirStep.Options;
|
||||
|
||||
pub const Step = struct {
|
||||
id: Id,
|
||||
name: []const u8,
|
||||
makeFn: MakeFn,
|
||||
dependencies: ArrayList(*Step),
|
||||
loop_flag: bool,
|
||||
done_flag: bool,
|
||||
|
||||
const MakeFn = *const fn (self: *Step) anyerror!void;
|
||||
|
||||
pub const Id = enum {
|
||||
top_level,
|
||||
lib_exe_obj,
|
||||
install_artifact,
|
||||
install_file,
|
||||
install_dir,
|
||||
log,
|
||||
remove_dir,
|
||||
fmt,
|
||||
translate_c,
|
||||
write_file,
|
||||
run,
|
||||
emulatable_run,
|
||||
check_file,
|
||||
check_object,
|
||||
config_header,
|
||||
install_raw,
|
||||
options,
|
||||
custom,
|
||||
|
||||
pub fn Type(comptime id: Id) type {
|
||||
return switch (id) {
|
||||
.top_level => Builder.TopLevelStep,
|
||||
.lib_exe_obj => LibExeObjStep,
|
||||
.install_artifact => InstallArtifactStep,
|
||||
.install_file => InstallFileStep,
|
||||
.install_dir => InstallDirStep,
|
||||
.log => LogStep,
|
||||
.remove_dir => RemoveDirStep,
|
||||
.fmt => FmtStep,
|
||||
.translate_c => TranslateCStep,
|
||||
.write_file => WriteFileStep,
|
||||
.run => RunStep,
|
||||
.emulatable_run => EmulatableRunStep,
|
||||
.check_file => CheckFileStep,
|
||||
.check_object => CheckObjectStep,
|
||||
.config_header => ConfigHeaderStep,
|
||||
.install_raw => InstallRawStep,
|
||||
.options => OptionsStep,
|
||||
.custom => @compileError("no type available for custom step"),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn init(id: Id, name: []const u8, allocator: Allocator, makeFn: MakeFn) Step {
|
||||
return Step{
|
||||
.id = id,
|
||||
.name = allocator.dupe(u8, name) catch unreachable,
|
||||
.makeFn = makeFn,
|
||||
.dependencies = ArrayList(*Step).init(allocator),
|
||||
.loop_flag = false,
|
||||
.done_flag = false,
|
||||
};
|
||||
}
|
||||
pub fn initNoOp(id: Id, name: []const u8, allocator: Allocator) Step {
|
||||
return init(id, name, allocator, makeNoOp);
|
||||
}
|
||||
|
||||
pub fn make(self: *Step) !void {
|
||||
if (self.done_flag) return;
|
||||
|
||||
try self.makeFn(self);
|
||||
self.done_flag = true;
|
||||
}
|
||||
|
||||
pub fn dependOn(self: *Step, other: *Step) void {
|
||||
self.dependencies.append(other) catch unreachable;
|
||||
}
|
||||
|
||||
fn makeNoOp(self: *Step) anyerror!void {
|
||||
_ = self;
|
||||
}
|
||||
|
||||
pub fn cast(step: *Step, comptime T: type) ?*T {
|
||||
if (step.id == T.base_id) {
|
||||
return @fieldParentPtr(T, "step", step);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
pub const VcpkgRoot = union(VcpkgRootStatus) {
|
||||
unattempted: void,
|
||||
not_found: void,
|
||||
found: []const u8,
|
||||
};
|
||||
|
||||
pub const VcpkgRootStatus = enum {
|
||||
unattempted,
|
||||
not_found,
|
||||
found,
|
||||
};
|
||||
|
||||
pub const InstallDir = union(enum) {
|
||||
prefix: void,
|
||||
lib: void,
|
||||
bin: void,
|
||||
header: void,
|
||||
/// A path relative to the prefix
|
||||
custom: []const u8,
|
||||
|
||||
/// Duplicates the install directory including the path if set to custom.
|
||||
pub fn dupe(self: InstallDir, builder: *Builder) InstallDir {
|
||||
if (self == .custom) {
|
||||
// Written with this temporary to avoid RLS problems
|
||||
const duped_path = builder.dupe(self.custom);
|
||||
return .{ .custom = duped_path };
|
||||
} else {
|
||||
return self;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub const InstalledFile = struct {
|
||||
dir: InstallDir,
|
||||
path: []const u8,
|
||||
|
||||
/// Duplicates the installed file path and directory.
|
||||
pub fn dupe(self: InstalledFile, builder: *Builder) InstalledFile {
|
||||
return .{
|
||||
.dir = self.dir.dupe(builder),
|
||||
.path = builder.dupe(self.path),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
test "dupePkg()" {
|
||||
if (builtin.os.tag == .wasi) return error.SkipZigTest;
|
||||
|
||||
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
||||
defer arena.deinit();
|
||||
var builder = try Builder.create(
|
||||
arena.allocator(),
|
||||
"test",
|
||||
"test",
|
||||
"test",
|
||||
"test",
|
||||
);
|
||||
defer builder.destroy();
|
||||
|
||||
var pkg_dep = Pkg{
|
||||
.name = "pkg_dep",
|
||||
.source = .{ .path = "/not/a/pkg_dep.zig" },
|
||||
};
|
||||
var pkg_top = Pkg{
|
||||
.name = "pkg_top",
|
||||
.source = .{ .path = "/not/a/pkg_top.zig" },
|
||||
.dependencies = &[_]Pkg{pkg_dep},
|
||||
};
|
||||
const dupe = builder.dupePkg(pkg_top);
|
||||
|
||||
const original_deps = pkg_top.dependencies.?;
|
||||
const dupe_deps = dupe.dependencies.?;
|
||||
|
||||
// probably the same top level package details
|
||||
try std.testing.expectEqualStrings(pkg_top.name, dupe.name);
|
||||
|
||||
// probably the same dependencies
|
||||
try std.testing.expectEqual(original_deps.len, dupe_deps.len);
|
||||
try std.testing.expectEqual(original_deps[0].name, pkg_dep.name);
|
||||
|
||||
// could segfault otherwise if pointers in duplicated package's fields are
|
||||
// the same as those in stack allocated package's fields
|
||||
try std.testing.expect(dupe_deps.ptr != original_deps.ptr);
|
||||
try std.testing.expect(dupe.name.ptr != pkg_top.name.ptr);
|
||||
try std.testing.expect(dupe.source.path.ptr != pkg_top.source.path.ptr);
|
||||
try std.testing.expect(dupe_deps[0].name.ptr != pkg_dep.name.ptr);
|
||||
try std.testing.expect(dupe_deps[0].source.path.ptr != pkg_dep.source.path.ptr);
|
||||
}
|
||||
|
||||
test {
|
||||
_ = CheckFileStep;
|
||||
_ = CheckObjectStep;
|
||||
_ = EmulatableRunStep;
|
||||
_ = FmtStep;
|
||||
_ = InstallArtifactStep;
|
||||
_ = InstallDirStep;
|
||||
_ = InstallFileStep;
|
||||
_ = InstallRawStep;
|
||||
_ = LibExeObjStep;
|
||||
_ = LogStep;
|
||||
_ = OptionsStep;
|
||||
_ = RemoveDirStep;
|
||||
_ = RunStep;
|
||||
_ = TranslateCStep;
|
||||
_ = WriteFileStep;
|
||||
}
|
||||
+4
-1
@@ -131,13 +131,16 @@ pub const CodeModel = enum {
|
||||
|
||||
/// This data structure is used by the Zig language code generation and
|
||||
/// therefore must be kept in sync with the compiler implementation.
|
||||
pub const Mode = enum {
|
||||
pub const OptimizeMode = enum {
|
||||
Debug,
|
||||
ReleaseSafe,
|
||||
ReleaseFast,
|
||||
ReleaseSmall,
|
||||
};
|
||||
|
||||
/// Deprecated; use OptimizeMode.
|
||||
pub const Mode = OptimizeMode;
|
||||
|
||||
/// This data structure is used by the Zig language code generation and
|
||||
/// therefore must be kept in sync with the compiler implementation.
|
||||
pub const CallingConvention = enum {
|
||||
|
||||
+4
-1
@@ -9,6 +9,7 @@ pub const AutoArrayHashMapUnmanaged = array_hash_map.AutoArrayHashMapUnmanaged;
|
||||
pub const AutoHashMap = hash_map.AutoHashMap;
|
||||
pub const AutoHashMapUnmanaged = hash_map.AutoHashMapUnmanaged;
|
||||
pub const BoundedArray = @import("bounded_array.zig").BoundedArray;
|
||||
pub const Build = @import("Build.zig");
|
||||
pub const BufMap = @import("buf_map.zig").BufMap;
|
||||
pub const BufSet = @import("buf_set.zig").BufSet;
|
||||
pub const ChildProcess = @import("child_process.zig").ChildProcess;
|
||||
@@ -49,7 +50,6 @@ pub const array_hash_map = @import("array_hash_map.zig");
|
||||
pub const atomic = @import("atomic.zig");
|
||||
pub const base64 = @import("base64.zig");
|
||||
pub const bit_set = @import("bit_set.zig");
|
||||
pub const build = @import("build.zig");
|
||||
pub const builtin = @import("builtin.zig");
|
||||
pub const c = @import("c.zig");
|
||||
pub const coff = @import("coff.zig");
|
||||
@@ -96,6 +96,9 @@ pub const wasm = @import("wasm.zig");
|
||||
pub const zig = @import("zig.zig");
|
||||
pub const start = @import("start.zig");
|
||||
|
||||
/// deprecated: use `Build`.
|
||||
pub const build = Build;
|
||||
|
||||
const root = @import("root");
|
||||
const options_override = if (@hasDecl(root, "std_options")) root.std_options else struct {};
|
||||
|
||||
|
||||
@@ -1880,6 +1880,559 @@ pub const Target = struct {
|
||||
=> 16,
|
||||
};
|
||||
}
|
||||
|
||||
pub const CType = enum {
|
||||
short,
|
||||
ushort,
|
||||
int,
|
||||
uint,
|
||||
long,
|
||||
ulong,
|
||||
longlong,
|
||||
ulonglong,
|
||||
float,
|
||||
double,
|
||||
longdouble,
|
||||
};
|
||||
|
||||
pub fn c_type_byte_size(t: Target, c_type: CType) u16 {
|
||||
return switch (c_type) {
|
||||
.short,
|
||||
.ushort,
|
||||
.int,
|
||||
.uint,
|
||||
.long,
|
||||
.ulong,
|
||||
.longlong,
|
||||
.ulonglong,
|
||||
=> @divExact(c_type_bit_size(t, c_type), 8),
|
||||
|
||||
.float => 4,
|
||||
.double => 8,
|
||||
|
||||
.longdouble => switch (c_type_bit_size(t, c_type)) {
|
||||
16 => 2,
|
||||
32 => 4,
|
||||
64 => 8,
|
||||
80 => @intCast(u16, mem.alignForward(10, c_type_alignment(t, .longdouble))),
|
||||
128 => 16,
|
||||
else => unreachable,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn c_type_bit_size(target: Target, c_type: CType) u16 {
|
||||
switch (target.os.tag) {
|
||||
.freestanding, .other => switch (target.cpu.arch) {
|
||||
.msp430 => switch (c_type) {
|
||||
.short, .ushort, .int, .uint => return 16,
|
||||
.float, .long, .ulong => return 32,
|
||||
.longlong, .ulonglong, .double, .longdouble => return 64,
|
||||
},
|
||||
.avr => switch (c_type) {
|
||||
.short, .ushort, .int, .uint => return 16,
|
||||
.long, .ulong, .float, .double, .longdouble => return 32,
|
||||
.longlong, .ulonglong => return 64,
|
||||
},
|
||||
.tce, .tcele => switch (c_type) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .long, .ulong, .longlong, .ulonglong => return 32,
|
||||
.float, .double, .longdouble => return 32,
|
||||
},
|
||||
.mips64, .mips64el => switch (c_type) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong => return if (target.abi != .gnuabin32) 64 else 32,
|
||||
.longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => return 128,
|
||||
},
|
||||
.x86_64 => switch (c_type) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong => switch (target.abi) {
|
||||
.gnux32, .muslx32 => return 32,
|
||||
else => return 64,
|
||||
},
|
||||
.longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => return 80,
|
||||
},
|
||||
else => switch (c_type) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong => return target.cpu.arch.ptrBitWidth(),
|
||||
.longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => switch (target.cpu.arch) {
|
||||
.x86 => switch (target.abi) {
|
||||
.android => return 64,
|
||||
else => return 80,
|
||||
},
|
||||
|
||||
.powerpc,
|
||||
.powerpcle,
|
||||
.powerpc64,
|
||||
.powerpc64le,
|
||||
=> switch (target.abi) {
|
||||
.musl,
|
||||
.musleabi,
|
||||
.musleabihf,
|
||||
.muslx32,
|
||||
=> return 64,
|
||||
else => return 128,
|
||||
},
|
||||
|
||||
.riscv32,
|
||||
.riscv64,
|
||||
.aarch64,
|
||||
.aarch64_be,
|
||||
.aarch64_32,
|
||||
.s390x,
|
||||
.sparc,
|
||||
.sparc64,
|
||||
.sparcel,
|
||||
.wasm32,
|
||||
.wasm64,
|
||||
=> return 128,
|
||||
|
||||
else => return 64,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
.linux,
|
||||
.freebsd,
|
||||
.netbsd,
|
||||
.dragonfly,
|
||||
.openbsd,
|
||||
.wasi,
|
||||
.emscripten,
|
||||
.plan9,
|
||||
.solaris,
|
||||
.haiku,
|
||||
.ananas,
|
||||
.fuchsia,
|
||||
.minix,
|
||||
=> switch (target.cpu.arch) {
|
||||
.msp430 => switch (c_type) {
|
||||
.short, .ushort, .int, .uint => return 16,
|
||||
.long, .ulong, .float => return 32,
|
||||
.longlong, .ulonglong, .double, .longdouble => return 64,
|
||||
},
|
||||
.avr => switch (c_type) {
|
||||
.short, .ushort, .int, .uint => return 16,
|
||||
.long, .ulong, .float, .double, .longdouble => return 32,
|
||||
.longlong, .ulonglong => return 64,
|
||||
},
|
||||
.tce, .tcele => switch (c_type) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .long, .ulong, .longlong, .ulonglong => return 32,
|
||||
.float, .double, .longdouble => return 32,
|
||||
},
|
||||
.mips64, .mips64el => switch (c_type) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong => return if (target.abi != .gnuabin32) 64 else 32,
|
||||
.longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => if (target.os.tag == .freebsd) return 64 else return 128,
|
||||
},
|
||||
.x86_64 => switch (c_type) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong => switch (target.abi) {
|
||||
.gnux32, .muslx32 => return 32,
|
||||
else => return 64,
|
||||
},
|
||||
.longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => return 80,
|
||||
},
|
||||
else => switch (c_type) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong => return target.cpu.arch.ptrBitWidth(),
|
||||
.longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => switch (target.cpu.arch) {
|
||||
.x86 => switch (target.abi) {
|
||||
.android => return 64,
|
||||
else => return 80,
|
||||
},
|
||||
|
||||
.powerpc,
|
||||
.powerpcle,
|
||||
=> switch (target.abi) {
|
||||
.musl,
|
||||
.musleabi,
|
||||
.musleabihf,
|
||||
.muslx32,
|
||||
=> return 64,
|
||||
else => switch (target.os.tag) {
|
||||
.freebsd, .netbsd, .openbsd => return 64,
|
||||
else => return 128,
|
||||
},
|
||||
},
|
||||
|
||||
.powerpc64,
|
||||
.powerpc64le,
|
||||
=> switch (target.abi) {
|
||||
.musl,
|
||||
.musleabi,
|
||||
.musleabihf,
|
||||
.muslx32,
|
||||
=> return 64,
|
||||
else => switch (target.os.tag) {
|
||||
.freebsd, .openbsd => return 64,
|
||||
else => return 128,
|
||||
},
|
||||
},
|
||||
|
||||
.riscv32,
|
||||
.riscv64,
|
||||
.aarch64,
|
||||
.aarch64_be,
|
||||
.aarch64_32,
|
||||
.s390x,
|
||||
.mips64,
|
||||
.mips64el,
|
||||
.sparc,
|
||||
.sparc64,
|
||||
.sparcel,
|
||||
.wasm32,
|
||||
.wasm64,
|
||||
=> return 128,
|
||||
|
||||
else => return 64,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
.windows, .uefi => switch (target.cpu.arch) {
|
||||
.x86 => switch (c_type) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong => return 32,
|
||||
.longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => switch (target.abi) {
|
||||
.gnu, .gnuilp32, .cygnus => return 80,
|
||||
else => return 64,
|
||||
},
|
||||
},
|
||||
.x86_64 => switch (c_type) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong => switch (target.abi) {
|
||||
.cygnus => return 64,
|
||||
else => return 32,
|
||||
},
|
||||
.longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => switch (target.abi) {
|
||||
.gnu, .gnuilp32, .cygnus => return 80,
|
||||
else => return 64,
|
||||
},
|
||||
},
|
||||
else => switch (c_type) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong => return 32,
|
||||
.longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => return 64,
|
||||
},
|
||||
},
|
||||
|
||||
.macos, .ios, .tvos, .watchos => switch (c_type) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong => switch (target.cpu.arch) {
|
||||
.x86, .arm, .aarch64_32 => return 32,
|
||||
.x86_64 => switch (target.abi) {
|
||||
.gnux32, .muslx32 => return 32,
|
||||
else => return 64,
|
||||
},
|
||||
else => return 64,
|
||||
},
|
||||
.longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => switch (target.cpu.arch) {
|
||||
.x86 => switch (target.abi) {
|
||||
.android => return 64,
|
||||
else => return 80,
|
||||
},
|
||||
.x86_64 => return 80,
|
||||
else => return 64,
|
||||
},
|
||||
},
|
||||
|
||||
.nvcl, .cuda => switch (c_type) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong => switch (target.cpu.arch) {
|
||||
.nvptx => return 32,
|
||||
.nvptx64 => return 64,
|
||||
else => return 64,
|
||||
},
|
||||
.longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => return 64,
|
||||
},
|
||||
|
||||
.amdhsa, .amdpal => switch (c_type) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong, .longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => return 128,
|
||||
},
|
||||
|
||||
.cloudabi,
|
||||
.kfreebsd,
|
||||
.lv2,
|
||||
.zos,
|
||||
.rtems,
|
||||
.nacl,
|
||||
.aix,
|
||||
.ps4,
|
||||
.ps5,
|
||||
.elfiamcu,
|
||||
.mesa3d,
|
||||
.contiki,
|
||||
.hermit,
|
||||
.hurd,
|
||||
.opencl,
|
||||
.glsl450,
|
||||
.vulkan,
|
||||
.driverkit,
|
||||
.shadermodel,
|
||||
=> @panic("TODO specify the C integer and float type sizes for this OS"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn c_type_alignment(target: Target, c_type: CType) u16 {
|
||||
// Overrides for unusual alignments
|
||||
switch (target.cpu.arch) {
|
||||
.avr => switch (c_type) {
|
||||
.short, .ushort => return 2,
|
||||
else => return 1,
|
||||
},
|
||||
.x86 => switch (target.os.tag) {
|
||||
.windows, .uefi => switch (c_type) {
|
||||
.longlong, .ulonglong, .double => return 8,
|
||||
.longdouble => switch (target.abi) {
|
||||
.gnu, .gnuilp32, .cygnus => return 4,
|
||||
else => return 8,
|
||||
},
|
||||
else => {},
|
||||
},
|
||||
else => {},
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
||||
// Next-power-of-two-aligned, up to a maximum.
|
||||
return @min(
|
||||
std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8),
|
||||
switch (target.cpu.arch) {
|
||||
.arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) {
|
||||
.netbsd => switch (target.abi) {
|
||||
.gnueabi,
|
||||
.gnueabihf,
|
||||
.eabi,
|
||||
.eabihf,
|
||||
.android,
|
||||
.musleabi,
|
||||
.musleabihf,
|
||||
=> 8,
|
||||
|
||||
else => @as(u16, 4),
|
||||
},
|
||||
.ios, .tvos, .watchos => 4,
|
||||
else => 8,
|
||||
},
|
||||
|
||||
.msp430,
|
||||
.avr,
|
||||
=> 2,
|
||||
|
||||
.arc,
|
||||
.csky,
|
||||
.x86,
|
||||
.xcore,
|
||||
.dxil,
|
||||
.loongarch32,
|
||||
.tce,
|
||||
.tcele,
|
||||
.le32,
|
||||
.amdil,
|
||||
.hsail,
|
||||
.spir,
|
||||
.spirv32,
|
||||
.kalimba,
|
||||
.shave,
|
||||
.renderscript32,
|
||||
.ve,
|
||||
.spu_2,
|
||||
=> 4,
|
||||
|
||||
.aarch64_32,
|
||||
.amdgcn,
|
||||
.amdil64,
|
||||
.bpfel,
|
||||
.bpfeb,
|
||||
.hexagon,
|
||||
.hsail64,
|
||||
.loongarch64,
|
||||
.m68k,
|
||||
.mips,
|
||||
.mipsel,
|
||||
.sparc,
|
||||
.sparcel,
|
||||
.sparc64,
|
||||
.lanai,
|
||||
.le64,
|
||||
.nvptx,
|
||||
.nvptx64,
|
||||
.r600,
|
||||
.s390x,
|
||||
.spir64,
|
||||
.spirv64,
|
||||
.renderscript64,
|
||||
=> 8,
|
||||
|
||||
.aarch64,
|
||||
.aarch64_be,
|
||||
.mips64,
|
||||
.mips64el,
|
||||
.powerpc,
|
||||
.powerpcle,
|
||||
.powerpc64,
|
||||
.powerpc64le,
|
||||
.riscv32,
|
||||
.riscv64,
|
||||
.x86_64,
|
||||
.wasm32,
|
||||
.wasm64,
|
||||
=> 16,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
pub fn c_type_preferred_alignment(target: Target, c_type: CType) u16 {
|
||||
// Overrides for unusual alignments
|
||||
switch (target.cpu.arch) {
|
||||
.arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) {
|
||||
.netbsd => switch (target.abi) {
|
||||
.gnueabi,
|
||||
.gnueabihf,
|
||||
.eabi,
|
||||
.eabihf,
|
||||
.android,
|
||||
.musleabi,
|
||||
.musleabihf,
|
||||
=> {},
|
||||
|
||||
else => switch (c_type) {
|
||||
.longdouble => return 4,
|
||||
else => {},
|
||||
},
|
||||
},
|
||||
.ios, .tvos, .watchos => switch (c_type) {
|
||||
.longdouble => return 4,
|
||||
else => {},
|
||||
},
|
||||
else => {},
|
||||
},
|
||||
.arc => switch (c_type) {
|
||||
.longdouble => return 4,
|
||||
else => {},
|
||||
},
|
||||
.avr => switch (c_type) {
|
||||
.int, .uint, .long, .ulong, .float, .longdouble => return 1,
|
||||
.short, .ushort => return 2,
|
||||
.double => return 4,
|
||||
.longlong, .ulonglong => return 8,
|
||||
},
|
||||
.x86 => switch (target.os.tag) {
|
||||
.windows, .uefi => switch (c_type) {
|
||||
.longdouble => switch (target.abi) {
|
||||
.gnu, .gnuilp32, .cygnus => return 4,
|
||||
else => return 8,
|
||||
},
|
||||
else => {},
|
||||
},
|
||||
else => switch (c_type) {
|
||||
.longdouble => return 4,
|
||||
else => {},
|
||||
},
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
||||
// Next-power-of-two-aligned, up to a maximum.
|
||||
return @min(
|
||||
std.math.ceilPowerOfTwoAssert(u16, (c_type_bit_size(target, c_type) + 7) / 8),
|
||||
switch (target.cpu.arch) {
|
||||
.msp430 => @as(u16, 2),
|
||||
|
||||
.csky,
|
||||
.xcore,
|
||||
.dxil,
|
||||
.loongarch32,
|
||||
.tce,
|
||||
.tcele,
|
||||
.le32,
|
||||
.amdil,
|
||||
.hsail,
|
||||
.spir,
|
||||
.spirv32,
|
||||
.kalimba,
|
||||
.shave,
|
||||
.renderscript32,
|
||||
.ve,
|
||||
.spu_2,
|
||||
=> 4,
|
||||
|
||||
.arc,
|
||||
.arm,
|
||||
.armeb,
|
||||
.avr,
|
||||
.thumb,
|
||||
.thumbeb,
|
||||
.aarch64_32,
|
||||
.amdgcn,
|
||||
.amdil64,
|
||||
.bpfel,
|
||||
.bpfeb,
|
||||
.hexagon,
|
||||
.hsail64,
|
||||
.x86,
|
||||
.loongarch64,
|
||||
.m68k,
|
||||
.mips,
|
||||
.mipsel,
|
||||
.sparc,
|
||||
.sparcel,
|
||||
.sparc64,
|
||||
.lanai,
|
||||
.le64,
|
||||
.nvptx,
|
||||
.nvptx64,
|
||||
.r600,
|
||||
.s390x,
|
||||
.spir64,
|
||||
.spirv64,
|
||||
.renderscript64,
|
||||
=> 8,
|
||||
|
||||
.aarch64,
|
||||
.aarch64_be,
|
||||
.mips64,
|
||||
.mips64el,
|
||||
.powerpc,
|
||||
.powerpcle,
|
||||
.powerpc64,
|
||||
.powerpc64le,
|
||||
.riscv32,
|
||||
.riscv64,
|
||||
.x86_64,
|
||||
.wasm32,
|
||||
.wasm64,
|
||||
=> 16,
|
||||
},
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
test {
|
||||
|
||||
+1
-1
@@ -26076,7 +26076,7 @@ fn coerceVarArgParam(
|
||||
.Array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}),
|
||||
.Float => float: {
|
||||
const target = sema.mod.getTarget();
|
||||
const double_bits = @import("type.zig").CType.sizeInBits(.double, target);
|
||||
const double_bits = target.c_type_bit_size(.double);
|
||||
const inst_bits = uncasted_ty.floatBits(sema.mod.getTarget());
|
||||
if (inst_bits >= double_bits) break :float inst;
|
||||
switch (double_bits) {
|
||||
|
||||
@@ -16,7 +16,6 @@ const trace = @import("../tracy.zig").trace;
|
||||
const LazySrcLoc = Module.LazySrcLoc;
|
||||
const Air = @import("../Air.zig");
|
||||
const Liveness = @import("../Liveness.zig");
|
||||
const CType = @import("../type.zig").CType;
|
||||
|
||||
const target_util = @import("../target.zig");
|
||||
const libcFloatPrefix = target_util.libcFloatPrefix;
|
||||
|
||||
@@ -19,7 +19,6 @@ const Liveness = @import("../Liveness.zig");
|
||||
const Value = @import("../value.zig").Value;
|
||||
const Type = @import("../type.zig").Type;
|
||||
const LazySrcLoc = Module.LazySrcLoc;
|
||||
const CType = @import("../type.zig").CType;
|
||||
const x86_64_abi = @import("../arch/x86_64/abi.zig");
|
||||
const wasm_c_abi = @import("../arch/wasm/abi.zig");
|
||||
const aarch64_c_abi = @import("../arch/aarch64/abi.zig");
|
||||
@@ -11043,8 +11042,8 @@ fn backendSupportsF128(target: std.Target) bool {
|
||||
fn intrinsicsAllowed(scalar_ty: Type, target: std.Target) bool {
|
||||
return switch (scalar_ty.tag()) {
|
||||
.f16 => backendSupportsF16(target),
|
||||
.f80 => (CType.longdouble.sizeInBits(target) == 80) and backendSupportsF80(target),
|
||||
.f128 => (CType.longdouble.sizeInBits(target) == 128) and backendSupportsF128(target),
|
||||
.f80 => (target.c_type_bit_size(.longdouble) == 80) and backendSupportsF80(target),
|
||||
.f128 => (target.c_type_bit_size(.longdouble) == 128) and backendSupportsF128(target),
|
||||
else => true,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3596,7 +3596,8 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
|
||||
man.hash.addOptionalBytes(options.sysroot);
|
||||
try man.addOptionalFile(options.entitlements);
|
||||
|
||||
// We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
|
||||
// We don't actually care whether it's a cache hit or miss; we just
|
||||
// need the digest and the lock.
|
||||
_ = try man.hit();
|
||||
digest = man.final();
|
||||
|
||||
@@ -4177,9 +4178,11 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
|
||||
log.debug("failed to save linking hash digest file: {s}", .{@errorName(err)});
|
||||
};
|
||||
// Again failure here only means an unnecessary cache miss.
|
||||
man.writeManifest() catch |err| {
|
||||
log.debug("failed to write cache manifest when linking: {s}", .{@errorName(err)});
|
||||
};
|
||||
if (man.have_exclusive_lock) {
|
||||
man.writeManifest() catch |err| {
|
||||
log.debug("failed to write cache manifest when linking: {s}", .{@errorName(err)});
|
||||
};
|
||||
}
|
||||
// We hang on to this lock so that the output file path can be used without
|
||||
// other processes clobbering it.
|
||||
macho_file.base.lock = man.toOwnedLock();
|
||||
|
||||
+45
-585
@@ -2937,24 +2937,24 @@ pub const Type = extern union {
|
||||
.anyframe_T,
|
||||
=> return AbiAlignmentAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) },
|
||||
|
||||
.c_short => return AbiAlignmentAdvanced{ .scalar = CType.short.alignment(target) },
|
||||
.c_ushort => return AbiAlignmentAdvanced{ .scalar = CType.ushort.alignment(target) },
|
||||
.c_int => return AbiAlignmentAdvanced{ .scalar = CType.int.alignment(target) },
|
||||
.c_uint => return AbiAlignmentAdvanced{ .scalar = CType.uint.alignment(target) },
|
||||
.c_long => return AbiAlignmentAdvanced{ .scalar = CType.long.alignment(target) },
|
||||
.c_ulong => return AbiAlignmentAdvanced{ .scalar = CType.ulong.alignment(target) },
|
||||
.c_longlong => return AbiAlignmentAdvanced{ .scalar = CType.longlong.alignment(target) },
|
||||
.c_ulonglong => return AbiAlignmentAdvanced{ .scalar = CType.ulonglong.alignment(target) },
|
||||
.c_longdouble => return AbiAlignmentAdvanced{ .scalar = CType.longdouble.alignment(target) },
|
||||
.c_short => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.short) },
|
||||
.c_ushort => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ushort) },
|
||||
.c_int => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.int) },
|
||||
.c_uint => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.uint) },
|
||||
.c_long => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.long) },
|
||||
.c_ulong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ulong) },
|
||||
.c_longlong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longlong) },
|
||||
.c_ulonglong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ulonglong) },
|
||||
.c_longdouble => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) },
|
||||
|
||||
.f16 => return AbiAlignmentAdvanced{ .scalar = 2 },
|
||||
.f32 => return AbiAlignmentAdvanced{ .scalar = CType.float.alignment(target) },
|
||||
.f64 => switch (CType.double.sizeInBits(target)) {
|
||||
64 => return AbiAlignmentAdvanced{ .scalar = CType.double.alignment(target) },
|
||||
.f32 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.float) },
|
||||
.f64 => switch (target.c_type_bit_size(.double)) {
|
||||
64 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.double) },
|
||||
else => return AbiAlignmentAdvanced{ .scalar = 8 },
|
||||
},
|
||||
.f80 => switch (CType.longdouble.sizeInBits(target)) {
|
||||
80 => return AbiAlignmentAdvanced{ .scalar = CType.longdouble.alignment(target) },
|
||||
.f80 => switch (target.c_type_bit_size(.longdouble)) {
|
||||
80 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) },
|
||||
else => {
|
||||
var payload: Payload.Bits = .{
|
||||
.base = .{ .tag = .int_unsigned },
|
||||
@@ -2964,8 +2964,8 @@ pub const Type = extern union {
|
||||
return AbiAlignmentAdvanced{ .scalar = abiAlignment(u80_ty, target) };
|
||||
},
|
||||
},
|
||||
.f128 => switch (CType.longdouble.sizeInBits(target)) {
|
||||
128 => return AbiAlignmentAdvanced{ .scalar = CType.longdouble.alignment(target) },
|
||||
.f128 => switch (target.c_type_bit_size(.longdouble)) {
|
||||
128 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) },
|
||||
else => return AbiAlignmentAdvanced{ .scalar = 16 },
|
||||
},
|
||||
|
||||
@@ -3434,21 +3434,22 @@ pub const Type = extern union {
|
||||
else => return AbiSizeAdvanced{ .scalar = @divExact(target.cpu.arch.ptrBitWidth(), 8) },
|
||||
},
|
||||
|
||||
.c_short => return AbiSizeAdvanced{ .scalar = @divExact(CType.short.sizeInBits(target), 8) },
|
||||
.c_ushort => return AbiSizeAdvanced{ .scalar = @divExact(CType.ushort.sizeInBits(target), 8) },
|
||||
.c_int => return AbiSizeAdvanced{ .scalar = @divExact(CType.int.sizeInBits(target), 8) },
|
||||
.c_uint => return AbiSizeAdvanced{ .scalar = @divExact(CType.uint.sizeInBits(target), 8) },
|
||||
.c_long => return AbiSizeAdvanced{ .scalar = @divExact(CType.long.sizeInBits(target), 8) },
|
||||
.c_ulong => return AbiSizeAdvanced{ .scalar = @divExact(CType.ulong.sizeInBits(target), 8) },
|
||||
.c_longlong => return AbiSizeAdvanced{ .scalar = @divExact(CType.longlong.sizeInBits(target), 8) },
|
||||
.c_ulonglong => return AbiSizeAdvanced{ .scalar = @divExact(CType.ulonglong.sizeInBits(target), 8) },
|
||||
.c_short => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.short) },
|
||||
.c_ushort => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ushort) },
|
||||
.c_int => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.int) },
|
||||
.c_uint => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.uint) },
|
||||
.c_long => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.long) },
|
||||
.c_ulong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulong) },
|
||||
.c_longlong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longlong) },
|
||||
.c_ulonglong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulonglong) },
|
||||
.c_longdouble => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) },
|
||||
|
||||
.f16 => return AbiSizeAdvanced{ .scalar = 2 },
|
||||
.f32 => return AbiSizeAdvanced{ .scalar = 4 },
|
||||
.f64 => return AbiSizeAdvanced{ .scalar = 8 },
|
||||
.f128 => return AbiSizeAdvanced{ .scalar = 16 },
|
||||
.f80 => switch (CType.longdouble.sizeInBits(target)) {
|
||||
80 => return AbiSizeAdvanced{ .scalar = std.mem.alignForward(10, CType.longdouble.alignment(target)) },
|
||||
.f80 => switch (target.c_type_bit_size(.longdouble)) {
|
||||
80 => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) },
|
||||
else => {
|
||||
var payload: Payload.Bits = .{
|
||||
.base = .{ .tag = .int_unsigned },
|
||||
@@ -3458,14 +3459,6 @@ pub const Type = extern union {
|
||||
return AbiSizeAdvanced{ .scalar = abiSize(u80_ty, target) };
|
||||
},
|
||||
},
|
||||
.c_longdouble => switch (CType.longdouble.sizeInBits(target)) {
|
||||
16 => return AbiSizeAdvanced{ .scalar = abiSize(Type.f16, target) },
|
||||
32 => return AbiSizeAdvanced{ .scalar = abiSize(Type.f32, target) },
|
||||
64 => return AbiSizeAdvanced{ .scalar = abiSize(Type.f64, target) },
|
||||
80 => return AbiSizeAdvanced{ .scalar = abiSize(Type.f80, target) },
|
||||
128 => return AbiSizeAdvanced{ .scalar = abiSize(Type.f128, target) },
|
||||
else => unreachable,
|
||||
},
|
||||
|
||||
// TODO revisit this when we have the concept of the error tag type
|
||||
.anyerror_void_error_union,
|
||||
@@ -3748,15 +3741,15 @@ pub const Type = extern union {
|
||||
.manyptr_const_u8_sentinel_0,
|
||||
=> return target.cpu.arch.ptrBitWidth(),
|
||||
|
||||
.c_short => return CType.short.sizeInBits(target),
|
||||
.c_ushort => return CType.ushort.sizeInBits(target),
|
||||
.c_int => return CType.int.sizeInBits(target),
|
||||
.c_uint => return CType.uint.sizeInBits(target),
|
||||
.c_long => return CType.long.sizeInBits(target),
|
||||
.c_ulong => return CType.ulong.sizeInBits(target),
|
||||
.c_longlong => return CType.longlong.sizeInBits(target),
|
||||
.c_ulonglong => return CType.ulonglong.sizeInBits(target),
|
||||
.c_longdouble => return CType.longdouble.sizeInBits(target),
|
||||
.c_short => return target.c_type_bit_size(.short),
|
||||
.c_ushort => return target.c_type_bit_size(.ushort),
|
||||
.c_int => return target.c_type_bit_size(.int),
|
||||
.c_uint => return target.c_type_bit_size(.uint),
|
||||
.c_long => return target.c_type_bit_size(.long),
|
||||
.c_ulong => return target.c_type_bit_size(.ulong),
|
||||
.c_longlong => return target.c_type_bit_size(.longlong),
|
||||
.c_ulonglong => return target.c_type_bit_size(.ulonglong),
|
||||
.c_longdouble => return target.c_type_bit_size(.longdouble),
|
||||
|
||||
.error_set,
|
||||
.error_set_single,
|
||||
@@ -4631,14 +4624,14 @@ pub const Type = extern union {
|
||||
.i128 => return .{ .signedness = .signed, .bits = 128 },
|
||||
.usize => return .{ .signedness = .unsigned, .bits = target.cpu.arch.ptrBitWidth() },
|
||||
.isize => return .{ .signedness = .signed, .bits = target.cpu.arch.ptrBitWidth() },
|
||||
.c_short => return .{ .signedness = .signed, .bits = CType.short.sizeInBits(target) },
|
||||
.c_ushort => return .{ .signedness = .unsigned, .bits = CType.ushort.sizeInBits(target) },
|
||||
.c_int => return .{ .signedness = .signed, .bits = CType.int.sizeInBits(target) },
|
||||
.c_uint => return .{ .signedness = .unsigned, .bits = CType.uint.sizeInBits(target) },
|
||||
.c_long => return .{ .signedness = .signed, .bits = CType.long.sizeInBits(target) },
|
||||
.c_ulong => return .{ .signedness = .unsigned, .bits = CType.ulong.sizeInBits(target) },
|
||||
.c_longlong => return .{ .signedness = .signed, .bits = CType.longlong.sizeInBits(target) },
|
||||
.c_ulonglong => return .{ .signedness = .unsigned, .bits = CType.ulonglong.sizeInBits(target) },
|
||||
.c_short => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.short) },
|
||||
.c_ushort => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ushort) },
|
||||
.c_int => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.int) },
|
||||
.c_uint => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.uint) },
|
||||
.c_long => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.long) },
|
||||
.c_ulong => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulong) },
|
||||
.c_longlong => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.longlong) },
|
||||
.c_ulonglong => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulonglong) },
|
||||
|
||||
.enum_full, .enum_nonexhaustive => ty = ty.cast(Payload.EnumFull).?.data.tag_ty,
|
||||
.enum_numbered => ty = ty.castTag(.enum_numbered).?.data.tag_ty,
|
||||
@@ -4724,7 +4717,7 @@ pub const Type = extern union {
|
||||
.f64 => 64,
|
||||
.f80 => 80,
|
||||
.f128, .comptime_float => 128,
|
||||
.c_longdouble => CType.longdouble.sizeInBits(target),
|
||||
.c_longdouble => target.c_type_bit_size(.longdouble),
|
||||
|
||||
else => unreachable,
|
||||
};
|
||||
@@ -6689,536 +6682,3 @@ pub const Type = extern union {
|
||||
/// to packed struct layout to find out all the places in the codebase you need to edit!
|
||||
pub const packed_struct_layout_version = 2;
|
||||
};
|
||||
|
||||
pub const CType = enum {
|
||||
short,
|
||||
ushort,
|
||||
int,
|
||||
uint,
|
||||
long,
|
||||
ulong,
|
||||
longlong,
|
||||
ulonglong,
|
||||
longdouble,
|
||||
|
||||
// We don't have a `c_float`/`c_double` type in Zig, but these
|
||||
// are useful for querying target-correct alignment and checking
|
||||
// whether C's double is f64 or f32
|
||||
float,
|
||||
double,
|
||||
|
||||
pub fn sizeInBits(self: CType, target: Target) u16 {
|
||||
switch (target.os.tag) {
|
||||
.freestanding, .other => switch (target.cpu.arch) {
|
||||
.msp430 => switch (self) {
|
||||
.short, .ushort, .int, .uint => return 16,
|
||||
.float, .long, .ulong => return 32,
|
||||
.longlong, .ulonglong, .double, .longdouble => return 64,
|
||||
},
|
||||
.avr => switch (self) {
|
||||
.short, .ushort, .int, .uint => return 16,
|
||||
.long, .ulong, .float, .double, .longdouble => return 32,
|
||||
.longlong, .ulonglong => return 64,
|
||||
},
|
||||
.tce, .tcele => switch (self) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .long, .ulong, .longlong, .ulonglong => return 32,
|
||||
.float, .double, .longdouble => return 32,
|
||||
},
|
||||
.mips64, .mips64el => switch (self) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong => return if (target.abi != .gnuabin32) 64 else 32,
|
||||
.longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => return 128,
|
||||
},
|
||||
.x86_64 => switch (self) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong => switch (target.abi) {
|
||||
.gnux32, .muslx32 => return 32,
|
||||
else => return 64,
|
||||
},
|
||||
.longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => return 80,
|
||||
},
|
||||
else => switch (self) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong => return target.cpu.arch.ptrBitWidth(),
|
||||
.longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => switch (target.cpu.arch) {
|
||||
.x86 => switch (target.abi) {
|
||||
.android => return 64,
|
||||
else => return 80,
|
||||
},
|
||||
|
||||
.powerpc,
|
||||
.powerpcle,
|
||||
.powerpc64,
|
||||
.powerpc64le,
|
||||
=> switch (target.abi) {
|
||||
.musl,
|
||||
.musleabi,
|
||||
.musleabihf,
|
||||
.muslx32,
|
||||
=> return 64,
|
||||
else => return 128,
|
||||
},
|
||||
|
||||
.riscv32,
|
||||
.riscv64,
|
||||
.aarch64,
|
||||
.aarch64_be,
|
||||
.aarch64_32,
|
||||
.s390x,
|
||||
.sparc,
|
||||
.sparc64,
|
||||
.sparcel,
|
||||
.wasm32,
|
||||
.wasm64,
|
||||
=> return 128,
|
||||
|
||||
else => return 64,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
.linux,
|
||||
.freebsd,
|
||||
.netbsd,
|
||||
.dragonfly,
|
||||
.openbsd,
|
||||
.wasi,
|
||||
.emscripten,
|
||||
.plan9,
|
||||
.solaris,
|
||||
.haiku,
|
||||
.ananas,
|
||||
.fuchsia,
|
||||
.minix,
|
||||
=> switch (target.cpu.arch) {
|
||||
.msp430 => switch (self) {
|
||||
.short, .ushort, .int, .uint => return 16,
|
||||
.long, .ulong, .float => return 32,
|
||||
.longlong, .ulonglong, .double, .longdouble => return 64,
|
||||
},
|
||||
.avr => switch (self) {
|
||||
.short, .ushort, .int, .uint => return 16,
|
||||
.long, .ulong, .float, .double, .longdouble => return 32,
|
||||
.longlong, .ulonglong => return 64,
|
||||
},
|
||||
.tce, .tcele => switch (self) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .long, .ulong, .longlong, .ulonglong => return 32,
|
||||
.float, .double, .longdouble => return 32,
|
||||
},
|
||||
.mips64, .mips64el => switch (self) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong => return if (target.abi != .gnuabin32) 64 else 32,
|
||||
.longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => if (target.os.tag == .freebsd) return 64 else return 128,
|
||||
},
|
||||
.x86_64 => switch (self) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong => switch (target.abi) {
|
||||
.gnux32, .muslx32 => return 32,
|
||||
else => return 64,
|
||||
},
|
||||
.longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => return 80,
|
||||
},
|
||||
else => switch (self) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong => return target.cpu.arch.ptrBitWidth(),
|
||||
.longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => switch (target.cpu.arch) {
|
||||
.x86 => switch (target.abi) {
|
||||
.android => return 64,
|
||||
else => return 80,
|
||||
},
|
||||
|
||||
.powerpc,
|
||||
.powerpcle,
|
||||
=> switch (target.abi) {
|
||||
.musl,
|
||||
.musleabi,
|
||||
.musleabihf,
|
||||
.muslx32,
|
||||
=> return 64,
|
||||
else => switch (target.os.tag) {
|
||||
.freebsd, .netbsd, .openbsd => return 64,
|
||||
else => return 128,
|
||||
},
|
||||
},
|
||||
|
||||
.powerpc64,
|
||||
.powerpc64le,
|
||||
=> switch (target.abi) {
|
||||
.musl,
|
||||
.musleabi,
|
||||
.musleabihf,
|
||||
.muslx32,
|
||||
=> return 64,
|
||||
else => switch (target.os.tag) {
|
||||
.freebsd, .openbsd => return 64,
|
||||
else => return 128,
|
||||
},
|
||||
},
|
||||
|
||||
.riscv32,
|
||||
.riscv64,
|
||||
.aarch64,
|
||||
.aarch64_be,
|
||||
.aarch64_32,
|
||||
.s390x,
|
||||
.mips64,
|
||||
.mips64el,
|
||||
.sparc,
|
||||
.sparc64,
|
||||
.sparcel,
|
||||
.wasm32,
|
||||
.wasm64,
|
||||
=> return 128,
|
||||
|
||||
else => return 64,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
.windows, .uefi => switch (target.cpu.arch) {
|
||||
.x86 => switch (self) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong => return 32,
|
||||
.longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => switch (target.abi) {
|
||||
.gnu, .gnuilp32, .cygnus => return 80,
|
||||
else => return 64,
|
||||
},
|
||||
},
|
||||
.x86_64 => switch (self) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong => switch (target.abi) {
|
||||
.cygnus => return 64,
|
||||
else => return 32,
|
||||
},
|
||||
.longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => switch (target.abi) {
|
||||
.gnu, .gnuilp32, .cygnus => return 80,
|
||||
else => return 64,
|
||||
},
|
||||
},
|
||||
else => switch (self) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong => return 32,
|
||||
.longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => return 64,
|
||||
},
|
||||
},
|
||||
|
||||
.macos, .ios, .tvos, .watchos => switch (self) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong => switch (target.cpu.arch) {
|
||||
.x86, .arm, .aarch64_32 => return 32,
|
||||
.x86_64 => switch (target.abi) {
|
||||
.gnux32, .muslx32 => return 32,
|
||||
else => return 64,
|
||||
},
|
||||
else => return 64,
|
||||
},
|
||||
.longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => switch (target.cpu.arch) {
|
||||
.x86 => switch (target.abi) {
|
||||
.android => return 64,
|
||||
else => return 80,
|
||||
},
|
||||
.x86_64 => return 80,
|
||||
else => return 64,
|
||||
},
|
||||
},
|
||||
|
||||
.nvcl, .cuda => switch (self) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong => switch (target.cpu.arch) {
|
||||
.nvptx => return 32,
|
||||
.nvptx64 => return 64,
|
||||
else => return 64,
|
||||
},
|
||||
.longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => return 64,
|
||||
},
|
||||
|
||||
.amdhsa, .amdpal => switch (self) {
|
||||
.short, .ushort => return 16,
|
||||
.int, .uint, .float => return 32,
|
||||
.long, .ulong, .longlong, .ulonglong, .double => return 64,
|
||||
.longdouble => return 128,
|
||||
},
|
||||
|
||||
.cloudabi,
|
||||
.kfreebsd,
|
||||
.lv2,
|
||||
.zos,
|
||||
.rtems,
|
||||
.nacl,
|
||||
.aix,
|
||||
.ps4,
|
||||
.ps5,
|
||||
.elfiamcu,
|
||||
.mesa3d,
|
||||
.contiki,
|
||||
.hermit,
|
||||
.hurd,
|
||||
.opencl,
|
||||
.glsl450,
|
||||
.vulkan,
|
||||
.driverkit,
|
||||
.shadermodel,
|
||||
=> @panic("TODO specify the C integer and float type sizes for this OS"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alignment(self: CType, target: Target) u16 {
|
||||
|
||||
// Overrides for unusual alignments
|
||||
switch (target.cpu.arch) {
|
||||
.avr => switch (self) {
|
||||
.short, .ushort => return 2,
|
||||
else => return 1,
|
||||
},
|
||||
.x86 => switch (target.os.tag) {
|
||||
.windows, .uefi => switch (self) {
|
||||
.longlong, .ulonglong, .double => return 8,
|
||||
.longdouble => switch (target.abi) {
|
||||
.gnu, .gnuilp32, .cygnus => return 4,
|
||||
else => return 8,
|
||||
},
|
||||
else => {},
|
||||
},
|
||||
else => {},
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
||||
// Next-power-of-two-aligned, up to a maximum.
|
||||
return @min(
|
||||
std.math.ceilPowerOfTwoAssert(u16, (self.sizeInBits(target) + 7) / 8),
|
||||
switch (target.cpu.arch) {
|
||||
.arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) {
|
||||
.netbsd => switch (target.abi) {
|
||||
.gnueabi,
|
||||
.gnueabihf,
|
||||
.eabi,
|
||||
.eabihf,
|
||||
.android,
|
||||
.musleabi,
|
||||
.musleabihf,
|
||||
=> 8,
|
||||
|
||||
else => @as(u16, 4),
|
||||
},
|
||||
.ios, .tvos, .watchos => 4,
|
||||
else => 8,
|
||||
},
|
||||
|
||||
.msp430,
|
||||
.avr,
|
||||
=> 2,
|
||||
|
||||
.arc,
|
||||
.csky,
|
||||
.x86,
|
||||
.xcore,
|
||||
.dxil,
|
||||
.loongarch32,
|
||||
.tce,
|
||||
.tcele,
|
||||
.le32,
|
||||
.amdil,
|
||||
.hsail,
|
||||
.spir,
|
||||
.spirv32,
|
||||
.kalimba,
|
||||
.shave,
|
||||
.renderscript32,
|
||||
.ve,
|
||||
.spu_2,
|
||||
=> 4,
|
||||
|
||||
.aarch64_32,
|
||||
.amdgcn,
|
||||
.amdil64,
|
||||
.bpfel,
|
||||
.bpfeb,
|
||||
.hexagon,
|
||||
.hsail64,
|
||||
.loongarch64,
|
||||
.m68k,
|
||||
.mips,
|
||||
.mipsel,
|
||||
.sparc,
|
||||
.sparcel,
|
||||
.sparc64,
|
||||
.lanai,
|
||||
.le64,
|
||||
.nvptx,
|
||||
.nvptx64,
|
||||
.r600,
|
||||
.s390x,
|
||||
.spir64,
|
||||
.spirv64,
|
||||
.renderscript64,
|
||||
=> 8,
|
||||
|
||||
.aarch64,
|
||||
.aarch64_be,
|
||||
.mips64,
|
||||
.mips64el,
|
||||
.powerpc,
|
||||
.powerpcle,
|
||||
.powerpc64,
|
||||
.powerpc64le,
|
||||
.riscv32,
|
||||
.riscv64,
|
||||
.x86_64,
|
||||
.wasm32,
|
||||
.wasm64,
|
||||
=> 16,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
pub fn preferredAlignment(self: CType, target: Target) u16 {
|
||||
|
||||
// Overrides for unusual alignments
|
||||
switch (target.cpu.arch) {
|
||||
.arm, .armeb, .thumb, .thumbeb => switch (target.os.tag) {
|
||||
.netbsd => switch (target.abi) {
|
||||
.gnueabi,
|
||||
.gnueabihf,
|
||||
.eabi,
|
||||
.eabihf,
|
||||
.android,
|
||||
.musleabi,
|
||||
.musleabihf,
|
||||
=> {},
|
||||
|
||||
else => switch (self) {
|
||||
.longdouble => return 4,
|
||||
else => {},
|
||||
},
|
||||
},
|
||||
.ios, .tvos, .watchos => switch (self) {
|
||||
.longdouble => return 4,
|
||||
else => {},
|
||||
},
|
||||
else => {},
|
||||
},
|
||||
.arc => switch (self) {
|
||||
.longdouble => return 4,
|
||||
else => {},
|
||||
},
|
||||
.avr => switch (self) {
|
||||
.int, .uint, .long, .ulong, .float, .longdouble => return 1,
|
||||
.short, .ushort => return 2,
|
||||
.double => return 4,
|
||||
.longlong, .ulonglong => return 8,
|
||||
},
|
||||
.x86 => switch (target.os.tag) {
|
||||
.windows, .uefi => switch (self) {
|
||||
.longdouble => switch (target.abi) {
|
||||
.gnu, .gnuilp32, .cygnus => return 4,
|
||||
else => return 8,
|
||||
},
|
||||
else => {},
|
||||
},
|
||||
else => switch (self) {
|
||||
.longdouble => return 4,
|
||||
else => {},
|
||||
},
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
|
||||
// Next-power-of-two-aligned, up to a maximum.
|
||||
return @min(
|
||||
std.math.ceilPowerOfTwoAssert(u16, (self.sizeInBits(target) + 7) / 8),
|
||||
switch (target.cpu.arch) {
|
||||
.msp430 => @as(u16, 2),
|
||||
|
||||
.csky,
|
||||
.xcore,
|
||||
.dxil,
|
||||
.loongarch32,
|
||||
.tce,
|
||||
.tcele,
|
||||
.le32,
|
||||
.amdil,
|
||||
.hsail,
|
||||
.spir,
|
||||
.spirv32,
|
||||
.kalimba,
|
||||
.shave,
|
||||
.renderscript32,
|
||||
.ve,
|
||||
.spu_2,
|
||||
=> 4,
|
||||
|
||||
.arc,
|
||||
.arm,
|
||||
.armeb,
|
||||
.avr,
|
||||
.thumb,
|
||||
.thumbeb,
|
||||
.aarch64_32,
|
||||
.amdgcn,
|
||||
.amdil64,
|
||||
.bpfel,
|
||||
.bpfeb,
|
||||
.hexagon,
|
||||
.hsail64,
|
||||
.x86,
|
||||
.loongarch64,
|
||||
.m68k,
|
||||
.mips,
|
||||
.mipsel,
|
||||
.sparc,
|
||||
.sparcel,
|
||||
.sparc64,
|
||||
.lanai,
|
||||
.le64,
|
||||
.nvptx,
|
||||
.nvptx64,
|
||||
.r600,
|
||||
.s390x,
|
||||
.spir64,
|
||||
.spirv64,
|
||||
.renderscript64,
|
||||
=> 8,
|
||||
|
||||
.aarch64,
|
||||
.aarch64_be,
|
||||
.mips64,
|
||||
.mips64el,
|
||||
.powerpc,
|
||||
.powerpcle,
|
||||
.powerpc64,
|
||||
.powerpc64le,
|
||||
.riscv32,
|
||||
.riscv64,
|
||||
.x86_64,
|
||||
.wasm32,
|
||||
.wasm64,
|
||||
=> 16,
|
||||
},
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const builtin = @import("std").builtin;
|
||||
export fn entry() void {
|
||||
const foo = builtin.Mode.x86;
|
||||
const foo = builtin.OptimizeMode.x86;
|
||||
_ = foo;
|
||||
}
|
||||
|
||||
@@ -8,5 +8,5 @@ export fn entry() void {
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :3:30: error: enum 'builtin.Mode' has no member named 'x86'
|
||||
// :3:38: error: enum 'builtin.OptimizeMode' has no member named 'x86'
|
||||
// :?:18: note: enum declared here
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const test_step = b.step("test", "Test");
|
||||
|
||||
const exe = b.addExecutable("bss", "main.zig");
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "bss",
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = optimize,
|
||||
});
|
||||
b.default_step.dependOn(&exe.step);
|
||||
exe.setBuildMode(mode);
|
||||
|
||||
const run = exe.run();
|
||||
run.expectStdOutEqual("0, 1, 0\n");
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const lib_a = b.addStaticLibrary("a", null);
|
||||
const lib_a = b.addStaticLibrary(.{
|
||||
.name = "a",
|
||||
.optimize = optimize,
|
||||
.target = .{},
|
||||
});
|
||||
lib_a.addCSourceFiles(&.{ "c.c", "a.c", "b.c" }, &.{"-fcommon"});
|
||||
lib_a.setBuildMode(mode);
|
||||
|
||||
const test_exe = b.addTest("main.zig");
|
||||
test_exe.setBuildMode(mode);
|
||||
const test_exe = b.addTest(.{
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = optimize,
|
||||
});
|
||||
test_exe.linkLibrary(lib_a);
|
||||
|
||||
const test_step = b.step("test", "Test it");
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target = b.standardTargetOptions(.{});
|
||||
|
||||
const lib_a = b.addStaticLibrary("a", null);
|
||||
const lib_a = b.addStaticLibrary(.{
|
||||
.name = "a",
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
lib_a.addCSourceFiles(&.{"a.c"}, &.{"-fcommon"});
|
||||
lib_a.setBuildMode(mode);
|
||||
|
||||
const test_exe = b.addTest("main.zig");
|
||||
test_exe.setBuildMode(mode);
|
||||
const test_exe = b.addTest(.{
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
test_exe.linkLibrary(lib_a);
|
||||
|
||||
const test_step = b.step("test", "Test it");
|
||||
|
||||
@@ -1,20 +1,30 @@
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target = b.standardTargetOptions(.{});
|
||||
|
||||
const lib_a = b.addStaticLibrary("a", null);
|
||||
const lib_a = b.addStaticLibrary(.{
|
||||
.name = "a",
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
lib_a.addCSourceFile("a.c", &[_][]const u8{});
|
||||
lib_a.setBuildMode(mode);
|
||||
lib_a.addIncludePath(".");
|
||||
|
||||
const lib_b = b.addStaticLibrary("b", null);
|
||||
const lib_b = b.addStaticLibrary(.{
|
||||
.name = "b",
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
lib_b.addCSourceFile("b.c", &[_][]const u8{});
|
||||
lib_b.setBuildMode(mode);
|
||||
lib_b.addIncludePath(".");
|
||||
|
||||
const test_exe = b.addTest("main.zig");
|
||||
test_exe.setBuildMode(mode);
|
||||
const test_exe = b.addTest(.{
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
test_exe.linkLibrary(lib_a);
|
||||
test_exe.linkLibrary(lib_b);
|
||||
test_exe.addIncludePath(".");
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const target: std.zig.CrossTarget = .{ .os_tag = .macos };
|
||||
const target_info = std.zig.system.NativeTargetInfo.detect(target) catch unreachable;
|
||||
@@ -11,7 +10,10 @@ pub fn build(b: *Builder) void {
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
|
||||
const exe = b.addExecutable("test", null);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "test",
|
||||
.optimize = optimize,
|
||||
});
|
||||
b.default_step.dependOn(&exe.step);
|
||||
exe.addIncludePath(std.fs.path.join(b.allocator, &.{ sdk.path, "/usr/include" }) catch unreachable);
|
||||
exe.addIncludePath(std.fs.path.join(b.allocator, &.{ sdk.path, "/usr/include/c++/v1" }) catch unreachable);
|
||||
@@ -20,7 +22,6 @@ pub fn build(b: *Builder) void {
|
||||
"-nostdinc++",
|
||||
});
|
||||
exe.addObjectFile(std.fs.path.join(b.allocator, &.{ sdk.path, "/usr/lib/libc++.tbd" }) catch unreachable);
|
||||
exe.setBuildMode(mode);
|
||||
|
||||
const run_cmd = exe.run();
|
||||
run_cmd.expectStdErrEqual("x: 5\n");
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
const LibExeObjectStep = std.build.LibExeObjStep;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target: std.zig.CrossTarget = .{ .os_tag = .macos };
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
|
||||
const exe = b.addExecutable("test", "main.zig");
|
||||
exe.setBuildMode(mode);
|
||||
exe.setTarget(target);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "test",
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
|
||||
const run = exe.runEmulatable();
|
||||
test_step.dependOn(&run.step);
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
const LibExeObjectStep = std.build.LibExeObjStep;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target: std.zig.CrossTarget = .{ .os_tag = .macos };
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
@@ -11,7 +9,7 @@ pub fn build(b: *Builder) void {
|
||||
|
||||
{
|
||||
// Without -dead_strip, we expect `iAmUnused` symbol present
|
||||
const exe = createScenario(b, mode, target);
|
||||
const exe = createScenario(b, optimize, target);
|
||||
|
||||
const check = exe.checkObject(.macho);
|
||||
check.checkInSymtab();
|
||||
@@ -24,7 +22,7 @@ pub fn build(b: *Builder) void {
|
||||
|
||||
{
|
||||
// With -dead_strip, no `iAmUnused` symbol should be present
|
||||
const exe = createScenario(b, mode, target);
|
||||
const exe = createScenario(b, optimize, target);
|
||||
exe.link_gc_sections = true;
|
||||
|
||||
const check = exe.checkObject(.macho);
|
||||
@@ -37,11 +35,17 @@ pub fn build(b: *Builder) void {
|
||||
}
|
||||
}
|
||||
|
||||
fn createScenario(b: *Builder, mode: std.builtin.Mode, target: std.zig.CrossTarget) *LibExeObjectStep {
|
||||
const exe = b.addExecutable("test", null);
|
||||
fn createScenario(
|
||||
b: *std.Build,
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
target: std.zig.CrossTarget,
|
||||
) *std.Build.CompileStep {
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "test",
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
exe.addCSourceFile("main.c", &[0][]const u8{});
|
||||
exe.setBuildMode(mode);
|
||||
exe.setTarget(target);
|
||||
exe.linkLibC();
|
||||
return exe;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
const LibExeObjectStep = std.build.LibExeObjStep;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
{
|
||||
// Without -dead_strip_dylibs we expect `-la` to include liba.dylib in the final executable
|
||||
const exe = createScenario(b, mode);
|
||||
const exe = createScenario(b, optimize);
|
||||
|
||||
const check = exe.checkObject(.macho);
|
||||
check.checkStart("cmd LOAD_DYLIB");
|
||||
@@ -27,7 +25,7 @@ pub fn build(b: *Builder) void {
|
||||
|
||||
{
|
||||
// With -dead_strip_dylibs, we should include liba.dylib as it's unreachable
|
||||
const exe = createScenario(b, mode);
|
||||
const exe = createScenario(b, optimize);
|
||||
exe.dead_strip_dylibs = true;
|
||||
|
||||
const run_cmd = exe.run();
|
||||
@@ -36,10 +34,12 @@ pub fn build(b: *Builder) void {
|
||||
}
|
||||
}
|
||||
|
||||
fn createScenario(b: *Builder, mode: std.builtin.Mode) *LibExeObjectStep {
|
||||
const exe = b.addExecutable("test", null);
|
||||
fn createScenario(b: *std.Build, optimize: std.builtin.OptimizeMode) *std.Build.CompileStep {
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "test",
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe.addCSourceFile("main.c", &[0][]const u8{});
|
||||
exe.setBuildMode(mode);
|
||||
exe.linkLibC();
|
||||
exe.linkFramework("Cocoa");
|
||||
return exe;
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target: std.zig.CrossTarget = .{ .os_tag = .macos };
|
||||
|
||||
const test_step = b.step("test", "Test");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
const dylib = b.addSharedLibrary("a", null, b.version(1, 0, 0));
|
||||
dylib.setBuildMode(mode);
|
||||
dylib.setTarget(target);
|
||||
const dylib = b.addSharedLibrary(.{
|
||||
.name = "a",
|
||||
.version = .{ .major = 1, .minor = 0 },
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
dylib.addCSourceFile("a.c", &.{});
|
||||
dylib.linkLibC();
|
||||
dylib.install();
|
||||
@@ -24,9 +26,11 @@ pub fn build(b: *Builder) void {
|
||||
|
||||
test_step.dependOn(&check_dylib.step);
|
||||
|
||||
const exe = b.addExecutable("main", null);
|
||||
exe.setTarget(target);
|
||||
exe.setBuildMode(mode);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "main",
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
exe.addCSourceFile("main.c", &.{});
|
||||
exe.linkSystemLibrary("a");
|
||||
exe.linkLibC();
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target: std.zig.CrossTarget = .{ .os_tag = .macos };
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
const exe = b.addExecutable("test", null);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "test",
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
exe.addCSourceFile("main.c", &[0][]const u8{});
|
||||
exe.addCSourceFile("empty.c", &[0][]const u8{});
|
||||
exe.setBuildMode(mode);
|
||||
exe.setTarget(target);
|
||||
exe.linkLibC();
|
||||
|
||||
const run_cmd = std.build.EmulatableRunStep.create(b, "run", exe);
|
||||
const run_cmd = std.Build.EmulatableRunStep.create(b, "run", exe);
|
||||
run_cmd.expectStdOutEqual("Hello!\n");
|
||||
test_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const test_step = b.step("test", "Test");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
const exe = b.addExecutable("main", null);
|
||||
exe.setTarget(.{ .os_tag = .macos });
|
||||
exe.setBuildMode(mode);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "main",
|
||||
.optimize = optimize,
|
||||
.target = .{ .os_tag = .macos },
|
||||
});
|
||||
exe.addCSourceFile("main.c", &.{});
|
||||
exe.linkLibC();
|
||||
exe.entry_symbol_name = "_non_main";
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const Builder = std.build.Builder;
|
||||
const LibExeObjectStep = std.build.LibExeObjStep;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const test_step = b.step("test", "Test");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
{
|
||||
// Test -headerpad_max_install_names
|
||||
const exe = simpleExe(b, mode);
|
||||
const exe = simpleExe(b, optimize);
|
||||
exe.headerpad_max_install_names = true;
|
||||
|
||||
const check = exe.checkObject(.macho);
|
||||
@@ -36,7 +34,7 @@ pub fn build(b: *Builder) void {
|
||||
|
||||
{
|
||||
// Test -headerpad
|
||||
const exe = simpleExe(b, mode);
|
||||
const exe = simpleExe(b, optimize);
|
||||
exe.headerpad_size = 0x10000;
|
||||
|
||||
const check = exe.checkObject(.macho);
|
||||
@@ -52,7 +50,7 @@ pub fn build(b: *Builder) void {
|
||||
|
||||
{
|
||||
// Test both flags with -headerpad overriding -headerpad_max_install_names
|
||||
const exe = simpleExe(b, mode);
|
||||
const exe = simpleExe(b, optimize);
|
||||
exe.headerpad_max_install_names = true;
|
||||
exe.headerpad_size = 0x10000;
|
||||
|
||||
@@ -69,7 +67,7 @@ pub fn build(b: *Builder) void {
|
||||
|
||||
{
|
||||
// Test both flags with -headerpad_max_install_names overriding -headerpad
|
||||
const exe = simpleExe(b, mode);
|
||||
const exe = simpleExe(b, optimize);
|
||||
exe.headerpad_size = 0x1000;
|
||||
exe.headerpad_max_install_names = true;
|
||||
|
||||
@@ -94,9 +92,11 @@ pub fn build(b: *Builder) void {
|
||||
}
|
||||
}
|
||||
|
||||
fn simpleExe(b: *Builder, mode: std.builtin.Mode) *LibExeObjectStep {
|
||||
const exe = b.addExecutable("main", null);
|
||||
exe.setBuildMode(mode);
|
||||
fn simpleExe(b: *std.Build, optimize: std.builtin.OptimizeMode) *std.Build.CompileStep {
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "main",
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe.addCSourceFile("main.c", &.{});
|
||||
exe.linkLibC();
|
||||
exe.linkFramework("CoreFoundation");
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.build.Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target = std.zig.CrossTarget{ .os_tag = .macos };
|
||||
|
||||
const test_step = b.step("test", "Test");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
const obj = b.addObject("test", "main.zig");
|
||||
obj.setBuildMode(mode);
|
||||
obj.setTarget(target);
|
||||
const obj = b.addObject(.{
|
||||
.name = "test",
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
|
||||
const check = obj.checkObject(.macho);
|
||||
|
||||
@@ -19,7 +22,7 @@ pub fn build(b: *std.build.Builder) void {
|
||||
check.checkInSymtab();
|
||||
check.checkNext("{*} (__TEXT,__TestFn) external _testFn");
|
||||
|
||||
if (mode == .Debug) {
|
||||
if (optimize == .Debug) {
|
||||
check.checkInSymtab();
|
||||
check.checkNext("{*} (__TEXT,__TestGenFnA) _main.testGenericFn__anon_{*}");
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
const LibExeObjectStep = std.build.LibExeObjStep;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
// -dead_strip_dylibs
|
||||
// -needed_framework Cocoa
|
||||
const exe = b.addExecutable("test", null);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "test",
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe.addCSourceFile("main.c", &[0][]const u8{});
|
||||
exe.setBuildMode(mode);
|
||||
exe.linkLibC();
|
||||
exe.linkFrameworkNeeded("Cocoa");
|
||||
exe.dead_strip_dylibs = true;
|
||||
|
||||
@@ -1,27 +1,30 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
const LibExeObjectStep = std.build.LibExeObjStep;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target: std.zig.CrossTarget = .{ .os_tag = .macos };
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
const dylib = b.addSharedLibrary("a", null, b.version(1, 0, 0));
|
||||
dylib.setTarget(target);
|
||||
dylib.setBuildMode(mode);
|
||||
const dylib = b.addSharedLibrary(.{
|
||||
.name = "a",
|
||||
.version = .{ .major = 1, .minor = 0 },
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
dylib.addCSourceFile("a.c", &.{});
|
||||
dylib.linkLibC();
|
||||
dylib.install();
|
||||
|
||||
// -dead_strip_dylibs
|
||||
// -needed-la
|
||||
const exe = b.addExecutable("test", null);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "test",
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
exe.addCSourceFile("main.c", &[0][]const u8{});
|
||||
exe.setBuildMode(mode);
|
||||
exe.setTarget(target);
|
||||
exe.linkLibC();
|
||||
exe.linkSystemLibraryNeeded("a");
|
||||
exe.addLibraryPath(b.pathFromRoot("zig-out/lib"));
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
|
||||
const exe = b.addExecutable("test", null);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "test",
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe.addIncludePath(".");
|
||||
exe.addCSourceFile("Foo.m", &[0][]const u8{});
|
||||
exe.addCSourceFile("test.m", &[0][]const u8{});
|
||||
exe.setBuildMode(mode);
|
||||
exe.linkLibC();
|
||||
// TODO when we figure out how to ship framework stubs for cross-compilation,
|
||||
// populate paths to the sysroot here.
|
||||
exe.linkFramework("Foundation");
|
||||
|
||||
const run_cmd = std.build.EmulatableRunStep.create(b, "run", exe);
|
||||
const run_cmd = std.Build.EmulatableRunStep.create(b, "run", exe);
|
||||
test_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
|
||||
const exe = b.addExecutable("test", null);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "test",
|
||||
.optimize = optimize,
|
||||
});
|
||||
b.default_step.dependOn(&exe.step);
|
||||
exe.addIncludePath(".");
|
||||
exe.addCSourceFile("Foo.mm", &[0][]const u8{});
|
||||
exe.addCSourceFile("test.mm", &[0][]const u8{});
|
||||
exe.setBuildMode(mode);
|
||||
exe.linkLibCpp();
|
||||
// TODO when we figure out how to ship framework stubs for cross-compilation,
|
||||
// populate paths to the sysroot here.
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target: std.zig.CrossTarget = .{ .os_tag = .macos };
|
||||
|
||||
const test_step = b.step("test", "Test");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
{
|
||||
const exe = b.addExecutable("pagezero", null);
|
||||
exe.setTarget(target);
|
||||
exe.setBuildMode(mode);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "pagezero",
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
exe.addCSourceFile("main.c", &.{});
|
||||
exe.linkLibC();
|
||||
exe.pagezero_size = 0x4000;
|
||||
@@ -29,9 +30,11 @@ pub fn build(b: *Builder) void {
|
||||
}
|
||||
|
||||
{
|
||||
const exe = b.addExecutable("no_pagezero", null);
|
||||
exe.setTarget(target);
|
||||
exe.setBuildMode(mode);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "no_pagezero",
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
exe.addCSourceFile("main.c", &.{});
|
||||
exe.linkLibC();
|
||||
exe.pagezero_size = 0;
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
const LibExeObjectStep = std.build.LibExeObjStep;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target: std.zig.CrossTarget = .{ .os_tag = .macos };
|
||||
|
||||
const test_step = b.step("test", "Test");
|
||||
@@ -11,7 +9,7 @@ pub fn build(b: *Builder) void {
|
||||
|
||||
{
|
||||
// -search_dylibs_first
|
||||
const exe = createScenario(b, mode, target);
|
||||
const exe = createScenario(b, optimize, target);
|
||||
exe.search_strategy = .dylibs_first;
|
||||
|
||||
const check = exe.checkObject(.macho);
|
||||
@@ -26,40 +24,51 @@ pub fn build(b: *Builder) void {
|
||||
|
||||
{
|
||||
// -search_paths_first
|
||||
const exe = createScenario(b, mode, target);
|
||||
const exe = createScenario(b, optimize, target);
|
||||
exe.search_strategy = .paths_first;
|
||||
|
||||
const run = std.build.EmulatableRunStep.create(b, "run", exe);
|
||||
const run = std.Build.EmulatableRunStep.create(b, "run", exe);
|
||||
run.cwd = b.pathFromRoot(".");
|
||||
run.expectStdOutEqual("Hello world");
|
||||
test_step.dependOn(&run.step);
|
||||
}
|
||||
}
|
||||
|
||||
fn createScenario(b: *Builder, mode: std.builtin.Mode, target: std.zig.CrossTarget) *LibExeObjectStep {
|
||||
const static = b.addStaticLibrary("a", null);
|
||||
static.setTarget(target);
|
||||
static.setBuildMode(mode);
|
||||
fn createScenario(
|
||||
b: *std.Build,
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
target: std.zig.CrossTarget,
|
||||
) *std.Build.CompileStep {
|
||||
const static = b.addStaticLibrary(.{
|
||||
.name = "a",
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
static.addCSourceFile("a.c", &.{});
|
||||
static.linkLibC();
|
||||
static.override_dest_dir = std.build.InstallDir{
|
||||
static.override_dest_dir = std.Build.InstallDir{
|
||||
.custom = "static",
|
||||
};
|
||||
static.install();
|
||||
|
||||
const dylib = b.addSharedLibrary("a", null, b.version(1, 0, 0));
|
||||
dylib.setTarget(target);
|
||||
dylib.setBuildMode(mode);
|
||||
const dylib = b.addSharedLibrary(.{
|
||||
.name = "a",
|
||||
.version = .{ .major = 1, .minor = 0 },
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
dylib.addCSourceFile("a.c", &.{});
|
||||
dylib.linkLibC();
|
||||
dylib.override_dest_dir = std.build.InstallDir{
|
||||
dylib.override_dest_dir = std.Build.InstallDir{
|
||||
.custom = "dynamic",
|
||||
};
|
||||
dylib.install();
|
||||
|
||||
const exe = b.addExecutable("main", null);
|
||||
exe.setTarget(target);
|
||||
exe.setBuildMode(mode);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "main",
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
exe.addCSourceFile("main.c", &.{});
|
||||
exe.linkSystemLibraryName("a");
|
||||
exe.linkLibC();
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target: std.zig.CrossTarget = .{ .os_tag = .macos };
|
||||
|
||||
const test_step = b.step("test", "Test");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
const exe = b.addExecutable("main", null);
|
||||
exe.setTarget(target);
|
||||
exe.setBuildMode(mode);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "main",
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
exe.addCSourceFile("main.c", &.{});
|
||||
exe.linkLibC();
|
||||
exe.stack_size = 0x100000000;
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const Builder = std.build.Builder;
|
||||
const LibExeObjectStep = std.build.LibExeObjStep;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target: std.zig.CrossTarget = .{ .os_tag = .macos };
|
||||
|
||||
const test_step = b.step("test", "Test");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
const exe = b.addExecutable("main", "main.zig");
|
||||
exe.setBuildMode(mode);
|
||||
exe.setTarget(target);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "main",
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
exe.linkLibC();
|
||||
|
||||
const check_exe = exe.checkObject(.macho);
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target: std.zig.CrossTarget = .{ .os_tag = .macos };
|
||||
|
||||
const lib = b.addSharedLibrary("a", null, b.version(1, 0, 0));
|
||||
lib.setBuildMode(mode);
|
||||
lib.setTarget(target);
|
||||
const lib = b.addSharedLibrary(.{
|
||||
.name = "a",
|
||||
.version = .{ .major = 1, .minor = 0 },
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
lib.addCSourceFile("a.c", &.{});
|
||||
lib.linkLibC();
|
||||
|
||||
const test_exe = b.addTest("main.zig");
|
||||
test_exe.setBuildMode(mode);
|
||||
test_exe.setTarget(target);
|
||||
const test_exe = b.addTest(.{
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
test_exe.linkLibrary(lib);
|
||||
test_exe.linkLibC();
|
||||
|
||||
|
||||
@@ -1,26 +1,24 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const Builder = std.build.Builder;
|
||||
const LibExeObjectStep = std.build.LibExeObjStep;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target: std.zig.CrossTarget = .{ .os_tag = .macos };
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
|
||||
testUnwindInfo(b, test_step, mode, target, false);
|
||||
testUnwindInfo(b, test_step, mode, target, true);
|
||||
testUnwindInfo(b, test_step, optimize, target, false);
|
||||
testUnwindInfo(b, test_step, optimize, target, true);
|
||||
}
|
||||
|
||||
fn testUnwindInfo(
|
||||
b: *Builder,
|
||||
test_step: *std.build.Step,
|
||||
mode: std.builtin.Mode,
|
||||
b: *std.Build,
|
||||
test_step: *std.Build.Step,
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
target: std.zig.CrossTarget,
|
||||
dead_strip: bool,
|
||||
) void {
|
||||
const exe = createScenario(b, mode, target);
|
||||
const exe = createScenario(b, optimize, target);
|
||||
exe.link_gc_sections = dead_strip;
|
||||
|
||||
const check = exe.checkObject(.macho);
|
||||
@@ -52,8 +50,16 @@ fn testUnwindInfo(
|
||||
test_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
|
||||
fn createScenario(b: *Builder, mode: std.builtin.Mode, target: std.zig.CrossTarget) *LibExeObjectStep {
|
||||
const exe = b.addExecutable("test", null);
|
||||
fn createScenario(
|
||||
b: *std.Build,
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
target: std.zig.CrossTarget,
|
||||
) *std.Build.CompileStep {
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "test",
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
b.default_step.dependOn(&exe.step);
|
||||
exe.addIncludePath(".");
|
||||
exe.addCSourceFiles(&[_][]const u8{
|
||||
@@ -61,8 +67,6 @@ fn createScenario(b: *Builder, mode: std.builtin.Mode, target: std.zig.CrossTarg
|
||||
"simple_string.cpp",
|
||||
"simple_string_owner.cpp",
|
||||
}, &[0][]const u8{});
|
||||
exe.setBuildMode(mode);
|
||||
exe.setTarget(target);
|
||||
exe.linkLibCpp();
|
||||
return exe;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
const LibExeObjectStep = std.build.LibExeObjStep;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
pub fn build(b: *std.Build) void {
|
||||
const test_step = b.step("test", "Test");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
@@ -27,23 +25,23 @@ pub fn build(b: *Builder) void {
|
||||
}
|
||||
|
||||
fn testUuid(
|
||||
b: *Builder,
|
||||
test_step: *std.build.Step,
|
||||
mode: std.builtin.Mode,
|
||||
b: *std.Build,
|
||||
test_step: *std.Build.Step,
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
target: std.zig.CrossTarget,
|
||||
comptime exp: []const u8,
|
||||
) void {
|
||||
// The calculated UUID value is independent of debug info and so it should
|
||||
// stay the same across builds.
|
||||
{
|
||||
const dylib = simpleDylib(b, mode, target);
|
||||
const dylib = simpleDylib(b, optimize, target);
|
||||
const check_dylib = dylib.checkObject(.macho);
|
||||
check_dylib.checkStart("cmd UUID");
|
||||
check_dylib.checkNext("uuid " ++ exp);
|
||||
test_step.dependOn(&check_dylib.step);
|
||||
}
|
||||
{
|
||||
const dylib = simpleDylib(b, mode, target);
|
||||
const dylib = simpleDylib(b, optimize, target);
|
||||
dylib.strip = true;
|
||||
const check_dylib = dylib.checkObject(.macho);
|
||||
check_dylib.checkStart("cmd UUID");
|
||||
@@ -52,10 +50,17 @@ fn testUuid(
|
||||
}
|
||||
}
|
||||
|
||||
fn simpleDylib(b: *Builder, mode: std.builtin.Mode, target: std.zig.CrossTarget) *LibExeObjectStep {
|
||||
const dylib = b.addSharedLibrary("test", null, b.version(1, 0, 0));
|
||||
dylib.setTarget(target);
|
||||
dylib.setBuildMode(mode);
|
||||
fn simpleDylib(
|
||||
b: *std.Build,
|
||||
optimize: std.builtin.OptimizeMode,
|
||||
target: std.zig.CrossTarget,
|
||||
) *std.Build.CompileStep {
|
||||
const dylib = b.addSharedLibrary(.{
|
||||
.name = "test",
|
||||
.version = .{ .major = 1, .minor = 0 },
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
dylib.addCSourceFile("test.c", &.{});
|
||||
dylib.linkLibC();
|
||||
return dylib;
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
const LibExeObjectStep = std.build.LibExeObjStep;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
const exe = b.addExecutable("test", null);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "test",
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe.addCSourceFile("main.c", &[0][]const u8{});
|
||||
exe.setBuildMode(mode);
|
||||
exe.linkLibC();
|
||||
exe.linkFrameworkWeak("Cocoa");
|
||||
|
||||
|
||||
@@ -1,25 +1,28 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
const LibExeObjectStep = std.build.LibExeObjStep;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target: std.zig.CrossTarget = .{ .os_tag = .macos };
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
const dylib = b.addSharedLibrary("a", null, b.version(1, 0, 0));
|
||||
dylib.setTarget(target);
|
||||
dylib.setBuildMode(mode);
|
||||
const dylib = b.addSharedLibrary(.{
|
||||
.name = "a",
|
||||
.version = .{ .major = 1, .minor = 0, .patch = 0 },
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
dylib.addCSourceFile("a.c", &.{});
|
||||
dylib.linkLibC();
|
||||
dylib.install();
|
||||
|
||||
const exe = b.addExecutable("test", null);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "test",
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe.addCSourceFile("main.c", &[0][]const u8{});
|
||||
exe.setTarget(target);
|
||||
exe.setBuildMode(mode);
|
||||
exe.linkLibC();
|
||||
exe.linkSystemLibraryWeak("a");
|
||||
exe.addLibraryPath(b.pathFromRoot("zig-out/lib"));
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target = b.standardTargetOptions(.{});
|
||||
|
||||
const lib_a = b.addStaticLibrary("a", null);
|
||||
const lib_a = b.addStaticLibrary(.{
|
||||
.name = "a",
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
lib_a.addCSourceFile("a.c", &[_][]const u8{});
|
||||
lib_a.setBuildMode(mode);
|
||||
lib_a.addIncludePath(".");
|
||||
lib_a.install();
|
||||
|
||||
const test_exe = b.addTest("main.zig");
|
||||
test_exe.setBuildMode(mode);
|
||||
const test_exe = b.addTest(.{
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
test_exe.linkSystemLibrary("a"); // force linking liba.a as -la
|
||||
test_exe.addSystemIncludePath(".");
|
||||
const search_path = std.fs.path.join(b.allocator, &[_][]const u8{ b.install_path, "lib" }) catch unreachable;
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const test_step = b.step("test", "Test");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
// The code in question will pull-in compiler-rt,
|
||||
// and therefore link with its archive file.
|
||||
const lib = b.addSharedLibrary("main", "main.zig", .unversioned);
|
||||
lib.setBuildMode(mode);
|
||||
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
|
||||
const lib = b.addSharedLibrary(.{
|
||||
.name = "main",
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = b.standardOptimizeOption(.{}),
|
||||
.target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
|
||||
});
|
||||
lib.use_llvm = false;
|
||||
lib.use_lld = false;
|
||||
lib.strip = false;
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.build.Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
// Library with explicitly set cpu features
|
||||
const lib = b.addSharedLibrary("lib", "main.zig", .unversioned);
|
||||
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
|
||||
lib.target.cpu_model = .{ .explicit = &std.Target.wasm.cpu.mvp };
|
||||
lib.target.cpu_features_add.addFeature(0); // index 0 == atomics (see std.Target.wasm.Features)
|
||||
lib.setBuildMode(mode);
|
||||
const lib = b.addSharedLibrary(.{
|
||||
.name = "lib",
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = b.standardOptimizeOption(.{}),
|
||||
.target = .{
|
||||
.cpu_arch = .wasm32,
|
||||
.cpu_model = .{ .explicit = &std.Target.wasm.cpu.mvp },
|
||||
.cpu_features_add = std.Target.wasm.featureSet(&.{.atomics}),
|
||||
.os_tag = .freestanding,
|
||||
},
|
||||
});
|
||||
lib.use_llvm = false;
|
||||
lib.use_lld = false;
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const test_step = b.step("test", "Test");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
const lib = b.addSharedLibrary("lib", "lib.zig", .unversioned);
|
||||
lib.setBuildMode(mode);
|
||||
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
|
||||
const lib = b.addSharedLibrary(.{
|
||||
.name = "lib",
|
||||
.root_source_file = .{ .path = "lib.zig" },
|
||||
.target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
|
||||
.optimize = b.standardOptimizeOption(.{}),
|
||||
});
|
||||
lib.use_llvm = false;
|
||||
lib.use_lld = false;
|
||||
lib.strip = false;
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
pub fn build(b: *std.Build) void {
|
||||
const test_step = b.step("test", "Test");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
const lib = b.addSharedLibrary("lib", "lib.zig", .unversioned);
|
||||
lib.setBuildMode(.ReleaseSafe); // to make the output deterministic in address positions
|
||||
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
|
||||
const lib = b.addSharedLibrary(.{
|
||||
.name = "lib",
|
||||
.root_source_file = .{ .path = "lib.zig" },
|
||||
.optimize = .ReleaseSafe, // to make the output deterministic in address positions
|
||||
.target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
|
||||
});
|
||||
lib.use_lld = false;
|
||||
lib.export_symbol_names = &.{ "foo", "bar" };
|
||||
lib.global_base = 0; // put data section at address 0 to make data symbols easier to parse
|
||||
|
||||
@@ -1,24 +1,33 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.build.Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const no_export = b.addSharedLibrary("no-export", "main.zig", .unversioned);
|
||||
no_export.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
|
||||
no_export.setBuildMode(mode);
|
||||
const no_export = b.addSharedLibrary(.{
|
||||
.name = "no-export",
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = optimize,
|
||||
.target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
|
||||
});
|
||||
no_export.use_llvm = false;
|
||||
no_export.use_lld = false;
|
||||
|
||||
const dynamic_export = b.addSharedLibrary("dynamic", "main.zig", .unversioned);
|
||||
dynamic_export.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
|
||||
dynamic_export.setBuildMode(mode);
|
||||
const dynamic_export = b.addSharedLibrary(.{
|
||||
.name = "dynamic",
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = optimize,
|
||||
.target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
|
||||
});
|
||||
dynamic_export.rdynamic = true;
|
||||
dynamic_export.use_llvm = false;
|
||||
dynamic_export.use_lld = false;
|
||||
|
||||
const force_export = b.addSharedLibrary("force", "main.zig", .unversioned);
|
||||
force_export.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
|
||||
force_export.setBuildMode(mode);
|
||||
const force_export = b.addSharedLibrary(.{
|
||||
.name = "force",
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = optimize,
|
||||
.target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
|
||||
});
|
||||
force_export.export_symbol_names = &.{"foo"};
|
||||
force_export.use_llvm = false;
|
||||
force_export.use_lld = false;
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const test_step = b.step("test", "Test");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
const lib = b.addSharedLibrary("lib", "lib.zig", .unversioned);
|
||||
lib.setBuildMode(mode);
|
||||
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
|
||||
const lib = b.addSharedLibrary(.{
|
||||
.name = "lib",
|
||||
.root_source_file = .{ .path = "lib.zig" },
|
||||
.target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
|
||||
.optimize = b.standardOptimizeOption(.{}),
|
||||
});
|
||||
lib.import_symbols = true; // import `a` and `b`
|
||||
lib.rdynamic = true; // export `foo`
|
||||
lib.install();
|
||||
|
||||
Vendored
+7
-5
@@ -1,10 +1,12 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.build.Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
const exe = b.addExecutable("extern", "main.zig");
|
||||
exe.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .wasi });
|
||||
exe.setBuildMode(mode);
|
||||
pub fn build(b: *std.Build) void {
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "extern",
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = b.standardOptimizeOption(.{}),
|
||||
.target = .{ .cpu_arch = .wasm32, .os_tag = .wasi },
|
||||
});
|
||||
exe.addCSourceFile("foo.c", &.{});
|
||||
exe.use_llvm = false;
|
||||
exe.use_lld = false;
|
||||
|
||||
@@ -1,29 +1,37 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const test_step = b.step("test", "Test");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
const import_table = b.addSharedLibrary("lib", "lib.zig", .unversioned);
|
||||
import_table.setBuildMode(mode);
|
||||
import_table.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
|
||||
const import_table = b.addSharedLibrary(.{
|
||||
.name = "lib",
|
||||
.root_source_file = .{ .path = "lib.zig" },
|
||||
.target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
|
||||
.optimize = optimize,
|
||||
});
|
||||
import_table.use_llvm = false;
|
||||
import_table.use_lld = false;
|
||||
import_table.import_table = true;
|
||||
|
||||
const export_table = b.addSharedLibrary("lib", "lib.zig", .unversioned);
|
||||
export_table.setBuildMode(mode);
|
||||
export_table.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
|
||||
const export_table = b.addSharedLibrary(.{
|
||||
.name = "lib",
|
||||
.root_source_file = .{ .path = "lib.zig" },
|
||||
.target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
|
||||
.optimize = optimize,
|
||||
});
|
||||
export_table.use_llvm = false;
|
||||
export_table.use_lld = false;
|
||||
export_table.export_table = true;
|
||||
|
||||
const regular_table = b.addSharedLibrary("lib", "lib.zig", .unversioned);
|
||||
regular_table.setBuildMode(mode);
|
||||
regular_table.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
|
||||
const regular_table = b.addSharedLibrary(.{
|
||||
.name = "lib",
|
||||
.root_source_file = .{ .path = "lib.zig" },
|
||||
.target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
|
||||
.optimize = optimize,
|
||||
});
|
||||
regular_table.use_llvm = false;
|
||||
regular_table.use_lld = false;
|
||||
|
||||
|
||||
@@ -1,21 +1,32 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.build.Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
// Wasm Object file which we will use to infer the features from
|
||||
const c_obj = b.addObject("c_obj", null);
|
||||
c_obj.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
|
||||
c_obj.target.cpu_model = .{ .explicit = &std.Target.wasm.cpu.bleeding_edge };
|
||||
const c_obj = b.addObject(.{
|
||||
.name = "c_obj",
|
||||
.optimize = optimize,
|
||||
.target = .{
|
||||
.cpu_arch = .wasm32,
|
||||
.cpu_model = .{ .explicit = &std.Target.wasm.cpu.bleeding_edge },
|
||||
.os_tag = .freestanding,
|
||||
},
|
||||
});
|
||||
c_obj.addCSourceFile("foo.c", &.{});
|
||||
c_obj.setBuildMode(mode);
|
||||
|
||||
// Wasm library that doesn't have any features specified. This will
|
||||
// infer its featureset from other linked object files.
|
||||
const lib = b.addSharedLibrary("lib", "main.zig", .unversioned);
|
||||
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
|
||||
lib.target.cpu_model = .{ .explicit = &std.Target.wasm.cpu.mvp };
|
||||
lib.setBuildMode(mode);
|
||||
const lib = b.addSharedLibrary(.{
|
||||
.name = "lib",
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = optimize,
|
||||
.target = .{
|
||||
.cpu_arch = .wasm32,
|
||||
.cpu_model = .{ .explicit = &std.Target.wasm.cpu.mvp },
|
||||
.os_tag = .freestanding,
|
||||
},
|
||||
});
|
||||
lib.use_llvm = false;
|
||||
lib.use_lld = false;
|
||||
lib.addObject(c_obj);
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const Builder = std.build.Builder;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const test_step = b.step("test", "Test");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
const lib = b.addSharedLibrary("lib", "lib.zig", .unversioned);
|
||||
lib.setBuildMode(mode);
|
||||
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
|
||||
const lib = b.addSharedLibrary(.{
|
||||
.name = "lib",
|
||||
.root_source_file = .{ .path = "lib.zig" },
|
||||
.target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
|
||||
.optimize = b.standardOptimizeOption(.{}),
|
||||
});
|
||||
lib.use_llvm = false;
|
||||
lib.use_lld = false;
|
||||
lib.strip = false;
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const test_step = b.step("test", "Test");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
const lib = b.addSharedLibrary("lib", "lib.zig", .unversioned);
|
||||
lib.setBuildMode(mode);
|
||||
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
|
||||
const lib = b.addSharedLibrary(.{
|
||||
.name = "lib",
|
||||
.root_source_file = .{ .path = "lib.zig" },
|
||||
.target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
|
||||
.optimize = b.standardOptimizeOption(.{}),
|
||||
});
|
||||
lib.use_llvm = false;
|
||||
lib.use_lld = false;
|
||||
lib.strip = false;
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const test_step = b.step("test", "Test");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
const lib = b.addSharedLibrary("lib", "lib.zig", .unversioned);
|
||||
lib.setBuildMode(mode);
|
||||
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
|
||||
const lib = b.addSharedLibrary(.{
|
||||
.name = "lib",
|
||||
.root_source_file = .{ .path = "lib.zig" },
|
||||
.target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
|
||||
.optimize = b.standardOptimizeOption(.{}),
|
||||
});
|
||||
lib.use_llvm = false;
|
||||
lib.use_lld = false;
|
||||
lib.strip = false;
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const test_step = b.step("test", "Test");
|
||||
test_step.dependOn(b.getInstallStep());
|
||||
|
||||
const lib = b.addSharedLibrary("lib", "lib.zig", .unversioned);
|
||||
lib.setBuildMode(mode);
|
||||
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding });
|
||||
const lib = b.addSharedLibrary(.{
|
||||
.name = "lib",
|
||||
.root_source_file = .{ .path = "lib.zig" },
|
||||
.target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
|
||||
.optimize = b.standardOptimizeOption(.{}),
|
||||
});
|
||||
lib.use_llvm = false;
|
||||
lib.use_lld = false;
|
||||
lib.strip = false;
|
||||
|
||||
+25
-11
@@ -1,19 +1,18 @@
|
||||
// This is the implementation of the test harness.
|
||||
// For the actual test cases, see test/compare_output.zig.
|
||||
const std = @import("std");
|
||||
const build = std.build;
|
||||
const ArrayList = std.ArrayList;
|
||||
const fmt = std.fmt;
|
||||
const mem = std.mem;
|
||||
const fs = std.fs;
|
||||
const Mode = std.builtin.Mode;
|
||||
const OptimizeMode = std.builtin.OptimizeMode;
|
||||
|
||||
pub const CompareOutputContext = struct {
|
||||
b: *build.Builder,
|
||||
step: *build.Step,
|
||||
b: *std.Build,
|
||||
step: *std.Build.Step,
|
||||
test_index: usize,
|
||||
test_filter: ?[]const u8,
|
||||
modes: []const Mode,
|
||||
optimize_modes: []const OptimizeMode,
|
||||
|
||||
const Special = enum {
|
||||
None,
|
||||
@@ -102,7 +101,11 @@ pub const CompareOutputContext = struct {
|
||||
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
|
||||
}
|
||||
|
||||
const exe = b.addExecutable("test", null);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "test",
|
||||
.target = .{},
|
||||
.optimize = .Debug,
|
||||
});
|
||||
exe.addAssemblyFileSource(write_src.getFileSource(case.sources.items[0].filename).?);
|
||||
|
||||
const run = exe.run();
|
||||
@@ -113,19 +116,23 @@ pub const CompareOutputContext = struct {
|
||||
self.step.dependOn(&run.step);
|
||||
},
|
||||
Special.None => {
|
||||
for (self.modes) |mode| {
|
||||
for (self.optimize_modes) |optimize| {
|
||||
const annotated_case_name = fmt.allocPrint(self.b.allocator, "{s} {s} ({s})", .{
|
||||
"compare-output",
|
||||
case.name,
|
||||
@tagName(mode),
|
||||
@tagName(optimize),
|
||||
}) catch unreachable;
|
||||
if (self.test_filter) |filter| {
|
||||
if (mem.indexOf(u8, annotated_case_name, filter) == null) continue;
|
||||
}
|
||||
|
||||
const basename = case.sources.items[0].filename;
|
||||
const exe = b.addExecutableSource("test", write_src.getFileSource(basename).?);
|
||||
exe.setBuildMode(mode);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "test",
|
||||
.root_source_file = write_src.getFileSource(basename).?,
|
||||
.optimize = optimize,
|
||||
.target = .{},
|
||||
});
|
||||
if (case.link_libc) {
|
||||
exe.linkSystemLibrary("c");
|
||||
}
|
||||
@@ -139,13 +146,20 @@ pub const CompareOutputContext = struct {
|
||||
}
|
||||
},
|
||||
Special.RuntimeSafety => {
|
||||
// TODO iterate over self.optimize_modes and test this in both
|
||||
// debug and release safe mode
|
||||
const annotated_case_name = fmt.allocPrint(self.b.allocator, "safety {s}", .{case.name}) catch unreachable;
|
||||
if (self.test_filter) |filter| {
|
||||
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
|
||||
}
|
||||
|
||||
const basename = case.sources.items[0].filename;
|
||||
const exe = b.addExecutableSource("test", write_src.getFileSource(basename).?);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "test",
|
||||
.root_source_file = write_src.getFileSource(basename).?,
|
||||
.target = .{},
|
||||
.optimize = .Debug,
|
||||
});
|
||||
if (case.link_libc) {
|
||||
exe.linkSystemLibrary("c");
|
||||
}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
// This is the implementation of the test harness for running translated
|
||||
// C code. For the actual test cases, see test/run_translated_c.zig.
|
||||
const std = @import("std");
|
||||
const build = std.build;
|
||||
const ArrayList = std.ArrayList;
|
||||
const fmt = std.fmt;
|
||||
const mem = std.mem;
|
||||
const fs = std.fs;
|
||||
|
||||
pub const RunTranslatedCContext = struct {
|
||||
b: *build.Builder,
|
||||
step: *build.Step,
|
||||
b: *std.Build,
|
||||
step: *std.Build.Step,
|
||||
test_index: usize,
|
||||
test_filter: ?[]const u8,
|
||||
target: std.zig.CrossTarget,
|
||||
@@ -85,11 +84,14 @@ pub const RunTranslatedCContext = struct {
|
||||
for (case.sources.items) |src_file| {
|
||||
write_src.add(src_file.filename, src_file.source);
|
||||
}
|
||||
const translate_c = b.addTranslateC(write_src.getFileSource(case.sources.items[0].filename).?);
|
||||
const translate_c = b.addTranslateC(.{
|
||||
.source_file = write_src.getFileSource(case.sources.items[0].filename).?,
|
||||
.target = .{},
|
||||
.optimize = .Debug,
|
||||
});
|
||||
|
||||
translate_c.step.name = b.fmt("{s} translate-c", .{annotated_case_name});
|
||||
const exe = translate_c.addExecutable();
|
||||
exe.setTarget(self.target);
|
||||
const exe = translate_c.addExecutable(.{});
|
||||
exe.step.name = b.fmt("{s} build-exe", .{annotated_case_name});
|
||||
exe.linkLibC();
|
||||
const run = exe.run();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// This is the implementation of the test harness.
|
||||
// For the actual test cases, see test/translate_c.zig.
|
||||
const std = @import("std");
|
||||
const build = std.build;
|
||||
const ArrayList = std.ArrayList;
|
||||
const fmt = std.fmt;
|
||||
const mem = std.mem;
|
||||
@@ -9,8 +8,8 @@ const fs = std.fs;
|
||||
const CrossTarget = std.zig.CrossTarget;
|
||||
|
||||
pub const TranslateCContext = struct {
|
||||
b: *build.Builder,
|
||||
step: *build.Step,
|
||||
b: *std.Build,
|
||||
step: *std.Build.Step,
|
||||
test_index: usize,
|
||||
test_filter: ?[]const u8,
|
||||
|
||||
@@ -108,10 +107,13 @@ pub const TranslateCContext = struct {
|
||||
write_src.add(src_file.filename, src_file.source);
|
||||
}
|
||||
|
||||
const translate_c = b.addTranslateC(write_src.getFileSource(case.sources.items[0].filename).?);
|
||||
const translate_c = b.addTranslateC(.{
|
||||
.source_file = write_src.getFileSource(case.sources.items[0].filename).?,
|
||||
.target = case.target,
|
||||
.optimize = .Debug,
|
||||
});
|
||||
|
||||
translate_c.step.name = annotated_case_name;
|
||||
translate_c.setTarget(case.target);
|
||||
|
||||
const check_file = translate_c.addCheckFile(case.expected_lines.items);
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const main = b.addTest("main.zig");
|
||||
main.setBuildMode(b.standardReleaseOptions());
|
||||
pub fn build(b: *std.Build) void {
|
||||
const main = b.addTest(.{
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = b.standardOptimizeOption(.{}),
|
||||
});
|
||||
|
||||
const test_step = b.step("test", "Test it");
|
||||
test_step.dependOn(&main.step);
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const Builder = std.build.Builder;
|
||||
const CrossTarget = std.zig.CrossTarget;
|
||||
|
||||
// TODO integrate this with the std.build executor API
|
||||
// TODO integrate this with the std.Build executor API
|
||||
fn isRunnableTarget(t: CrossTarget) bool {
|
||||
if (t.isNative()) return true;
|
||||
|
||||
@@ -11,24 +10,28 @@ fn isRunnableTarget(t: CrossTarget) bool {
|
||||
t.getCpuArch() == builtin.cpu.arch);
|
||||
}
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target = b.standardTargetOptions(.{});
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
|
||||
const exe_c = b.addExecutable("test_c", null);
|
||||
const exe_c = b.addExecutable(.{
|
||||
.name = "test_c",
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
b.default_step.dependOn(&exe_c.step);
|
||||
exe_c.addCSourceFile("test.c", &[0][]const u8{});
|
||||
exe_c.setBuildMode(mode);
|
||||
exe_c.setTarget(target);
|
||||
exe_c.linkLibC();
|
||||
|
||||
const exe_cpp = b.addExecutable("test_cpp", null);
|
||||
const exe_cpp = b.addExecutable(.{
|
||||
.name = "test_cpp",
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
b.default_step.dependOn(&exe_cpp.step);
|
||||
exe_cpp.addCSourceFile("test.cpp", &[0][]const u8{});
|
||||
exe_cpp.setBuildMode(mode);
|
||||
exe_cpp.setTarget(target);
|
||||
exe_cpp.linkLibCpp();
|
||||
|
||||
switch (target.getOsTag()) {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const main = b.addTest("main.zig");
|
||||
main.setBuildMode(b.standardReleaseOptions());
|
||||
pub fn build(b: *std.Build) void {
|
||||
const main = b.addTest(.{
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = b.standardOptimizeOption(.{}),
|
||||
});
|
||||
main.emit_asm = .{ .emit_to = b.pathFromRoot("main.s") };
|
||||
main.emit_bin = .{ .emit_to = b.pathFromRoot("main") };
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const main = b.addExecutable("main", "main.zig");
|
||||
main.setBuildMode(b.standardReleaseOptions());
|
||||
pub fn build(b: *std.Build) void {
|
||||
const main = b.addExecutable(.{
|
||||
.name = "main",
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = b.standardOptimizeOption(.{}),
|
||||
});
|
||||
|
||||
const run = main.run();
|
||||
run.clearEnvironment();
|
||||
|
||||
@@ -1,16 +1,26 @@
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const obj1 = b.addStaticLibrary("obj1", "obj1.zig");
|
||||
obj1.setBuildMode(mode);
|
||||
const obj1 = b.addStaticLibrary(.{
|
||||
.name = "obj1",
|
||||
.root_source_file = .{ .path = "obj1.zig" },
|
||||
.optimize = optimize,
|
||||
.target = .{},
|
||||
});
|
||||
|
||||
const obj2 = b.addStaticLibrary("obj2", "obj2.zig");
|
||||
obj2.setBuildMode(mode);
|
||||
const obj2 = b.addStaticLibrary(.{
|
||||
.name = "obj2",
|
||||
.root_source_file = .{ .path = "obj2.zig" },
|
||||
.optimize = optimize,
|
||||
.target = .{},
|
||||
});
|
||||
|
||||
const main = b.addTest("main.zig");
|
||||
main.setBuildMode(mode);
|
||||
const main = b.addTest(.{
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = optimize,
|
||||
});
|
||||
main.linkLibrary(obj1);
|
||||
main.linkLibrary(obj2);
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
const CheckFileStep = std.build.CheckFileStep;
|
||||
const CheckFileStep = std.Build.CheckFileStep;
|
||||
|
||||
pub fn build(b: *std.build.Builder) void {
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = .{
|
||||
.cpu_arch = .thumb,
|
||||
.cpu_model = .{ .explicit = &std.Target.arm.cpu.cortex_m4 },
|
||||
@@ -10,11 +10,14 @@ pub fn build(b: *std.build.Builder) void {
|
||||
.abi = .gnueabihf,
|
||||
};
|
||||
|
||||
const mode = b.standardReleaseOptions();
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const elf = b.addExecutable("zig-nrf52-blink.elf", "main.zig");
|
||||
elf.setTarget(target);
|
||||
elf.setBuildMode(mode);
|
||||
const elf = b.addExecutable(.{
|
||||
.name = "zig-nrf52-blink.elf",
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
b.default_step.dependOn(test_step);
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const Builder = std.build.Builder;
|
||||
const CrossTarget = std.zig.CrossTarget;
|
||||
|
||||
// TODO integrate this with the std.build executor API
|
||||
// TODO integrate this with the std.Build executor API
|
||||
fn isRunnableTarget(t: CrossTarget) bool {
|
||||
if (t.isNative()) return true;
|
||||
|
||||
@@ -11,12 +10,16 @@ fn isRunnableTarget(t: CrossTarget) bool {
|
||||
t.getCpuArch() == builtin.cpu.arch);
|
||||
}
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target = b.standardTargetOptions(.{});
|
||||
|
||||
const exe = b.addExecutable("zigtest", "main.zig");
|
||||
exe.setBuildMode(mode);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "zigtest",
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe.install();
|
||||
|
||||
const c_sources = [_][]const u8{
|
||||
@@ -39,7 +42,6 @@ pub fn build(b: *Builder) void {
|
||||
exe.defineCMacro("QUX", "\"Q\" \"UX\"");
|
||||
exe.defineCMacro("QUUX", "\"QU\\\"UX\"");
|
||||
|
||||
exe.setTarget(target);
|
||||
b.default_step.dependOn(&exe.step);
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target = b.standardTargetOptions(.{});
|
||||
|
||||
const obj = b.addObject("main", "main.zig");
|
||||
obj.setBuildMode(mode);
|
||||
obj.setTarget(target);
|
||||
const obj = b.addObject(.{
|
||||
.name = "main",
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
obj.emit_llvm_ir = .{ .emit_to = b.pathFromRoot("main.ll") };
|
||||
obj.emit_llvm_bc = .{ .emit_to = b.pathFromRoot("main.bc") };
|
||||
obj.emit_bin = .no_emit;
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const Builder = std.build.Builder;
|
||||
const CrossTarget = std.zig.CrossTarget;
|
||||
|
||||
// TODO integrate this with the std.build executor API
|
||||
// TODO integrate this with the std.Build executor API
|
||||
fn isRunnableTarget(t: CrossTarget) bool {
|
||||
if (t.isNative()) return true;
|
||||
|
||||
@@ -11,12 +10,16 @@ fn isRunnableTarget(t: CrossTarget) bool {
|
||||
t.getCpuArch() == builtin.cpu.arch);
|
||||
}
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target = b.standardTargetOptions(.{});
|
||||
|
||||
const exe = b.addExecutable("main", "main.zig");
|
||||
exe.setBuildMode(mode);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "main",
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
exe.install();
|
||||
|
||||
const c_sources = [_][]const u8{
|
||||
@@ -26,7 +29,6 @@ pub fn build(b: *Builder) void {
|
||||
exe.addCSourceFiles(&c_sources, &.{});
|
||||
exe.linkLibC();
|
||||
|
||||
exe.setTarget(target);
|
||||
b.default_step.dependOn(&exe.step);
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const Builder = std.build.Builder;
|
||||
const CrossTarget = std.zig.CrossTarget;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target = b.standardTargetOptions(.{});
|
||||
|
||||
const obj = b.addObject("main", "main.zig");
|
||||
obj.setBuildMode(mode);
|
||||
|
||||
obj.setTarget(target);
|
||||
const obj = b.addObject(.{
|
||||
.name = "main",
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
b.default_step.dependOn(&obj.step);
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const obj = b.addObject("test", "test.zig");
|
||||
pub fn build(b: *std.Build) void {
|
||||
const obj = b.addObject(.{
|
||||
.name = "test",
|
||||
.root_source_file = .{ .path = "test.zig" },
|
||||
.target = b.standardTargetOptions(.{}),
|
||||
.optimize = b.standardOptimizeOption(.{}),
|
||||
});
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
test_step.dependOn(&obj.step);
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = .{
|
||||
.cpu_arch = .x86_64,
|
||||
.os_tag = .windows,
|
||||
.abi = .msvc,
|
||||
};
|
||||
const mode = b.standardReleaseOptions();
|
||||
const obj = b.addObject("issue_5825", "main.zig");
|
||||
obj.setTarget(target);
|
||||
obj.setBuildMode(mode);
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const obj = b.addObject(.{
|
||||
.name = "issue_5825",
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
|
||||
const exe = b.addExecutable("issue_5825", null);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "issue_5825",
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
exe.subsystem = .Console;
|
||||
exe.linkSystemLibrary("kernel32");
|
||||
exe.linkSystemLibrary("ntdll");
|
||||
exe.setTarget(target);
|
||||
exe.setBuildMode(mode);
|
||||
exe.addObject(obj);
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const exe = b.addExecutable("issue_7030", "main.zig");
|
||||
exe.setTarget(.{
|
||||
.cpu_arch = .wasm32,
|
||||
.os_tag = .freestanding,
|
||||
pub fn build(b: *std.Build) void {
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "issue_7030",
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.target = .{
|
||||
.cpu_arch = .wasm32,
|
||||
.os_tag = .freestanding,
|
||||
},
|
||||
});
|
||||
exe.install();
|
||||
b.default_step.dependOn(&exe.step);
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const test_artifact = b.addTest("main.zig");
|
||||
pub fn build(b: *std.Build) void {
|
||||
const test_artifact = b.addTest(.{
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
});
|
||||
test_artifact.addIncludePath("a_directory");
|
||||
|
||||
b.default_step.dependOn(&test_artifact.step);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.build.Builder) !void {
|
||||
pub fn build(b: *std.Build) !void {
|
||||
const target = std.zig.CrossTarget{
|
||||
.os_tag = .freestanding,
|
||||
.cpu_arch = .arm,
|
||||
@@ -8,12 +8,15 @@ pub fn build(b: *std.build.Builder) !void {
|
||||
.explicit = &std.Target.arm.cpu.arm1176jz_s,
|
||||
},
|
||||
};
|
||||
const mode = b.standardReleaseOptions();
|
||||
const kernel = b.addExecutable("kernel", "./main.zig");
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const kernel = b.addExecutable(.{
|
||||
.name = "kernel",
|
||||
.root_source_file = .{ .path = "./main.zig" },
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
kernel.addObjectFile("./boot.S");
|
||||
kernel.setLinkerScriptPath(.{ .path = "./linker.ld" });
|
||||
kernel.setBuildMode(mode);
|
||||
kernel.setTarget(target);
|
||||
kernel.install();
|
||||
|
||||
const test_step = b.step("test", "Test it");
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.build.Builder) !void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
const zip_add = b.addTest("main.zig");
|
||||
zip_add.setBuildMode(mode);
|
||||
pub fn build(b: *std.Build) !void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const zip_add = b.addTest(.{
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = optimize,
|
||||
});
|
||||
zip_add.addCSourceFile("vendor/kuba-zip/zip.c", &[_][]const u8{
|
||||
"-std=c99",
|
||||
"-fno-sanitize=undefined",
|
||||
|
||||
@@ -1,13 +1,23 @@
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const opts = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const lib = b.addSharedLibrary("add", "add.zig", b.version(1, 0, 0));
|
||||
lib.setBuildMode(opts);
|
||||
const lib = b.addSharedLibrary(.{
|
||||
.name = "add",
|
||||
.root_source_file = .{ .path = "add.zig" },
|
||||
.version = .{ .major = 1, .minor = 0 },
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
|
||||
const main = b.addExecutable("main", "main.zig");
|
||||
main.setBuildMode(opts);
|
||||
const main = b.addExecutable(.{
|
||||
.name = "main",
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
|
||||
const run = main.run();
|
||||
run.addArtifactArg(lib);
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const test_exe = b.addTest("a/test.zig");
|
||||
pub fn build(b: *std.Build) void {
|
||||
const test_exe = b.addTest(.{
|
||||
.root_source_file = .{ .path = "a/test.zig" },
|
||||
});
|
||||
test_exe.setMainPkgPath(".");
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const Builder = std.build.Builder;
|
||||
const CrossTarget = std.zig.CrossTarget;
|
||||
|
||||
// TODO integrate this with the std.build executor API
|
||||
// TODO integrate this with the std.Build executor API
|
||||
fn isRunnableTarget(t: CrossTarget) bool {
|
||||
if (t.isNative()) return true;
|
||||
|
||||
@@ -11,15 +10,18 @@ fn isRunnableTarget(t: CrossTarget) bool {
|
||||
t.getCpuArch() == builtin.cpu.arch);
|
||||
}
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target = b.standardTargetOptions(.{});
|
||||
|
||||
const exe = b.addExecutable("test", "main.zig");
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "test",
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
exe.addCSourceFile("test.c", &[_][]const u8{"-std=c11"});
|
||||
exe.setBuildMode(mode);
|
||||
exe.linkLibC();
|
||||
exe.setTarget(target);
|
||||
b.default_step.dependOn(&exe.step);
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
|
||||
@@ -1,9 +1,19 @@
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const obj = b.addObject("base64", "base64.zig");
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const exe = b.addExecutable("test", null);
|
||||
const obj = b.addObject(.{
|
||||
.name = "base64",
|
||||
.root_source_file = .{ .path = "base64.zig" },
|
||||
.optimize = optimize,
|
||||
.target = .{},
|
||||
});
|
||||
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "test",
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe.addCSourceFile("test.c", &[_][]const u8{"-std=c99"});
|
||||
exe.addObject(obj);
|
||||
exe.linkSystemLibrary("c");
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.build.Builder) void {
|
||||
pub fn build(b: *std.Build) void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const mode = b.standardReleaseOptions();
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const main = b.addTest("src/main.zig");
|
||||
main.setTarget(target);
|
||||
main.setBuildMode(mode);
|
||||
const main = b.addTest(.{
|
||||
.root_source_file = .{ .path = "src/main.zig" },
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
const options = b.addOptions();
|
||||
main.addOptions("build_options", options);
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const main = b.addTest("main.zig");
|
||||
main.setBuildMode(b.standardReleaseOptions());
|
||||
pub fn build(b: *std.Build) void {
|
||||
const main = b.addTest(.{
|
||||
.root_source_file = .{ .path = "main.zig" },
|
||||
.optimize = b.standardOptimizeOption(.{}),
|
||||
});
|
||||
main.pie = true;
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const exe = b.addExecutable("test", "test.zig");
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "test",
|
||||
.root_source_file = .{ .path = "test.zig" },
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe.addPackagePath("my_pkg", "pkg.zig");
|
||||
|
||||
// This is duplicated to test that you are allowed to call
|
||||
// b.standardReleaseOptions() twice.
|
||||
exe.setBuildMode(b.standardReleaseOptions());
|
||||
exe.setBuildMode(b.standardReleaseOptions());
|
||||
|
||||
const run = exe.run();
|
||||
|
||||
const test_step = b.step("test", "Test it");
|
||||
|
||||
@@ -1,12 +1,21 @@
|
||||
const Builder = @import("std").build.Builder;
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
pub fn build(b: *std.Build) void {
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));
|
||||
lib.setTarget(target);
|
||||
const lib = b.addSharedLibrary(.{
|
||||
.name = "mathtest",
|
||||
.root_source_file = .{ .path = "mathtest.zig" },
|
||||
.version = .{ .major = 1, .minor = 0 },
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
const exe = b.addExecutable("test", null);
|
||||
exe.setTarget(target);
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "test",
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
exe.addCSourceFile("test.c", &[_][]const u8{"-std=c99"});
|
||||
exe.linkLibrary(lib);
|
||||
exe.linkSystemLibrary("c");
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user