diff --git a/build.zig b/build.zig index 98da9f31ee..6b6c384fc4 100644 --- a/build.zig +++ b/build.zig @@ -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: { @@ -477,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 = .{ @@ -514,10 +513,10 @@ fn addWasiUpdateStep(b: *Builder, version: [:0]const u8) !void { } fn addCompilerStep( - b: *Builder, + b: *std.Build, optimize: std.builtin.OptimizeMode, target: std.zig.CrossTarget, -) *std.build.LibExeObjStep { +) *std.Build.LibExeObjStep { const exe = b.addExecutable(.{ .name = "zig", .root_source_file = .{ .path = "src/main.zig" }, @@ -543,9 +542,9 @@ const exe_cflags = [_][]const u8{ }; fn addCmakeCfgOptionsToExe( - b: *Builder, + b: *std.Build, cfg: CMakeConfig, - exe: *std.build.LibExeObjStep, + exe: *std.Build.LibExeObjStep, use_zig_libcxx: bool, ) !void { if (exe.target.isDarwin()) { @@ -624,7 +623,7 @@ fn addCmakeCfgOptionsToExe( } } -fn addStaticLlvmOptionsToExe(exe: *std.build.LibExeObjStep) !void { +fn addStaticLlvmOptionsToExe(exe: *std.Build.LibExeObjStep) !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 @@ -661,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.LibExeObjStep, objname: []const u8, errtxt: ?[]const u8, need_cpp_includes: bool, @@ -696,7 +695,7 @@ fn addCxxKnownPath( } } -fn addCMakeLibraryList(exe: *std.build.LibExeObjStep, list: []const u8) void { +fn addCMakeLibraryList(exe: *std.Build.LibExeObjStep, list: []const u8) void { var it = mem.tokenize(u8, list, ";"); while (it.next()) |lib| { if (mem.startsWith(u8, lib, "-l")) { @@ -710,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.LibExeObjStep.Linkage, cmake_binary_dir: []const u8, cmake_prefix_path: []const u8, cmake_static_library_prefix: []const u8, @@ -727,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| { @@ -773,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, @@ -862,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, diff --git a/doc/langref.html.in b/doc/langref.html.in index c008149f41..1163ad0200 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -9528,9 +9528,9 @@ fn foo(comptime T: type, ptr: *T) T { To add standard build options to a build.zig file:

{#code_begin|syntax|build#} -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 exe = b.addExecutable(.{ .name = "example", @@ -10551,9 +10551,9 @@ const separator = if (builtin.os.tag == .windows) '\\' else '/';

This build.zig file is automatically generated by zig init-exe.

{#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 @@ -10588,9 +10588,9 @@ pub fn build(b: *Builder) void {

This build.zig file is automatically generated by zig init-lib.

{#code_begin|syntax|build_library#} -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 lib = b.addStaticLibrary(.{ .name = "example", @@ -10961,9 +10961,9 @@ 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 { +pub fn build(b: *std.Build) void { const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0)); const exe = b.addExecutable(.{ @@ -11025,9 +11025,9 @@ 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 { +pub fn build(b: *std.Build) void { const obj = b.addObject("base64", "base64.zig"); const exe = b.addExecutable(.{ diff --git a/lib/build_runner.zig b/lib/build_runner.zig index 4df2eb1d62..189b118787 100644 --- a/lib/build_runner.zig +++ b/lib/build_runner.zig @@ -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,7 +41,7 @@ pub fn main() !void { return error.InvalidArgs; }; - const builder = try Builder.create( + const builder = try std.Build.create( allocator, zig_exe, build_root, @@ -58,7 +57,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 +229,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 +329,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); } diff --git a/lib/init-exe/build.zig b/lib/init-exe/build.zig index 36e5feddec..b88515b403 100644 --- a/lib/init-exe/build.zig +++ b/lib/init-exe/build.zig @@ -3,7 +3,7 @@ const std = @import("std"); // 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.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 diff --git a/lib/init-lib/build.zig b/lib/init-lib/build.zig index 4a7b700dc2..5ebb55373f 100644 --- a/lib/init-lib/build.zig +++ b/lib/init-lib/build.zig @@ -3,7 +3,7 @@ const std = @import("std"); // 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.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 diff --git a/lib/std/Build.zig b/lib/std/Build.zig new file mode 100644 index 0000000000..a3c579c743 --- /dev/null +++ b/lib/std/Build.zig @@ -0,0 +1,1771 @@ +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(); + +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 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"); + +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, +) !*Build { + const env_map = try allocator.create(EnvMap); + env_map.* = try process.getEnvMap(allocator); + + const host = try NativeTargetInfo.detect(.{}); + + 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: ?LibExeObjStep.Linkage = null, +}; + +pub fn addExecutable(b: *Build, options: ExecutableOptions) *LibExeObjStep { + return LibExeObjStep.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) *LibExeObjStep { + return LibExeObjStep.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) *LibExeObjStep { + return LibExeObjStep.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) *LibExeObjStep { + return LibExeObjStep.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: LibExeObjStep.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) *LibExeObjStep { + return LibExeObjStep.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) *LibExeObjStep { + const obj_step = LibExeObjStep.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 `LibExeObjStep.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 unreachable; +} + +/// 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 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: *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 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: *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 unreachable; + 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 unreachable; + 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 unreachable; + 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 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, .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 unreachable; + }, + .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 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; +} + +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 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: *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); + 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; + }, + .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: *LibExeObjStep) void { + self.getInstallStep().dependOn(&self.addInstallArtifact(artifact).step); +} + +pub fn addInstallArtifact(self: *Build, artifact: *LibExeObjStep) *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: *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: *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: *LibExeObjStep, 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 unreachable; + 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 unreachable; + 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 unreachable; +} + +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 unreachable; +} + +/// Shorthand for `std.fs.path.join(Build.allocator, paths) catch unreachable` +pub fn pathJoin(self: *Build, paths: []const []const u8) []u8 { + return fs.path.join(self.allocator, paths) catch unreachable; +} + +pub fn fmt(self: *Build, comptime format: []const u8, args: anytype) []u8 { + return fmt_lib.allocPrint(self.allocator, format, args) catch unreachable; +} + +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 unreachable; +} + +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 unreachable; +} + +pub const Dependency = struct { + builder: *Build, + + 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: *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 unreachable; + sub_builder.runBuild(build_zig) catch unreachable; + + if (sub_builder.validateUserInputDidItFail()) { + std.debug.dumpCurrentStackTrace(@returnAddress()); + } + + const dep = b.allocator.create(Dependency) catch unreachable; + 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 builder = try Build.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, 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; +} + +/// deprecated: use `InstallDirStep.Options` +pub const InstallDirectoryOptions = InstallDirStep.Options; + +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(); + var builder = try Build.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 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; + _ = LibExeObjStep; + _ = LogStep; + _ = OptionsStep; + _ = RemoveDirStep; + _ = RunStep; + _ = TranslateCStep; + _ = WriteFileStep; +} diff --git a/lib/std/build/CheckFileStep.zig b/lib/std/Build/CheckFileStep.zig similarity index 88% rename from lib/std/build/CheckFileStep.zig rename to lib/std/Build/CheckFileStep.zig index 2c06ab9279..3b8cfe5263 100644 --- a/lib/std/build/CheckFileStep.zig +++ b/lib/std/Build/CheckFileStep.zig @@ -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,14 +8,14 @@ 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; diff --git a/lib/std/build/CheckObjectStep.zig b/lib/std/Build/CheckObjectStep.zig similarity index 98% rename from lib/std/build/CheckObjectStep.zig rename to lib/std/Build/CheckObjectStep.zig index 4ef350b418..7907be1787 100644 --- a/lib/std/build/CheckObjectStep.zig +++ b/lib/std/Build/CheckObjectStep.zig @@ -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,21 +9,20 @@ 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; self.* = .{ @@ -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.LibExeObjStep).?; 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), diff --git a/lib/std/build/ConfigHeaderStep.zig b/lib/std/Build/ConfigHeaderStep.zig similarity index 97% rename from lib/std/build/ConfigHeaderStep.zig rename to lib/std/Build/ConfigHeaderStep.zig index 400c06525e..b961227c9c 100644 --- a/lib/std/build/ConfigHeaderStep.zig +++ b/lib/std/Build/ConfigHeaderStep.zig @@ -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.* = .{ diff --git a/lib/std/build/EmulatableRunStep.zig b/lib/std/Build/EmulatableRunStep.zig similarity index 96% rename from lib/std/build/EmulatableRunStep.zig rename to lib/std/Build/EmulatableRunStep.zig index 52ce8edfac..b7b12d791f 100644 --- a/lib/std/build/EmulatableRunStep.zig +++ b/lib/std/Build/EmulatableRunStep.zig @@ -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 LibExeObjStep = std.Build.LibExeObjStep; +const RunStep = std.Build.RunStep; const fs = std.fs; const process = std.process; @@ -22,7 +20,7 @@ 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, @@ -47,7 +45,7 @@ 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: *LibExeObjStep) *EmulatableRunStep { std.debug.assert(artifact.kind == .exe or artifact.kind == .test_exe); const self = builder.allocator.create(EmulatableRunStep) catch unreachable; diff --git a/lib/std/build/FmtStep.zig b/lib/std/Build/FmtStep.zig similarity index 75% rename from lib/std/build/FmtStep.zig rename to lib/std/Build/FmtStep.zig index 62923623f2..44a93dee66 100644 --- a/lib/std/build/FmtStep.zig +++ b/lib/std/Build/FmtStep.zig @@ -1,19 +1,14 @@ 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 { +pub fn create(builder: *std.Build, paths: []const []const u8) *FmtStep { const self = builder.allocator.create(FmtStep) catch unreachable; const name = "zig fmt"; self.* = FmtStep{ diff --git a/lib/std/build/InstallArtifactStep.zig b/lib/std/Build/InstallArtifactStep.zig similarity index 88% rename from lib/std/build/InstallArtifactStep.zig rename to lib/std/Build/InstallArtifactStep.zig index 537b8c8fd9..929b30e935 100644 --- a/lib/std/build/InstallArtifactStep.zig +++ b/lib/std/Build/InstallArtifactStep.zig @@ -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 LibExeObjStep = std.Build.LibExeObjStep; +const InstallDir = std.Build.InstallDir; +const InstallArtifactStep = @This(); pub const base_id = .install_artifact; step: Step, -builder: *Builder, +builder: *std.Build, artifact: *LibExeObjStep, 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: *LibExeObjStep) *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 unreachable; + self.* = InstallArtifactStep{ .builder = builder, .step = Step.init(.install_artifact, builder.fmt("install {s}", .{artifact.step.name}), builder.allocator, make), .artifact = artifact, @@ -64,7 +61,7 @@ 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); diff --git a/lib/std/build/InstallDirStep.zig b/lib/std/Build/InstallDirStep.zig similarity index 92% rename from lib/std/build/InstallDirStep.zig rename to lib/std/Build/InstallDirStep.zig index 0a41e1aaef..41dbb3e35a 100644 --- a/lib/std/build/InstallDirStep.zig +++ b/lib/std/Build/InstallDirStep.zig @@ -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); diff --git a/lib/std/build/InstallFileStep.zig b/lib/std/Build/InstallFileStep.zig similarity index 82% rename from lib/std/build/InstallFileStep.zig rename to lib/std/Build/InstallFileStep.zig index 37203e64c5..8c8d8ad2d4 100644 --- a/lib/std/build/InstallFileStep.zig +++ b/lib/std/Build/InstallFileStep.zig @@ -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, diff --git a/lib/std/build/InstallRawStep.zig b/lib/std/Build/InstallRawStep.zig similarity index 84% rename from lib/std/build/InstallRawStep.zig rename to lib/std/Build/InstallRawStep.zig index e8266dff5a..08d646ff88 100644 --- a/lib/std/build/InstallRawStep.zig +++ b/lib/std/Build/InstallRawStep.zig @@ -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 LibExeObjStep = std.Build.LibExeObjStep; +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, +builder: *std.Build, artifact: *LibExeObjStep, 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,7 +38,12 @@ pub const CreateOptions = struct { pad_to: ?u64 = null, }; -pub fn create(builder: *Builder, artifact: *LibExeObjStep, dest_filename: []const u8, options: CreateOptions) *InstallRawStep { +pub fn create( + builder: *std.Build, + artifact: *LibExeObjStep, + dest_filename: []const u8, + options: CreateOptions, +) *InstallRawStep { const self = builder.allocator.create(InstallRawStep) catch unreachable; self.* = InstallRawStep{ .step = Step.init(.install_raw, builder.fmt("install raw binary {s}", .{artifact.step.name}), builder.allocator, make), @@ -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 { diff --git a/lib/std/build/LibExeObjStep.zig b/lib/std/Build/LibExeObjStep.zig similarity index 97% rename from lib/std/build/LibExeObjStep.zig rename to lib/std/Build/LibExeObjStep.zig index 6ee5205b50..af9d34440d 100644 --- a/lib/std/build/LibExeObjStep.zig +++ b/lib/std/Build/LibExeObjStep.zig @@ -9,32 +9,30 @@ 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 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 LibExeObjStep = @This(); pub const base_id = .lib_exe_obj; step: Step, -builder: *Builder, +builder: *std.Build, name: []const u8, target: CrossTarget, target_info: NativeTargetInfo, @@ -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), @@ -297,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, @@ -307,7 +305,7 @@ pub const EmitOption = union(enum) { } }; -pub fn create(builder: *Builder, options: Options) *LibExeObjStep { +pub fn create(builder: *std.Build, options: Options) *LibExeObjStep { 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) { @@ -343,9 +341,9 @@ pub fn create(builder: *Builder, options: Options) *LibExeObjStep { .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, @@ -461,7 +459,7 @@ pub fn installHeadersDirectory( pub fn installHeadersDirectoryOptions( a: *LibExeObjStep, - options: std.build.InstallDirStep.Options, + options: std.Build.InstallDirStep.Options, ) void { const install_dir = a.builder.addInstallDirectory(options); a.builder.getInstallStep().dependOn(&install_dir.step); @@ -600,7 +598,7 @@ pub fn linkLibCpp(self: *LibExeObjStep) void { /// 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); + const macro = std.Build.constructCMacro(self.builder.allocator, name, value); self.c_macros.append(macro) catch unreachable; } @@ -1460,7 +1458,7 @@ fn make(step: *Step) !void { if (!self.target.isNative()) { try zig_args.appendSlice(&.{ "-target", try self.target.zigTriple(builder.allocator), - "-mcpu", try build.serializeCpu(builder.allocator, self.target.getCpu()), + "-mcpu", try std.Build.serializeCpu(builder.allocator, self.target.getCpu()), }); if (self.target.dynamic_linker.get()) |dynamic_linker| { @@ -1902,7 +1900,7 @@ pub fn doAtomicSymLinks(allocator: Allocator, output_path: []const u8, filename_ }; } -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(); @@ -1918,7 +1916,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; } @@ -1948,7 +1946,7 @@ test "addPackage" { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); - var builder = try Builder.create( + var builder = try std.Build.create( arena.allocator(), "test", "test", diff --git a/lib/std/build/LogStep.zig b/lib/std/Build/LogStep.zig similarity index 72% rename from lib/std/build/LogStep.zig rename to lib/std/Build/LogStep.zig index fd937b00f9..6d51df8cbd 100644 --- a/lib/std/build/LogStep.zig +++ b/lib/std/Build/LogStep.zig @@ -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), diff --git a/lib/std/build/OptionsStep.zig b/lib/std/Build/OptionsStep.zig similarity index 97% rename from lib/std/build/OptionsStep.zig rename to lib/std/Build/OptionsStep.zig index fb06cc2179..3d26807411 100644 --- a/lib/std/build/OptionsStep.zig +++ b/lib/std/Build/OptionsStep.zig @@ -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 LibExeObjStep = std.Build.LibExeObjStep; +const FileSource = std.Build.FileSource; const OptionsStep = @This(); @@ -14,13 +12,13 @@ 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 { +pub fn create(builder: *std.Build) *OptionsStep { const self = builder.allocator.create(OptionsStep) catch unreachable; self.* = .{ .builder = builder, @@ -202,7 +200,7 @@ pub fn addOptionArtifact(self: *OptionsStep, name: []const u8, artifact: *LibExe 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() }; } @@ -281,7 +279,7 @@ test "OptionsStep" { var arena = std.heap.ArenaAllocator.init(std.testing.allocator); defer arena.deinit(); - var builder = try Builder.create( + var builder = try std.Build.create( arena.allocator(), "test", "test", diff --git a/lib/std/build/RemoveDirStep.zig b/lib/std/Build/RemoveDirStep.zig similarity index 79% rename from lib/std/build/RemoveDirStep.zig rename to lib/std/Build/RemoveDirStep.zig index 959414e54f..f3b71dcec1 100644 --- a/lib/std/build/RemoveDirStep.zig +++ b/lib/std/Build/RemoveDirStep.zig @@ -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), diff --git a/lib/std/build/RunStep.zig b/lib/std/Build/RunStep.zig similarity index 94% rename from lib/std/build/RunStep.zig rename to lib/std/Build/RunStep.zig index 5183a328cd..83e4f7f66c 100644 --- a/lib/std/build/RunStep.zig +++ b/lib/std/Build/RunStep.zig @@ -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 LibExeObjStep = std.Build.LibExeObjStep; +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), @@ -51,11 +49,11 @@ pub const StdIoAction = union(enum) { pub const Arg = union(enum) { artifact: *LibExeObjStep, - file_source: build.FileSource, + file_source: std.Build.FileSource, bytes: []u8, }; -pub fn create(builder: *Builder, name: []const u8) *RunStep { +pub fn create(builder: *std.Build, name: []const u8) *RunStep { const self = builder.allocator.create(RunStep) catch unreachable; self.* = RunStep{ .builder = builder, @@ -73,7 +71,7 @@ pub fn addArtifactArg(self: *RunStep, artifact: *LibExeObjStep) void { 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; @@ -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"; @@ -122,7 +120,7 @@ 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 { @@ -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, @@ -363,7 +361,7 @@ fn addPathForDynLibs(self: *RunStep, artifact: *LibExeObjStep) void { /// 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: *LibExeObjStep) void { for (artifact.link_objects.items) |link_object| { switch (link_object) { .other_step => |other| { diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig new file mode 100644 index 0000000000..86d6645c29 --- /dev/null +++ b/lib/std/Build/Step.zig @@ -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, + 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 => Build.TopLevelStep, + .lib_exe_obj => Build.LibExeObjStep, + .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 unreachable, + .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 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; +} + +const Step = @This(); +const std = @import("../std.zig"); +const Build = std.Build; +const Allocator = std.mem.Allocator; diff --git a/lib/std/build/TranslateCStep.zig b/lib/std/Build/TranslateCStep.zig similarity index 90% rename from lib/std/build/TranslateCStep.zig rename to lib/std/Build/TranslateCStep.zig index 9f45d606a1..5404747846 100644 --- a/lib/std/build/TranslateCStep.zig +++ b/lib/std/Build/TranslateCStep.zig @@ -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 LibExeObjStep = std.Build.LibExeObjStep; +const CheckFileStep = std.Build.CheckFileStep; const fs = std.fs; const mem = std.mem; const CrossTarget = std.zig.CrossTarget; @@ -13,23 +11,23 @@ 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, optimize: std.builtin.OptimizeMode, -output_file: build.GeneratedFile, +output_file: std.Build.GeneratedFile, pub const Options = struct { - source_file: build.FileSource, + source_file: std.Build.FileSource, target: CrossTarget, optimize: std.builtin.OptimizeMode, }; -pub fn create(builder: *Builder, options: Options) *TranslateCStep { +pub fn create(builder: *std.Build, options: Options) *TranslateCStep { const self = builder.allocator.create(TranslateCStep) catch unreachable; const source = options.source_file.dupe(builder); self.* = TranslateCStep{ @@ -42,7 +40,7 @@ pub fn create(builder: *Builder, options: Options) *TranslateCStep { .out_basename = undefined, .target = options.target, .optimize = options.optimize, - .output_file = build.GeneratedFile{ .step = &self.step }, + .output_file = std.Build.GeneratedFile{ .step = &self.step }, }; source.addStepDependencies(&self.step); return self; @@ -79,7 +77,7 @@ 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); + const macro = std.Build.constructCMacro(self.builder.allocator, name, value); self.c_macros.append(macro) catch unreachable; } diff --git a/lib/std/build/WriteFileStep.zig b/lib/std/Build/WriteFileStep.zig similarity index 91% rename from lib/std/build/WriteFileStep.zig rename to lib/std/Build/WriteFileStep.zig index 4faae8f74e..59ac568221 100644 --- a/lib/std/build/WriteFileStep.zig +++ b/lib/std/Build/WriteFileStep.zig @@ -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), @@ -33,7 +31,7 @@ pub fn add(self: *WriteFileStep, basename: []const u8, bytes: []const u8) void { const node = self.builder.allocator.create(std.TailQueue(File).Node) catch unreachable; 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; } diff --git a/lib/std/build.zig b/lib/std/build.zig deleted file mode 100644 index 4ee00a4710..0000000000 --- a/lib/std/build.zig +++ /dev/null @@ -1,1863 +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, - /// 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, - ) !*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", - }, - .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, - .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 { - 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: *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); - } - - pub fn addOptions(self: *Builder) *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: ?LibExeObjStep.Linkage = null, - }; - - pub fn addExecutable(b: *Builder, options: ExecutableOptions) *LibExeObjStep { - return LibExeObjStep.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: *Builder, options: ObjectOptions) *LibExeObjStep { - return LibExeObjStep.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: *Builder, options: SharedLibraryOptions) *LibExeObjStep { - return LibExeObjStep.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: *Builder, options: StaticLibraryOptions) *LibExeObjStep { - return LibExeObjStep.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: LibExeObjStep.Kind = .@"test", - root_source_file: FileSource, - target: CrossTarget = .{}, - optimize: std.builtin.Mode = .Debug, - version: ?std.builtin.Version = null, - }; - - pub fn addTest(b: *Builder, options: TestOptions) *LibExeObjStep { - return LibExeObjStep.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: *Builder, options: AssemblyOptions) *LibExeObjStep { - const obj_step = LibExeObjStep.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 `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, options: TranslateCStep.Options) *TranslateCStep { - return TranslateCStep.create(self, options); - } - - 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, .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 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; - } - - pub const StandardOptimizeOptionOptions = struct { - preferred_optimize_mode: ?std.builtin.Mode = null, - }; - - pub fn standardOptimizeOption(self: *Builder, 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: *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; - }, - .map => |*map| { - _ = map; - log.warn("TODO maps as command line arguments is not implemented yet.", .{}); - 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, .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: *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}", .{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; - - if (sub_builder.validateUserInputDidItFail()) { - std.debug.dumpCurrentStackTrace(@returnAddress()); - } - - 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), - }; - } -}; - -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(); - 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; -} diff --git a/lib/std/std.zig b/lib/std/std.zig index ba52784b45..e0318ceb43 100644 --- a/lib/std/std.zig +++ b/lib/std/std.zig @@ -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,12 @@ pub const wasm = @import("wasm.zig"); pub const zig = @import("zig.zig"); pub const start = @import("start.zig"); +///// Deprecated. Use `std.Build` instead. +//pub const build = struct { +// /// Deprecated. Use `std.Build` instead. +// pub const Builder = Build; +//}; + const root = @import("root"); const options_override = if (@hasDecl(root, "std_options")) root.std_options else struct {}; diff --git a/test/link/bss/build.zig b/test/link/bss/build.zig index c31fa7faf5..0df9c1d323 100644 --- a/test/link/bss/build.zig +++ b/test/link/bss/build.zig @@ -1,6 +1,6 @@ -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 test_step = b.step("test", "Test"); diff --git a/test/link/common_symbols/build.zig b/test/link/common_symbols/build.zig index 068c3f9c57..ee9dd94ebd 100644 --- a/test/link/common_symbols/build.zig +++ b/test/link/common_symbols/build.zig @@ -1,6 +1,6 @@ -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 lib_a = b.addStaticLibrary(.{ diff --git a/test/link/common_symbols_alignment/build.zig b/test/link/common_symbols_alignment/build.zig index b6dd39801c..f6efdc784b 100644 --- a/test/link/common_symbols_alignment/build.zig +++ b/test/link/common_symbols_alignment/build.zig @@ -1,6 +1,6 @@ -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(.{}); diff --git a/test/link/interdependent_static_c_libs/build.zig b/test/link/interdependent_static_c_libs/build.zig index 50a214490d..d8962a8e08 100644 --- a/test/link/interdependent_static_c_libs/build.zig +++ b/test/link/interdependent_static_c_libs/build.zig @@ -1,6 +1,6 @@ -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(.{}); diff --git a/test/link/macho/bugs/13056/build.zig b/test/link/macho/bugs/13056/build.zig index a65cd60766..662fd25c92 100644 --- a/test/link/macho/bugs/13056/build.zig +++ b/test/link/macho/bugs/13056/build.zig @@ -1,7 +1,6 @@ const std = @import("std"); -const Builder = std.build.Builder; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const target: std.zig.CrossTarget = .{ .os_tag = .macos }; diff --git a/test/link/macho/bugs/13457/build.zig b/test/link/macho/bugs/13457/build.zig index 4c1ce89261..6ca1f31b86 100644 --- a/test/link/macho/bugs/13457/build.zig +++ b/test/link/macho/bugs/13457/build.zig @@ -1,8 +1,7 @@ const std = @import("std"); -const Builder = std.build.Builder; -const LibExeObjectStep = std.build.LibExeObjStep; +const LibExeObjectStep = std.Build.LibExeObjStep; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const target: std.zig.CrossTarget = .{ .os_tag = .macos }; diff --git a/test/link/macho/dead_strip/build.zig b/test/link/macho/dead_strip/build.zig index a4c3575e45..b6c3002492 100644 --- a/test/link/macho/dead_strip/build.zig +++ b/test/link/macho/dead_strip/build.zig @@ -1,8 +1,7 @@ const std = @import("std"); -const Builder = std.build.Builder; -const LibExeObjectStep = std.build.LibExeObjStep; +const LibExeObjectStep = std.Build.LibExeObjStep; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const target: std.zig.CrossTarget = .{ .os_tag = .macos }; @@ -37,7 +36,7 @@ pub fn build(b: *Builder) void { } } -fn createScenario(b: *Builder, optimize: std.builtin.OptimizeMode, target: std.zig.CrossTarget) *LibExeObjectStep { +fn createScenario(b: *std.Build, optimize: std.builtin.OptimizeMode, target: std.zig.CrossTarget) *LibExeObjectStep { const exe = b.addExecutable(.{ .name = "test", .optimize = optimize, diff --git a/test/link/macho/dead_strip_dylibs/build.zig b/test/link/macho/dead_strip_dylibs/build.zig index 0127b575fc..f61b30ca4a 100644 --- a/test/link/macho/dead_strip_dylibs/build.zig +++ b/test/link/macho/dead_strip_dylibs/build.zig @@ -1,8 +1,7 @@ const std = @import("std"); -const Builder = std.build.Builder; -const LibExeObjectStep = std.build.LibExeObjStep; +const LibExeObjectStep = std.Build.LibExeObjStep; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const test_step = b.step("test", "Test the program"); @@ -36,7 +35,7 @@ pub fn build(b: *Builder) void { } } -fn createScenario(b: *Builder, optimize: std.builtin.OptimizeMode) *LibExeObjectStep { +fn createScenario(b: *std.Build, optimize: std.builtin.OptimizeMode) *LibExeObjectStep { const exe = b.addExecutable(.{ .name = "test", .optimize = optimize, diff --git a/test/link/macho/dylib/build.zig b/test/link/macho/dylib/build.zig index acd27a507f..7a1e2d862c 100644 --- a/test/link/macho/dylib/build.zig +++ b/test/link/macho/dylib/build.zig @@ -1,7 +1,6 @@ const std = @import("std"); -const Builder = std.build.Builder; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const target: std.zig.CrossTarget = .{ .os_tag = .macos }; diff --git a/test/link/macho/empty/build.zig b/test/link/macho/empty/build.zig index 8b2d047371..586da1511b 100644 --- a/test/link/macho/empty/build.zig +++ b/test/link/macho/empty/build.zig @@ -1,7 +1,6 @@ const std = @import("std"); -const Builder = std.build.Builder; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const target: std.zig.CrossTarget = .{ .os_tag = .macos }; @@ -17,7 +16,7 @@ pub fn build(b: *Builder) void { exe.addCSourceFile("empty.c", &[0][]const u8{}); 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); } diff --git a/test/link/macho/entry/build.zig b/test/link/macho/entry/build.zig index 87e4d1b5da..4504da9c6c 100644 --- a/test/link/macho/entry/build.zig +++ b/test/link/macho/entry/build.zig @@ -1,7 +1,6 @@ const std = @import("std"); -const Builder = std.build.Builder; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const test_step = b.step("test", "Test"); diff --git a/test/link/macho/headerpad/build.zig b/test/link/macho/headerpad/build.zig index 74efb5d580..2b3c6abb8a 100644 --- a/test/link/macho/headerpad/build.zig +++ b/test/link/macho/headerpad/build.zig @@ -1,9 +1,8 @@ const std = @import("std"); const builtin = @import("builtin"); -const Builder = std.build.Builder; -const LibExeObjectStep = std.build.LibExeObjStep; +const LibExeObjectStep = std.Build.LibExeObjStep; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const test_step = b.step("test", "Test"); @@ -94,7 +93,7 @@ pub fn build(b: *Builder) void { } } -fn simpleExe(b: *Builder, optimize: std.builtin.OptimizeMode) *LibExeObjectStep { +fn simpleExe(b: *std.Build, optimize: std.builtin.OptimizeMode) *LibExeObjectStep { const exe = b.addExecutable(.{ .name = "main", .optimize = optimize, diff --git a/test/link/macho/linksection/build.zig b/test/link/macho/linksection/build.zig index eebb31a21e..227d4eeb63 100644 --- a/test/link/macho/linksection/build.zig +++ b/test/link/macho/linksection/build.zig @@ -1,6 +1,6 @@ const std = @import("std"); -pub fn build(b: *std.build.Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const target = std.zig.CrossTarget{ .os_tag = .macos }; diff --git a/test/link/macho/needed_framework/build.zig b/test/link/macho/needed_framework/build.zig index 33965a9272..62b70b21f1 100644 --- a/test/link/macho/needed_framework/build.zig +++ b/test/link/macho/needed_framework/build.zig @@ -1,8 +1,7 @@ const std = @import("std"); -const Builder = std.build.Builder; -const LibExeObjectStep = std.build.LibExeObjStep; +const LibExeObjectStep = std.Build.LibExeObjStep; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const test_step = b.step("test", "Test the program"); diff --git a/test/link/macho/needed_library/build.zig b/test/link/macho/needed_library/build.zig index 137239d292..cdad94357b 100644 --- a/test/link/macho/needed_library/build.zig +++ b/test/link/macho/needed_library/build.zig @@ -1,8 +1,7 @@ const std = @import("std"); -const Builder = std.build.Builder; -const LibExeObjectStep = std.build.LibExeObjStep; +const LibExeObjectStep = std.Build.LibExeObjStep; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const target: std.zig.CrossTarget = .{ .os_tag = .macos }; diff --git a/test/link/macho/objc/build.zig b/test/link/macho/objc/build.zig index 9c38739a5c..10d293baab 100644 --- a/test/link/macho/objc/build.zig +++ b/test/link/macho/objc/build.zig @@ -1,7 +1,6 @@ const std = @import("std"); -const Builder = std.build.Builder; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const test_step = b.step("test", "Test the program"); @@ -18,6 +17,6 @@ pub fn build(b: *Builder) void { // 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); } diff --git a/test/link/macho/objcpp/build.zig b/test/link/macho/objcpp/build.zig index f4c88b2862..2a3459be50 100644 --- a/test/link/macho/objcpp/build.zig +++ b/test/link/macho/objcpp/build.zig @@ -1,7 +1,6 @@ const std = @import("std"); -const Builder = std.build.Builder; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const test_step = b.step("test", "Test the program"); diff --git a/test/link/macho/pagezero/build.zig b/test/link/macho/pagezero/build.zig index f61aa34a93..0a8471b919 100644 --- a/test/link/macho/pagezero/build.zig +++ b/test/link/macho/pagezero/build.zig @@ -1,7 +1,6 @@ const std = @import("std"); -const Builder = std.build.Builder; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const target: std.zig.CrossTarget = .{ .os_tag = .macos }; diff --git a/test/link/macho/search_strategy/build.zig b/test/link/macho/search_strategy/build.zig index db894b6ae3..eeda89446b 100644 --- a/test/link/macho/search_strategy/build.zig +++ b/test/link/macho/search_strategy/build.zig @@ -1,8 +1,7 @@ const std = @import("std"); -const Builder = std.build.Builder; -const LibExeObjectStep = std.build.LibExeObjStep; +const LibExeObjectStep = std.Build.LibExeObjStep; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const target: std.zig.CrossTarget = .{ .os_tag = .macos }; @@ -29,14 +28,14 @@ pub fn build(b: *Builder) void { 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, optimize: std.builtin.OptimizeMode, target: std.zig.CrossTarget) *LibExeObjectStep { +fn createScenario(b: *std.Build, optimize: std.builtin.OptimizeMode, target: std.zig.CrossTarget) *LibExeObjectStep { const static = b.addStaticLibrary(.{ .name = "a", .optimize = optimize, @@ -44,7 +43,7 @@ fn createScenario(b: *Builder, optimize: std.builtin.OptimizeMode, target: std.z }); static.addCSourceFile("a.c", &.{}); static.linkLibC(); - static.override_dest_dir = std.build.InstallDir{ + static.override_dest_dir = std.Build.InstallDir{ .custom = "static", }; static.install(); @@ -57,7 +56,7 @@ fn createScenario(b: *Builder, optimize: std.builtin.OptimizeMode, target: std.z }); dylib.addCSourceFile("a.c", &.{}); dylib.linkLibC(); - dylib.override_dest_dir = std.build.InstallDir{ + dylib.override_dest_dir = std.Build.InstallDir{ .custom = "dynamic", }; dylib.install(); diff --git a/test/link/macho/stack_size/build.zig b/test/link/macho/stack_size/build.zig index 74e9a86e94..3529a134eb 100644 --- a/test/link/macho/stack_size/build.zig +++ b/test/link/macho/stack_size/build.zig @@ -1,7 +1,6 @@ const std = @import("std"); -const Builder = std.build.Builder; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const target: std.zig.CrossTarget = .{ .os_tag = .macos }; diff --git a/test/link/macho/strict_validation/build.zig b/test/link/macho/strict_validation/build.zig index b6baf63c11..6eabc02b5f 100644 --- a/test/link/macho/strict_validation/build.zig +++ b/test/link/macho/strict_validation/build.zig @@ -1,9 +1,8 @@ const std = @import("std"); const builtin = @import("builtin"); -const Builder = std.build.Builder; -const LibExeObjectStep = std.build.LibExeObjStep; +const LibExeObjectStep = std.Build.LibExeObjStep; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const target: std.zig.CrossTarget = .{ .os_tag = .macos }; diff --git a/test/link/macho/tls/build.zig b/test/link/macho/tls/build.zig index 9b2fe952bf..c77588cb5d 100644 --- a/test/link/macho/tls/build.zig +++ b/test/link/macho/tls/build.zig @@ -1,7 +1,6 @@ const std = @import("std"); -const Builder = std.build.Builder; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const target: std.zig.CrossTarget = .{ .os_tag = .macos }; diff --git a/test/link/macho/unwind_info/build.zig b/test/link/macho/unwind_info/build.zig index dbbdbb3e51..e43c002e2e 100644 --- a/test/link/macho/unwind_info/build.zig +++ b/test/link/macho/unwind_info/build.zig @@ -1,9 +1,8 @@ const std = @import("std"); const builtin = @import("builtin"); -const Builder = std.build.Builder; -const LibExeObjectStep = std.build.LibExeObjStep; +const LibExeObjectStep = std.Build.LibExeObjStep; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const target: std.zig.CrossTarget = .{ .os_tag = .macos }; @@ -14,8 +13,8 @@ pub fn build(b: *Builder) void { } fn testUnwindInfo( - b: *Builder, - test_step: *std.build.Step, + b: *std.Build, + test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode, target: std.zig.CrossTarget, dead_strip: bool, @@ -52,7 +51,7 @@ fn testUnwindInfo( test_step.dependOn(&run_cmd.step); } -fn createScenario(b: *Builder, optimize: std.builtin.OptimizeMode, target: std.zig.CrossTarget) *LibExeObjectStep { +fn createScenario(b: *std.Build, optimize: std.builtin.OptimizeMode, target: std.zig.CrossTarget) *LibExeObjectStep { const exe = b.addExecutable(.{ .name = "test", .optimize = optimize, diff --git a/test/link/macho/uuid/build.zig b/test/link/macho/uuid/build.zig index 86ff99e8b1..62c288f1a0 100644 --- a/test/link/macho/uuid/build.zig +++ b/test/link/macho/uuid/build.zig @@ -1,8 +1,7 @@ const std = @import("std"); -const Builder = std.build.Builder; -const LibExeObjectStep = std.build.LibExeObjStep; +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,8 +26,8 @@ pub fn build(b: *Builder) void { } fn testUuid( - b: *Builder, - test_step: *std.build.Step, + b: *std.Build, + test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode, target: std.zig.CrossTarget, comptime exp: []const u8, @@ -52,7 +51,7 @@ fn testUuid( } } -fn simpleDylib(b: *Builder, optimize: std.builtin.OptimizeMode, target: std.zig.CrossTarget) *LibExeObjectStep { +fn simpleDylib(b: *std.Build, optimize: std.builtin.OptimizeMode, target: std.zig.CrossTarget) *LibExeObjectStep { const dylib = b.addSharedLibrary(.{ .name = "test", .version = .{ .major = 1, .minor = 0 }, diff --git a/test/link/macho/weak_framework/build.zig b/test/link/macho/weak_framework/build.zig index f8460c4e82..5be66991dd 100644 --- a/test/link/macho/weak_framework/build.zig +++ b/test/link/macho/weak_framework/build.zig @@ -1,8 +1,7 @@ const std = @import("std"); -const Builder = std.build.Builder; -const LibExeObjectStep = std.build.LibExeObjStep; +const LibExeObjectStep = std.Build.LibExeObjStep; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const test_step = b.step("test", "Test the program"); diff --git a/test/link/macho/weak_library/build.zig b/test/link/macho/weak_library/build.zig index 229d965e48..505ab5ae96 100644 --- a/test/link/macho/weak_library/build.zig +++ b/test/link/macho/weak_library/build.zig @@ -1,8 +1,7 @@ const std = @import("std"); -const Builder = std.build.Builder; -const LibExeObjectStep = std.build.LibExeObjStep; +const LibExeObjectStep = std.Build.LibExeObjStep; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const target: std.zig.CrossTarget = .{ .os_tag = .macos }; diff --git a/test/link/static_lib_as_system_lib/build.zig b/test/link/static_lib_as_system_lib/build.zig index 895cdcf316..b6cf32d711 100644 --- a/test/link/static_lib_as_system_lib/build.zig +++ b/test/link/static_lib_as_system_lib/build.zig @@ -1,7 +1,6 @@ const std = @import("std"); -const Builder = std.build.Builder; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const target = b.standardTargetOptions(.{}); diff --git a/test/link/wasm/archive/build.zig b/test/link/wasm/archive/build.zig index 7401ba22dc..342c4c08d1 100644 --- a/test/link/wasm/archive/build.zig +++ b/test/link/wasm/archive/build.zig @@ -1,7 +1,6 @@ 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()); diff --git a/test/link/wasm/basic-features/build.zig b/test/link/wasm/basic-features/build.zig index 69e88aefae..9f57066518 100644 --- a/test/link/wasm/basic-features/build.zig +++ b/test/link/wasm/basic-features/build.zig @@ -1,6 +1,6 @@ const std = @import("std"); -pub fn build(b: *std.build.Builder) void { +pub fn build(b: *std.Build) void { // Library with explicitly set cpu features const lib = b.addSharedLibrary(.{ .name = "lib", diff --git a/test/link/wasm/bss/build.zig b/test/link/wasm/bss/build.zig index 6b29fd0dc3..1017e70a71 100644 --- a/test/link/wasm/bss/build.zig +++ b/test/link/wasm/bss/build.zig @@ -1,7 +1,6 @@ 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()); diff --git a/test/link/wasm/export-data/build.zig b/test/link/wasm/export-data/build.zig index 8eab283ec2..95caf42dd0 100644 --- a/test/link/wasm/export-data/build.zig +++ b/test/link/wasm/export-data/build.zig @@ -1,7 +1,6 @@ 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()); diff --git a/test/link/wasm/export/build.zig b/test/link/wasm/export/build.zig index 2b9a91d728..69c34a320e 100644 --- a/test/link/wasm/export/build.zig +++ b/test/link/wasm/export/build.zig @@ -1,6 +1,6 @@ const std = @import("std"); -pub fn build(b: *std.build.Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const no_export = b.addSharedLibrary(.{ diff --git a/test/link/wasm/extern-mangle/build.zig b/test/link/wasm/extern-mangle/build.zig index 71bb986dff..19913e6eca 100644 --- a/test/link/wasm/extern-mangle/build.zig +++ b/test/link/wasm/extern-mangle/build.zig @@ -1,7 +1,6 @@ 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()); diff --git a/test/link/wasm/extern/build.zig b/test/link/wasm/extern/build.zig index 800c76a31c..569d94091a 100644 --- a/test/link/wasm/extern/build.zig +++ b/test/link/wasm/extern/build.zig @@ -1,6 +1,6 @@ const std = @import("std"); -pub fn build(b: *std.build.Builder) void { +pub fn build(b: *std.Build) void { const exe = b.addExecutable(.{ .name = "extern", .root_source_file = .{ .path = "main.zig" }, diff --git a/test/link/wasm/function-table/build.zig b/test/link/wasm/function-table/build.zig index 804aaf0b09..4c25d0d860 100644 --- a/test/link/wasm/function-table/build.zig +++ b/test/link/wasm/function-table/build.zig @@ -1,7 +1,6 @@ const std = @import("std"); -const Builder = std.build.Builder; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const test_step = b.step("test", "Test"); diff --git a/test/link/wasm/infer-features/build.zig b/test/link/wasm/infer-features/build.zig index 147fb55fda..d6d706a33d 100644 --- a/test/link/wasm/infer-features/build.zig +++ b/test/link/wasm/infer-features/build.zig @@ -1,6 +1,6 @@ const std = @import("std"); -pub fn build(b: *std.build.Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); // Wasm Object file which we will use to infer the features from diff --git a/test/link/wasm/producers/build.zig b/test/link/wasm/producers/build.zig index 57ee6acd18..2589b0dfcf 100644 --- a/test/link/wasm/producers/build.zig +++ b/test/link/wasm/producers/build.zig @@ -1,8 +1,7 @@ const std = @import("std"); const builtin = @import("builtin"); -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()); diff --git a/test/link/wasm/segments/build.zig b/test/link/wasm/segments/build.zig index 8f7d9e0583..76160e905f 100644 --- a/test/link/wasm/segments/build.zig +++ b/test/link/wasm/segments/build.zig @@ -1,7 +1,6 @@ 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()); diff --git a/test/link/wasm/stack_pointer/build.zig b/test/link/wasm/stack_pointer/build.zig index 42971c607d..95c7643880 100644 --- a/test/link/wasm/stack_pointer/build.zig +++ b/test/link/wasm/stack_pointer/build.zig @@ -1,7 +1,6 @@ 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()); diff --git a/test/link/wasm/type/build.zig b/test/link/wasm/type/build.zig index 7fa3849083..816b57ccab 100644 --- a/test/link/wasm/type/build.zig +++ b/test/link/wasm/type/build.zig @@ -1,7 +1,6 @@ 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()); diff --git a/test/src/compare_output.zig b/test/src/compare_output.zig index a885faaadf..edd48321c9 100644 --- a/test/src/compare_output.zig +++ b/test/src/compare_output.zig @@ -1,7 +1,6 @@ // 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; @@ -9,8 +8,8 @@ const fs = std.fs; 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, optimize_modes: []const OptimizeMode, diff --git a/test/src/run_translated_c.zig b/test/src/run_translated_c.zig index 0c54655b32..2103172ed6 100644 --- a/test/src/run_translated_c.zig +++ b/test/src/run_translated_c.zig @@ -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, diff --git a/test/src/translate_c.zig b/test/src/translate_c.zig index ad5fbb7091..e275ee57ee 100644 --- a/test/src/translate_c.zig +++ b/test/src/translate_c.zig @@ -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, diff --git a/test/standalone/brace_expansion/build.zig b/test/standalone/brace_expansion/build.zig index 89250ff96f..7c32a09bef 100644 --- a/test/standalone/brace_expansion/build.zig +++ b/test/standalone/brace_expansion/build.zig @@ -1,6 +1,6 @@ -const Builder = @import("std").build.Builder; +const std = @import("std"); -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const main = b.addTest(.{ .root_source_file = .{ .path = "main.zig" }, .optimize = b.standardOptimizeOption(.{}), diff --git a/test/standalone/c_compiler/build.zig b/test/standalone/c_compiler/build.zig index 6959f810d6..dce999d4a2 100644 --- a/test/standalone/c_compiler/build.zig +++ b/test/standalone/c_compiler/build.zig @@ -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,7 +10,7 @@ fn isRunnableTarget(t: CrossTarget) bool { t.getCpuArch() == builtin.cpu.arch); } -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const target = b.standardTargetOptions(.{}); diff --git a/test/standalone/emit_asm_and_bin/build.zig b/test/standalone/emit_asm_and_bin/build.zig index b8cbd5fc17..5345f0f538 100644 --- a/test/standalone/emit_asm_and_bin/build.zig +++ b/test/standalone/emit_asm_and_bin/build.zig @@ -1,6 +1,6 @@ -const Builder = @import("std").build.Builder; +const std = @import("std"); -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const main = b.addTest(.{ .root_source_file = .{ .path = "main.zig" }, .optimize = b.standardOptimizeOption(.{}), diff --git a/test/standalone/empty_env/build.zig b/test/standalone/empty_env/build.zig index ecdd74aa90..c4b4846141 100644 --- a/test/standalone/empty_env/build.zig +++ b/test/standalone/empty_env/build.zig @@ -1,6 +1,6 @@ -const Builder = @import("std").build.Builder; +const std = @import("std"); -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const main = b.addExecutable(.{ .name = "main", .root_source_file = .{ .path = "main.zig" }, diff --git a/test/standalone/global_linkage/build.zig b/test/standalone/global_linkage/build.zig index 3064c6cc08..9f79c80fcf 100644 --- a/test/standalone/global_linkage/build.zig +++ b/test/standalone/global_linkage/build.zig @@ -1,6 +1,6 @@ -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 obj1 = b.addStaticLibrary(.{ diff --git a/test/standalone/install_raw_hex/build.zig b/test/standalone/install_raw_hex/build.zig index 94016b1d74..b0f938a344 100644 --- a/test/standalone/install_raw_hex/build.zig +++ b/test/standalone/install_raw_hex/build.zig @@ -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 }, diff --git a/test/standalone/issue_11595/build.zig b/test/standalone/issue_11595/build.zig index b0310947f6..c335fb73da 100644 --- a/test/standalone/issue_11595/build.zig +++ b/test/standalone/issue_11595/build.zig @@ -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,7 +10,7 @@ fn isRunnableTarget(t: CrossTarget) bool { t.getCpuArch() == builtin.cpu.arch); } -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const target = b.standardTargetOptions(.{}); diff --git a/test/standalone/issue_12588/build.zig b/test/standalone/issue_12588/build.zig index 27a23d5a76..9f14c53e38 100644 --- a/test/standalone/issue_12588/build.zig +++ b/test/standalone/issue_12588/build.zig @@ -1,7 +1,6 @@ const std = @import("std"); -const Builder = std.build.Builder; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const target = b.standardTargetOptions(.{}); diff --git a/test/standalone/issue_12706/build.zig b/test/standalone/issue_12706/build.zig index e3c40d34c6..9d616477a2 100644 --- a/test/standalone/issue_12706/build.zig +++ b/test/standalone/issue_12706/build.zig @@ -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,7 +10,7 @@ fn isRunnableTarget(t: CrossTarget) bool { t.getCpuArch() == builtin.cpu.arch); } -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const target = b.standardTargetOptions(.{}); diff --git a/test/standalone/issue_13030/build.zig b/test/standalone/issue_13030/build.zig index 510c7610d9..258d9b7db8 100644 --- a/test/standalone/issue_13030/build.zig +++ b/test/standalone/issue_13030/build.zig @@ -1,9 +1,8 @@ const std = @import("std"); const builtin = @import("builtin"); -const Builder = std.build.Builder; const CrossTarget = std.zig.CrossTarget; -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const target = b.standardTargetOptions(.{}); diff --git a/test/standalone/issue_339/build.zig b/test/standalone/issue_339/build.zig index 34c555cfdb..62ac128aab 100644 --- a/test/standalone/issue_339/build.zig +++ b/test/standalone/issue_339/build.zig @@ -1,6 +1,6 @@ -const Builder = @import("std").build.Builder; +const std = @import("std"); -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const obj = b.addObject(.{ .name = "test", .root_source_file = .{ .path = "test.zig" }, diff --git a/test/standalone/issue_5825/build.zig b/test/standalone/issue_5825/build.zig index 8d7acc3e9a..89272280d4 100644 --- a/test/standalone/issue_5825/build.zig +++ b/test/standalone/issue_5825/build.zig @@ -1,6 +1,6 @@ -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, diff --git a/test/standalone/issue_7030/build.zig b/test/standalone/issue_7030/build.zig index 41a646abe8..dc535318cc 100644 --- a/test/standalone/issue_7030/build.zig +++ b/test/standalone/issue_7030/build.zig @@ -1,6 +1,6 @@ -const Builder = @import("std").build.Builder; +const std = @import("std"); -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const exe = b.addExecutable(.{ .name = "issue_7030", .root_source_file = .{ .path = "main.zig" }, diff --git a/test/standalone/issue_794/build.zig b/test/standalone/issue_794/build.zig index 59ff7ea9ab..3089a28fd0 100644 --- a/test/standalone/issue_794/build.zig +++ b/test/standalone/issue_794/build.zig @@ -1,6 +1,6 @@ -const Builder = @import("std").build.Builder; +const std = @import("std"); -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const test_artifact = b.addTest(.{ .root_source_file = .{ .path = "main.zig" }, }); diff --git a/test/standalone/issue_8550/build.zig b/test/standalone/issue_8550/build.zig index 233f701661..c3303d55db 100644 --- a/test/standalone/issue_8550/build.zig +++ b/test/standalone/issue_8550/build.zig @@ -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, diff --git a/test/standalone/issue_9812/build.zig b/test/standalone/issue_9812/build.zig index 50eefe846c..4ca55ce999 100644 --- a/test/standalone/issue_9812/build.zig +++ b/test/standalone/issue_9812/build.zig @@ -1,6 +1,6 @@ const std = @import("std"); -pub fn build(b: *std.build.Builder) !void { +pub fn build(b: *std.Build) !void { const optimize = b.standardOptimizeOption(.{}); const zip_add = b.addTest(.{ .root_source_file = .{ .path = "main.zig" }, diff --git a/test/standalone/load_dynamic_library/build.zig b/test/standalone/load_dynamic_library/build.zig index 1aca02bc71..44fc37893c 100644 --- a/test/standalone/load_dynamic_library/build.zig +++ b/test/standalone/load_dynamic_library/build.zig @@ -1,6 +1,6 @@ -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 = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); diff --git a/test/standalone/main_pkg_path/build.zig b/test/standalone/main_pkg_path/build.zig index baee74052e..f9919d5ab5 100644 --- a/test/standalone/main_pkg_path/build.zig +++ b/test/standalone/main_pkg_path/build.zig @@ -1,6 +1,6 @@ -const Builder = @import("std").build.Builder; +const std = @import("std"); -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const test_exe = b.addTest(.{ .root_source_file = .{ .path = "a/test.zig" }, }); diff --git a/test/standalone/mix_c_files/build.zig b/test/standalone/mix_c_files/build.zig index ad69f05ff6..f2dfb2093f 100644 --- a/test/standalone/mix_c_files/build.zig +++ b/test/standalone/mix_c_files/build.zig @@ -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,7 +10,7 @@ fn isRunnableTarget(t: CrossTarget) bool { t.getCpuArch() == builtin.cpu.arch); } -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const optimize = b.standardOptimizeOption(.{}); const target = b.standardTargetOptions(.{}); diff --git a/test/standalone/mix_o_files/build.zig b/test/standalone/mix_o_files/build.zig index de37265388..2708343aa5 100644 --- a/test/standalone/mix_o_files/build.zig +++ b/test/standalone/mix_o_files/build.zig @@ -1,6 +1,6 @@ -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 obj = b.addObject(.{ diff --git a/test/standalone/options/build.zig b/test/standalone/options/build.zig index 87a584a887..3f1e823359 100644 --- a/test/standalone/options/build.zig +++ b/test/standalone/options/build.zig @@ -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 = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); diff --git a/test/standalone/pie/build.zig b/test/standalone/pie/build.zig index 3f0b8b9f2f..d51ea27328 100644 --- a/test/standalone/pie/build.zig +++ b/test/standalone/pie/build.zig @@ -1,6 +1,6 @@ -const Builder = @import("std").build.Builder; +const std = @import("std"); -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const main = b.addTest(.{ .root_source_file = .{ .path = "main.zig" }, .optimize = b.standardOptimizeOption(.{}), diff --git a/test/standalone/pkg_import/build.zig b/test/standalone/pkg_import/build.zig index 8dcfaeded0..5fbc8a67ae 100644 --- a/test/standalone/pkg_import/build.zig +++ b/test/standalone/pkg_import/build.zig @@ -1,6 +1,6 @@ -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 exe = b.addExecutable(.{ diff --git a/test/standalone/shared_library/build.zig b/test/standalone/shared_library/build.zig index 135be095bc..91f7c8a06a 100644 --- a/test/standalone/shared_library/build.zig +++ b/test/standalone/shared_library/build.zig @@ -1,6 +1,6 @@ -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(.{ diff --git a/test/standalone/static_c_lib/build.zig b/test/standalone/static_c_lib/build.zig index 81b4349e20..9937888843 100644 --- a/test/standalone/static_c_lib/build.zig +++ b/test/standalone/static_c_lib/build.zig @@ -1,6 +1,6 @@ -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 foo = b.addStaticLibrary(.{ diff --git a/test/standalone/test_runner_path/build.zig b/test/standalone/test_runner_path/build.zig index 9b02da50c1..f073c55d4a 100644 --- a/test/standalone/test_runner_path/build.zig +++ b/test/standalone/test_runner_path/build.zig @@ -1,6 +1,6 @@ -const Builder = @import("std").build.Builder; +const std = @import("std"); -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const test_exe = b.addTest(.{ .root_source_file = .{ .path = "test.zig" }, .kind = .test_exe, diff --git a/test/standalone/use_alias/build.zig b/test/standalone/use_alias/build.zig index d2ca90f3ab..89e07efb22 100644 --- a/test/standalone/use_alias/build.zig +++ b/test/standalone/use_alias/build.zig @@ -1,6 +1,6 @@ -const Builder = @import("std").build.Builder; +const std = @import("std"); -pub fn build(b: *Builder) void { +pub fn build(b: *std.Build) void { const main = b.addTest(.{ .root_source_file = .{ .path = "main.zig" }, .optimize = b.standardOptimizeOption(.{}), diff --git a/test/standalone/windows_spawn/build.zig b/test/standalone/windows_spawn/build.zig index de58a602c3..3ebde5a50c 100644 --- a/test/standalone/windows_spawn/build.zig +++ b/test/standalone/windows_spawn/build.zig @@ -1,6 +1,6 @@ -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 hello = b.addExecutable(.{ diff --git a/test/tests.zig b/test/tests.zig index 575550be02..de25528dde 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -1,7 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); const debug = std.debug; -const build = std.build; const CrossTarget = std.zig.CrossTarget; const io = std.io; const fs = std.fs; @@ -9,9 +8,10 @@ const mem = std.mem; const fmt = std.fmt; const ArrayList = std.ArrayList; const OptimizeMode = std.builtin.OptimizeMode; -const LibExeObjStep = build.LibExeObjStep; +const LibExeObjStep = std.Build.LibExeObjStep; const Allocator = mem.Allocator; -const ExecError = build.Builder.ExecError; +const ExecError = std.Build.ExecError; +const Step = std.Build.Step; // Cases const compare_output = @import("compare_output.zig"); @@ -462,7 +462,7 @@ const test_targets = blk: { const max_stdout_size = 1 * 1024 * 1024; // 1 MB -pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, optimize_modes: []const OptimizeMode) *build.Step { +pub fn addCompareOutputTests(b: *std.Build, test_filter: ?[]const u8, optimize_modes: []const OptimizeMode) *Step { const cases = b.allocator.create(CompareOutputContext) catch unreachable; cases.* = CompareOutputContext{ .b = b, @@ -477,7 +477,7 @@ pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, optimi return cases.step; } -pub fn addStackTraceTests(b: *build.Builder, test_filter: ?[]const u8, optimize_modes: []const OptimizeMode) *build.Step { +pub fn addStackTraceTests(b: *std.Build, test_filter: ?[]const u8, optimize_modes: []const OptimizeMode) *Step { const cases = b.allocator.create(StackTracesContext) catch unreachable; cases.* = StackTracesContext{ .b = b, @@ -493,7 +493,7 @@ pub fn addStackTraceTests(b: *build.Builder, test_filter: ?[]const u8, optimize_ } pub fn addStandaloneTests( - b: *build.Builder, + b: *std.Build, test_filter: ?[]const u8, optimize_modes: []const OptimizeMode, skip_non_native: bool, @@ -506,7 +506,7 @@ pub fn addStandaloneTests( enable_wasmtime: bool, enable_wine: bool, enable_symlinks_windows: bool, -) *build.Step { +) *Step { const cases = b.allocator.create(StandaloneContext) catch unreachable; cases.* = StandaloneContext{ .b = b, @@ -532,13 +532,13 @@ pub fn addStandaloneTests( } pub fn addLinkTests( - b: *build.Builder, + b: *std.Build, test_filter: ?[]const u8, optimize_modes: []const OptimizeMode, enable_macos_sdk: bool, omit_stage2: bool, enable_symlinks_windows: bool, -) *build.Step { +) *Step { const cases = b.allocator.create(StandaloneContext) catch unreachable; cases.* = StandaloneContext{ .b = b, @@ -556,7 +556,7 @@ pub fn addLinkTests( return cases.step; } -pub fn addCliTests(b: *build.Builder, test_filter: ?[]const u8, optimize_modes: []const OptimizeMode) *build.Step { +pub fn addCliTests(b: *std.Build, test_filter: ?[]const u8, optimize_modes: []const OptimizeMode) *Step { _ = test_filter; _ = optimize_modes; const step = b.step("test-cli", "Test the command line interface"); @@ -577,7 +577,7 @@ pub fn addCliTests(b: *build.Builder, test_filter: ?[]const u8, optimize_modes: return step; } -pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, optimize_modes: []const OptimizeMode) *build.Step { +pub fn addAssembleAndLinkTests(b: *std.Build, test_filter: ?[]const u8, optimize_modes: []const OptimizeMode) *Step { const cases = b.allocator.create(CompareOutputContext) catch unreachable; cases.* = CompareOutputContext{ .b = b, @@ -592,7 +592,7 @@ pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, opti return cases.step; } -pub fn addTranslateCTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step { +pub fn addTranslateCTests(b: *std.Build, test_filter: ?[]const u8) *Step { const cases = b.allocator.create(TranslateCContext) catch unreachable; cases.* = TranslateCContext{ .b = b, @@ -607,10 +607,10 @@ pub fn addTranslateCTests(b: *build.Builder, test_filter: ?[]const u8) *build.St } pub fn addRunTranslatedCTests( - b: *build.Builder, + b: *std.Build, test_filter: ?[]const u8, target: std.zig.CrossTarget, -) *build.Step { +) *Step { const cases = b.allocator.create(RunTranslatedCContext) catch unreachable; cases.* = .{ .b = b, @@ -625,7 +625,7 @@ pub fn addRunTranslatedCTests( return cases.step; } -pub fn addGenHTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step { +pub fn addGenHTests(b: *std.Build, test_filter: ?[]const u8) *Step { const cases = b.allocator.create(GenHContext) catch unreachable; cases.* = GenHContext{ .b = b, @@ -640,7 +640,7 @@ pub fn addGenHTests(b: *build.Builder, test_filter: ?[]const u8) *build.Step { } pub fn addPkgTests( - b: *build.Builder, + b: *std.Build, test_filter: ?[]const u8, root_src: []const u8, name: []const u8, @@ -651,7 +651,7 @@ pub fn addPkgTests( skip_libc: bool, skip_stage1: bool, skip_stage2: bool, -) *build.Step { +) *Step { const step = b.step(b.fmt("test-{s}", .{name}), desc); for (test_targets) |test_target| { @@ -742,8 +742,8 @@ pub fn addPkgTests( } pub const StackTracesContext = struct { - b: *build.Builder, - step: *build.Step, + b: *std.Build, + step: *Step, test_index: usize, test_filter: ?[]const u8, optimize_modes: []const OptimizeMode, @@ -840,7 +840,7 @@ pub const StackTracesContext = struct { const RunAndCompareStep = struct { pub const base_id = .custom; - step: build.Step, + step: Step, context: *StackTracesContext, exe: *LibExeObjStep, name: []const u8, @@ -858,7 +858,7 @@ pub const StackTracesContext = struct { const allocator = context.b.allocator; const ptr = allocator.create(RunAndCompareStep) catch unreachable; ptr.* = RunAndCompareStep{ - .step = build.Step.init(.custom, "StackTraceCompareOutputStep", allocator, make), + .step = Step.init(.custom, "StackTraceCompareOutputStep", allocator, make), .context = context, .exe = exe, .name = name, @@ -871,7 +871,7 @@ pub const StackTracesContext = struct { return ptr; } - fn make(step: *build.Step) !void { + fn make(step: *Step) !void { const self = @fieldParentPtr(RunAndCompareStep, "step", step); const b = self.context.b; @@ -1014,8 +1014,8 @@ pub const StackTracesContext = struct { }; pub const StandaloneContext = struct { - b: *build.Builder, - step: *build.Step, + b: *std.Build, + step: *Step, test_index: usize, test_filter: ?[]const u8, optimize_modes: []const OptimizeMode, @@ -1150,8 +1150,8 @@ pub const StandaloneContext = struct { }; pub const GenHContext = struct { - b: *build.Builder, - step: *build.Step, + b: *std.Build, + step: *Step, test_index: usize, test_filter: ?[]const u8, @@ -1178,7 +1178,7 @@ pub const GenHContext = struct { }; const GenHCmpOutputStep = struct { - step: build.Step, + step: Step, context: *GenHContext, obj: *LibExeObjStep, name: []const u8, @@ -1194,7 +1194,7 @@ pub const GenHContext = struct { const allocator = context.b.allocator; const ptr = allocator.create(GenHCmpOutputStep) catch unreachable; ptr.* = GenHCmpOutputStep{ - .step = build.Step.init(.Custom, "ParseCCmpOutput", allocator, make), + .step = Step.init(.Custom, "ParseCCmpOutput", allocator, make), .context = context, .obj = obj, .name = name, @@ -1206,7 +1206,7 @@ pub const GenHContext = struct { return ptr; } - fn make(step: *build.Step) !void { + fn make(step: *Step) !void { const self = @fieldParentPtr(GenHCmpOutputStep, "step", step); const b = self.context.b; @@ -1348,7 +1348,7 @@ const c_abi_targets = [_]CrossTarget{ }, }; -pub fn addCAbiTests(b: *build.Builder, skip_non_native: bool, skip_release: bool) *build.Step { +pub fn addCAbiTests(b: *std.Build, skip_non_native: bool, skip_release: bool) *Step { const step = b.step("test-c-abi", "Run the C ABI tests"); const optimize_modes: [2]OptimizeMode = .{ .Debug, .ReleaseFast };