Merge pull request #20388 from BratishkaErik/std.Build/accept-root-module-2

std.Build: add new functions to create artifacts/Step.Compile from existing module
This commit is contained in:
Matthew Lugg 2024-12-18 03:34:43 +00:00 committed by GitHub
commit 12d64c456b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
95 changed files with 1833 additions and 1428 deletions

160
build.zig
View File

@ -50,10 +50,12 @@ pub fn build(b: *std.Build) !void {
const autodoc_test = b.addObject(.{
.name = "std",
.root_source_file = b.path("lib/std/std.zig"),
.target = target,
.zig_lib_dir = b.path("lib"),
.optimize = .Debug,
.root_module = b.createModule(.{
.root_source_file = b.path("lib/std/std.zig"),
.target = target,
.optimize = .Debug,
}),
});
const install_std_docs = b.addInstallDirectory(.{
.source_dir = autodoc_test.getEmittedDocs(),
@ -234,7 +236,7 @@ pub fn build(b: *std.Build) !void {
exe_options.addOption(DevEnv, "dev", b.option(DevEnv, "dev", "Build a compiler with a reduced feature set for development of specific features") orelse if (only_c) .bootstrap else .full);
if (link_libc) {
exe.linkLibC();
exe.root_module.link_libc = true;
}
const is_debug = optimize == .Debug;
@ -330,15 +332,15 @@ pub fn build(b: *std.Build) !void {
try addCmakeCfgOptionsToExe(b, cfg, exe, use_zig_libcxx);
} else {
// Here we are -Denable-llvm but no cmake integration.
try addStaticLlvmOptionsToExe(exe);
try addStaticLlvmOptionsToModule(exe.root_module);
}
if (target.result.os.tag == .windows) {
// LLVM depends on networking as of version 18.
exe.linkSystemLibrary("ws2_32");
exe.root_module.linkSystemLibrary("ws2_32", .{});
exe.linkSystemLibrary("version");
exe.linkSystemLibrary("uuid");
exe.linkSystemLibrary("ole32");
exe.root_module.linkSystemLibrary("version", .{});
exe.root_module.linkSystemLibrary("uuid", .{});
exe.root_module.linkSystemLibrary("ole32", .{});
}
}
@ -364,16 +366,16 @@ pub fn build(b: *std.Build) !void {
else
&[_][]const u8{ "-DTRACY_ENABLE=1", "-fno-sanitize=undefined" };
exe.addIncludePath(.{ .cwd_relative = tracy_path });
exe.addCSourceFile(.{ .file = .{ .cwd_relative = client_cpp }, .flags = tracy_c_flags });
exe.root_module.addIncludePath(.{ .cwd_relative = tracy_path });
exe.root_module.addCSourceFile(.{ .file = .{ .cwd_relative = client_cpp }, .flags = tracy_c_flags });
if (!enable_llvm) {
exe.root_module.linkSystemLibrary("c++", .{ .use_pkg_config = .no });
}
exe.linkLibC();
exe.root_module.link_libc = true;
if (target.result.os.tag == .windows) {
exe.linkSystemLibrary("dbghelp");
exe.linkSystemLibrary("ws2_32");
exe.root_module.linkSystemLibrary("dbghelp", .{});
exe.root_module.linkSystemLibrary("ws2_32", .{});
}
}
@ -559,8 +561,10 @@ pub fn build(b: *std.Build) !void {
if (opt_mingw_src_path) |mingw_src_path| {
const update_mingw_exe = b.addExecutable(.{
.name = "update_mingw",
.target = b.graph.host,
.root_source_file = b.path("tools/update_mingw.zig"),
.root_module = b.createModule(.{
.target = b.graph.host,
.root_source_file = b.path("tools/update_mingw.zig"),
}),
});
const update_mingw_run = b.addRunArtifact(update_mingw_exe);
update_mingw_run.addDirectoryArg(b.path("lib"));
@ -636,12 +640,10 @@ const AddCompilerStepOptions = struct {
};
fn addCompilerStep(b: *std.Build, options: AddCompilerStepOptions) *std.Build.Step.Compile {
const exe = b.addExecutable(.{
.name = "zig",
const compiler_mod = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = options.target,
.optimize = options.optimize,
.max_rss = 7_800_000_000,
.strip = options.strip,
.sanitize_thread = options.sanitize_thread,
.single_threaded = options.single_threaded,
@ -663,26 +665,28 @@ fn addCompilerStep(b: *std.Build, options: AddCompilerStepOptions) *std.Build.St
.loongarch32, .loongarch64 => .medium,
else => .default,
},
.valgrind = options.valgrind,
});
exe.root_module.valgrind = options.valgrind;
exe.stack_size = stack_size;
const aro_module = b.createModule(.{
const aro_mod = b.createModule(.{
.root_source_file = b.path("lib/compiler/aro/aro.zig"),
});
const aro_translate_c_module = b.createModule(.{
const aro_translate_c_mod = b.createModule(.{
.root_source_file = b.path("lib/compiler/aro_translate_c.zig"),
.imports = &.{
.{
.name = "aro",
.module = aro_module,
},
},
});
exe.root_module.addImport("aro", aro_module);
exe.root_module.addImport("aro_translate_c", aro_translate_c_module);
aro_translate_c_mod.addImport("aro", aro_mod);
compiler_mod.addImport("aro", aro_mod);
compiler_mod.addImport("aro_translate_c", aro_translate_c_mod);
const exe = b.addExecutable(.{
.name = "zig",
.max_rss = 7_800_000_000,
.root_module = compiler_mod,
});
exe.stack_size = stack_size;
return exe;
}
@ -707,11 +711,15 @@ fn addCmakeCfgOptionsToExe(
exe: *std.Build.Step.Compile,
use_zig_libcxx: bool,
) !void {
if (exe.rootModuleTarget().isDarwin()) {
const mod = exe.root_module;
const target = mod.resolved_target.?.result;
if (target.isDarwin()) {
// useful for package maintainers
exe.headerpad_max_install_names = true;
}
exe.addObjectFile(.{ .cwd_relative = b.pathJoin(&[_][]const u8{
mod.addObjectFile(.{ .cwd_relative = b.pathJoin(&.{
cfg.cmake_binary_dir,
"zigcpp",
b.fmt("{s}{s}{s}", .{
@ -721,38 +729,38 @@ fn addCmakeCfgOptionsToExe(
}),
}) });
assert(cfg.lld_include_dir.len != 0);
exe.addIncludePath(.{ .cwd_relative = cfg.lld_include_dir });
exe.addIncludePath(.{ .cwd_relative = cfg.llvm_include_dir });
exe.addLibraryPath(.{ .cwd_relative = cfg.llvm_lib_dir });
addCMakeLibraryList(exe, cfg.clang_libraries);
addCMakeLibraryList(exe, cfg.lld_libraries);
addCMakeLibraryList(exe, cfg.llvm_libraries);
mod.addIncludePath(.{ .cwd_relative = cfg.lld_include_dir });
mod.addIncludePath(.{ .cwd_relative = cfg.llvm_include_dir });
mod.addLibraryPath(.{ .cwd_relative = cfg.llvm_lib_dir });
addCMakeLibraryList(mod, cfg.clang_libraries);
addCMakeLibraryList(mod, cfg.lld_libraries);
addCMakeLibraryList(mod, cfg.llvm_libraries);
if (use_zig_libcxx) {
exe.linkLibCpp();
mod.link_libcpp = true;
} else {
// System -lc++ must be used because in this code path we are attempting to link
// against system-provided LLVM, Clang, LLD.
const need_cpp_includes = true;
const static = cfg.llvm_linkage == .static;
const lib_suffix = if (static) exe.rootModuleTarget().staticLibSuffix()[1..] else exe.rootModuleTarget().dynamicLibSuffix()[1..];
switch (exe.rootModuleTarget().os.tag) {
const lib_suffix = if (static) target.staticLibSuffix()[1..] else target.dynamicLibSuffix()[1..];
switch (target.os.tag) {
.linux => {
// First we try to link against the detected libcxx name. If that doesn't work, we fall
// back to -lc++ and cross our fingers.
addCxxKnownPath(b, cfg, exe, b.fmt("lib{s}.{s}", .{ cfg.system_libcxx, lib_suffix }), "", need_cpp_includes) catch |err| switch (err) {
error.RequiredLibraryNotFound => {
exe.linkLibCpp();
mod.link_libcpp = true;
},
else => |e| return e,
};
exe.linkSystemLibrary("unwind");
mod.linkSystemLibrary("unwind", .{});
},
.ios, .macos, .watchos, .tvos, .visionos => {
exe.linkLibCpp();
mod.link_libcpp = true;
},
.windows => {
if (exe.rootModuleTarget().abi != .msvc) exe.linkLibCpp();
if (target.abi != .msvc) mod.link_libcpp = true;
},
.freebsd => {
if (static) {
@ -786,46 +794,46 @@ fn addCmakeCfgOptionsToExe(
}
if (cfg.dia_guids_lib.len != 0) {
exe.addObjectFile(.{ .cwd_relative = cfg.dia_guids_lib });
mod.addObjectFile(.{ .cwd_relative = cfg.dia_guids_lib });
}
}
fn addStaticLlvmOptionsToExe(exe: *std.Build.Step.Compile) !void {
fn addStaticLlvmOptionsToModule(mod: *std.Build.Module) !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
// in a dependency on llvm::cfg::Update<llvm::BasicBlock*>::dump() which is
// unavailable when LLVM is compiled in Release mode.
const zig_cpp_cflags = exe_cflags ++ [_][]const u8{"-DNDEBUG=1"};
exe.addCSourceFiles(.{
mod.addCSourceFiles(.{
.files = &zig_cpp_sources,
.flags = &zig_cpp_cflags,
});
for (clang_libs) |lib_name| {
exe.linkSystemLibrary(lib_name);
mod.linkSystemLibrary(lib_name, .{});
}
for (lld_libs) |lib_name| {
exe.linkSystemLibrary(lib_name);
mod.linkSystemLibrary(lib_name, .{});
}
for (llvm_libs) |lib_name| {
exe.linkSystemLibrary(lib_name);
mod.linkSystemLibrary(lib_name, .{});
}
exe.linkSystemLibrary("z");
exe.linkSystemLibrary("zstd");
mod.linkSystemLibrary("z", .{});
mod.linkSystemLibrary("zstd", .{});
if (exe.rootModuleTarget().os.tag != .windows or exe.rootModuleTarget().abi != .msvc) {
if (mod.resolved_target.?.result.os.tag != .windows or mod.resolved_target.?.result.abi != .msvc) {
// This means we rely on clang-or-zig-built LLVM, Clang, LLD libraries.
exe.linkSystemLibrary("c++");
mod.linkSystemLibrary("c++", .{});
}
if (exe.rootModuleTarget().os.tag == .windows) {
exe.linkSystemLibrary("version");
exe.linkSystemLibrary("uuid");
exe.linkSystemLibrary("ole32");
if (mod.resolved_target.?.result.os.tag == .windows) {
mod.linkSystemLibrary("version", .{});
mod.linkSystemLibrary("uuid", .{});
mod.linkSystemLibrary("ole32", .{});
}
}
@ -862,29 +870,29 @@ fn addCxxKnownPath(
// but libc++ may very well be one, so force all inputs to be checked when passing
// an explicit path to libc++.
exe.allow_so_scripts = true;
exe.addObjectFile(.{ .cwd_relative = path_unpadded });
exe.root_module.addObjectFile(.{ .cwd_relative = path_unpadded });
// TODO a way to integrate with system c++ include files here
// c++ -E -Wp,-v -xc++ /dev/null
if (need_cpp_includes) {
// I used these temporarily for testing something but we obviously need a
// more general purpose solution here.
//exe.addIncludePath("/nix/store/2lr0fc0ak8rwj0k8n3shcyz1hz63wzma-gcc-11.3.0/include/c++/11.3.0");
//exe.addIncludePath("/nix/store/2lr0fc0ak8rwj0k8n3shcyz1hz63wzma-gcc-11.3.0/include/c++/11.3.0/x86_64-unknown-linux-gnu");
//exe.root_module.addIncludePath("/nix/store/2lr0fc0ak8rwj0k8n3shcyz1hz63wzma-gcc-11.3.0/include/c++/11.3.0");
//exe.root_module.addIncludePath("/nix/store/2lr0fc0ak8rwj0k8n3shcyz1hz63wzma-gcc-11.3.0/include/c++/11.3.0/x86_64-unknown-linux-gnu");
}
}
fn addCMakeLibraryList(exe: *std.Build.Step.Compile, list: []const u8) void {
fn addCMakeLibraryList(mod: *std.Build.Module, list: []const u8) void {
var it = mem.tokenizeScalar(u8, list, ';');
while (it.next()) |lib| {
if (mem.startsWith(u8, lib, "-l")) {
exe.linkSystemLibrary(lib["-l".len..]);
} else if (exe.rootModuleTarget().os.tag == .windows and
mod.linkSystemLibrary(lib["-l".len..], .{});
} else if (mod.resolved_target.?.result.os.tag == .windows and
mem.endsWith(u8, lib, ".lib") and !fs.path.isAbsolute(lib))
{
exe.linkSystemLibrary(lib[0 .. lib.len - ".lib".len]);
mod.linkSystemLibrary(lib[0 .. lib.len - ".lib".len], .{});
} else {
exe.addObjectFile(.{ .cwd_relative = lib });
mod.addObjectFile(.{ .cwd_relative = lib });
}
}
}
@ -1306,9 +1314,11 @@ const llvm_libs = [_][]const u8{
fn generateLangRef(b: *std.Build) std.Build.LazyPath {
const doctest_exe = b.addExecutable(.{
.name = "doctest",
.root_source_file = b.path("tools/doctest.zig"),
.target = b.graph.host,
.optimize = .Debug,
.root_module = b.createModule(.{
.root_source_file = b.path("tools/doctest.zig"),
.target = b.graph.host,
.optimize = .Debug,
}),
});
var dir = b.build_root.handle.openDir("doc/langref", .{ .iterate = true }) catch |err| {
@ -1343,9 +1353,11 @@ fn generateLangRef(b: *std.Build) std.Build.LazyPath {
const docgen_exe = b.addExecutable(.{
.name = "docgen",
.root_source_file = b.path("tools/docgen.zig"),
.target = b.graph.host,
.optimize = .Debug,
.root_module = b.createModule(.{
.root_source_file = b.path("tools/docgen.zig"),
.target = b.graph.host,
.optimize = .Debug,
}),
});
const docgen_cmd = b.addRunArtifact(docgen_exe);

View File

@ -337,6 +337,7 @@ pub fn main() !void {
var prog_node = main_progress_node.start("Configure", 0);
defer prog_node.end();
try builder.runBuild(root);
createModuleDependencies(builder) catch @panic("OOM");
}
if (graph.needed_lazy_dependencies.entries.len != 0) {
@ -1440,3 +1441,80 @@ fn validateSystemLibraryOptions(b: *std.Build) void {
process.exit(1);
}
}
/// Starting from all top-level steps in `b`, traverses the entire step graph
/// and adds all step dependencies implied by module graphs.
fn createModuleDependencies(b: *std.Build) Allocator.Error!void {
const arena = b.graph.arena;
var all_steps: std.AutoArrayHashMapUnmanaged(*Step, void) = .empty;
var next_step_idx: usize = 0;
try all_steps.ensureUnusedCapacity(arena, b.top_level_steps.count());
for (b.top_level_steps.values()) |tls| {
all_steps.putAssumeCapacityNoClobber(&tls.step, {});
}
while (next_step_idx < all_steps.count()) {
const step = all_steps.keys()[next_step_idx];
next_step_idx += 1;
// Set up any implied dependencies for this step. It's important that we do this first, so
// that the loop below discovers steps implied by the module graph.
try createModuleDependenciesForStep(step);
try all_steps.ensureUnusedCapacity(arena, step.dependencies.items.len);
for (step.dependencies.items) |other_step| {
all_steps.putAssumeCapacity(other_step, {});
}
}
}
/// If the given `Step` is a `Step.Compile`, adds any dependencies for that step which
/// are implied by the module graph rooted at `step.cast(Step.Compile).?.root_module`.
fn createModuleDependenciesForStep(step: *Step) Allocator.Error!void {
const root_module = if (step.cast(Step.Compile)) |cs| root: {
break :root cs.root_module;
} else return; // not a compile step so no module dependencies
// Starting from `root_module`, discover all modules in this graph.
const modules = root_module.getGraph().modules;
// For each of those modules, set up the implied step dependencies.
for (modules) |mod| {
if (mod.root_source_file) |lp| lp.addStepDependencies(step);
for (mod.include_dirs.items) |include_dir| switch (include_dir) {
.path,
.path_system,
.path_after,
.framework_path,
.framework_path_system,
=> |lp| lp.addStepDependencies(step),
.other_step => |other| {
other.getEmittedIncludeTree().addStepDependencies(step);
step.dependOn(&other.step);
},
.config_header_step => |other| step.dependOn(&other.step),
};
for (mod.lib_paths.items) |lp| lp.addStepDependencies(step);
for (mod.rpaths.items) |rpath| switch (rpath) {
.lazy_path => |lp| lp.addStepDependencies(step),
.special => {},
};
for (mod.link_objects.items) |link_object| switch (link_object) {
.static_path,
.assembly_file,
=> |lp| lp.addStepDependencies(step),
.other_step => |other| step.dependOn(&other.step),
.system_lib => {},
.c_source_file => |source| source.file.addStepDependencies(step),
.c_source_files => |source_files| source_files.root.addStepDependencies(step),
.win32_resource_file => |rc_source| {
rc_source.file.addStepDependencies(step);
for (rc_source.include_paths) |lp| lp.addStepDependencies(step);
},
};
}
}

View File

@ -15,8 +15,12 @@ pub fn build(b: *std.Build) void {
// set a preferred release mode, allowing the user to decide how to optimize.
const optimize = b.standardOptimizeOption(.{});
const lib = b.addStaticLibrary(.{
.name = "$",
// This creates a "module", which represents a collection of source files alongside
// some compilation options, such as optimization mode and linked system libraries.
// Every executable or library we compile will be based on one or more modules.
const lib_mod = b.createModule(.{
// `root_source_file` is the Zig "entry point" of the module. If a module
// only contains e.g. external object files, you can make this `null`.
// In this case the main source file is merely a path, however, in more
// complicated build scripts, this could be a generated file.
.root_source_file = b.path("src/root.zig"),
@ -24,16 +28,40 @@ pub fn build(b: *std.Build) void {
.optimize = optimize,
});
// We will also create a module for our other entry point, 'main.zig'.
const exe_mod = b.createModule(.{
// `root_source_file` is the Zig "entry point" of the module. If a module
// only contains e.g. external object files, you can make this `null`.
// In this case the main source file is merely a path, however, in more
// complicated build scripts, this could be a generated file.
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
// Modules can depend on one another using the `std.Build.Module.addImport` function.
// This is what allows Zig source code to use `@import("foo")` where 'foo' is not a
// file path. In this case, we set up `exe_mod` to import `lib_mod`.
exe_mod.addImport("$_lib", lib_mod);
// Now, we will create a static library based on the module we created above.
// This creates a `std.Build.Step.Compile`, which is the build step responsible
// for actually invoking the compiler.
const lib = b.addStaticLibrary(.{
.name = "$",
.root_module = lib_mod,
});
// This declares intent for the library to be installed into the standard
// location when the user invokes the "install" step (the default step when
// running `zig build`).
b.installArtifact(lib);
// This creates another `std.Build.Step.Compile`, but this one builds an executable
// rather than a static library.
const exe = b.addExecutable(.{
.name = "$",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
.root_module = exe_mod,
});
// This declares intent for the executable to be installed into the
@ -67,17 +95,13 @@ pub fn build(b: *std.Build) void {
// Creates a step for unit testing. This only builds the test executable
// but does not run it.
const lib_unit_tests = b.addTest(.{
.root_source_file = b.path("src/root.zig"),
.target = target,
.optimize = optimize,
.root_module = lib_mod,
});
const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests);
const exe_unit_tests = b.addTest(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
.root_module = exe_mod,
});
const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);

View File

@ -1,7 +1,6 @@
//! By convention, main.zig is where your main function lives in the case that
//! you are building an executable. If you are making a library, the convention
//! is to delete this file and start with root.zig instead.
const std = @import("std");
pub fn main() !void {
// Prints to stderr (it's a shortcut based on `std.io.getStdErr()`)
@ -26,6 +25,10 @@ test "simple test" {
try std.testing.expectEqual(@as(i32, 42), list.pop());
}
test "use other module" {
try std.testing.expectEqual(@as(i32, 150), lib.add(100, 50));
}
test "fuzz example" {
const global = struct {
fn testOne(input: []const u8) anyerror!void {
@ -35,3 +38,8 @@ test "fuzz example" {
};
try std.testing.fuzz(global.testOne, .{});
}
const std = @import("std");
/// This imports the separate module containing `root.zig`. Take a look in `build.zig` for details.
const lib = @import("$_lib");

View File

@ -4,7 +4,7 @@
const std = @import("std");
const testing = std.testing;
export fn add(a: i32, b: i32) i32 {
pub export fn add(a: i32, b: i32) i32 {
return a + b;
}

View File

@ -81,9 +81,6 @@ enable_wine: bool = false,
/// that contains the path `aarch64-linux-gnu/lib/ld-linux-aarch64.so.1`.
glibc_runtimes_dir: ?[]const u8 = null,
/// Deprecated. Use `b.graph.host`.
host: ResolvedTarget,
dep_prefix: []const u8 = "",
modules: std.StringArrayHashMap(*Module),
@ -301,7 +298,6 @@ pub fn create(
},
.install_path = undefined,
.args = null,
.host = graph.host,
.modules = .init(arena),
.named_writefiles = .init(arena),
.named_lazy_paths = .init(arena),
@ -393,7 +389,6 @@ fn createChildOnly(
.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 }),
.modules = .init(allocator),
.named_writefiles = .init(allocator),
@ -692,24 +687,9 @@ pub fn addOptions(b: *Build) *Step.Options {
pub const ExecutableOptions = struct {
name: []const u8,
/// If you want the executable to run on the same computer as the one
/// building the package, pass the `host` field of the package's `Build`
/// instance.
target: ResolvedTarget,
root_source_file: ?LazyPath = null,
version: ?std.SemanticVersion = null,
optimize: std.builtin.OptimizeMode = .Debug,
code_model: std.builtin.CodeModel = .default,
linkage: ?std.builtin.LinkMode = null,
max_rss: usize = 0,
link_libc: ?bool = null,
single_threaded: ?bool = null,
pic: ?bool = null,
strip: ?bool = null,
unwind_tables: ?std.builtin.UnwindTables = null,
omit_frame_pointer: ?bool = null,
sanitize_thread: ?bool = null,
error_tracing: ?bool = null,
use_llvm: ?bool = null,
use_lld: ?bool = null,
zig_lib_dir: ?LazyPath = null,
@ -719,14 +699,47 @@ pub const ExecutableOptions = struct {
/// Can be set regardless of target. The `.manifest` file will be ignored
/// if the target object format does not support embedded manifests.
win32_manifest: ?LazyPath = null,
/// Prefer populating this field (using e.g. `createModule`) instead of populating
/// the following fields (`root_source_file` etc). In a future release, those fields
/// will be removed, and this field will become non-optional.
root_module: ?*Module = null,
/// Deprecated; prefer populating `root_module`.
root_source_file: ?LazyPath = null,
/// Deprecated; prefer populating `root_module`.
target: ?ResolvedTarget = null,
/// Deprecated; prefer populating `root_module`.
optimize: std.builtin.OptimizeMode = .Debug,
/// Deprecated; prefer populating `root_module`.
code_model: std.builtin.CodeModel = .default,
/// Deprecated; prefer populating `root_module`.
link_libc: ?bool = null,
/// Deprecated; prefer populating `root_module`.
single_threaded: ?bool = null,
/// Deprecated; prefer populating `root_module`.
pic: ?bool = null,
/// Deprecated; prefer populating `root_module`.
strip: ?bool = null,
/// Deprecated; prefer populating `root_module`.
unwind_tables: ?std.builtin.UnwindTables = null,
/// Deprecated; prefer populating `root_module`.
omit_frame_pointer: ?bool = null,
/// Deprecated; prefer populating `root_module`.
sanitize_thread: ?bool = null,
/// Deprecated; prefer populating `root_module`.
error_tracing: ?bool = null,
};
pub fn addExecutable(b: *Build, options: ExecutableOptions) *Step.Compile {
return Step.Compile.create(b, .{
if (options.root_module != null and options.target != null) {
@panic("`root_module` and `target` cannot both be populated");
}
return .create(b, .{
.name = options.name,
.root_module = .{
.root_module = options.root_module orelse b.createModule(.{
.root_source_file = options.root_source_file,
.target = options.target,
.target = options.target orelse @panic("`root_module` and `target` cannot both be null"),
.optimize = options.optimize,
.link_libc = options.link_libc,
.single_threaded = options.single_threaded,
@ -737,7 +750,7 @@ pub fn addExecutable(b: *Build, options: ExecutableOptions) *Step.Compile {
.sanitize_thread = options.sanitize_thread,
.error_tracing = options.error_tracing,
.code_model = options.code_model,
},
}),
.version = options.version,
.kind = .exe,
.linkage = options.linkage,
@ -751,32 +764,51 @@ pub fn addExecutable(b: *Build, options: ExecutableOptions) *Step.Compile {
pub const ObjectOptions = struct {
name: []const u8,
root_source_file: ?LazyPath = null,
/// To choose the same computer as the one building the package, pass the
/// `host` field of the package's `Build` instance.
target: ResolvedTarget,
code_model: std.builtin.CodeModel = .default,
optimize: std.builtin.OptimizeMode,
max_rss: usize = 0,
link_libc: ?bool = null,
single_threaded: ?bool = null,
pic: ?bool = null,
strip: ?bool = null,
unwind_tables: ?std.builtin.UnwindTables = null,
omit_frame_pointer: ?bool = null,
sanitize_thread: ?bool = null,
error_tracing: ?bool = null,
use_llvm: ?bool = null,
use_lld: ?bool = null,
zig_lib_dir: ?LazyPath = null,
/// Prefer populating this field (using e.g. `createModule`) instead of populating
/// the following fields (`root_source_file` etc). In a future release, those fields
/// will be removed, and this field will become non-optional.
root_module: ?*Module = null,
/// Deprecated; prefer populating `root_module`.
root_source_file: ?LazyPath = null,
/// Deprecated; prefer populating `root_module`.
target: ?ResolvedTarget = null,
/// Deprecated; prefer populating `root_module`.
optimize: std.builtin.OptimizeMode = .Debug,
/// Deprecated; prefer populating `root_module`.
code_model: std.builtin.CodeModel = .default,
/// Deprecated; prefer populating `root_module`.
link_libc: ?bool = null,
/// Deprecated; prefer populating `root_module`.
single_threaded: ?bool = null,
/// Deprecated; prefer populating `root_module`.
pic: ?bool = null,
/// Deprecated; prefer populating `root_module`.
strip: ?bool = null,
/// Deprecated; prefer populating `root_module`.
unwind_tables: ?std.builtin.UnwindTables = null,
/// Deprecated; prefer populating `root_module`.
omit_frame_pointer: ?bool = null,
/// Deprecated; prefer populating `root_module`.
sanitize_thread: ?bool = null,
/// Deprecated; prefer populating `root_module`.
error_tracing: ?bool = null,
};
pub fn addObject(b: *Build, options: ObjectOptions) *Step.Compile {
return Step.Compile.create(b, .{
if (options.root_module != null and options.target != null) {
@panic("`root_module` and `target` cannot both be populated");
}
return .create(b, .{
.name = options.name,
.root_module = .{
.root_module = options.root_module orelse b.createModule(.{
.root_source_file = options.root_source_file,
.target = options.target,
.target = options.target orelse @panic("`root_module` and `target` cannot both be null"),
.optimize = options.optimize,
.link_libc = options.link_libc,
.single_threaded = options.single_threaded,
@ -787,7 +819,7 @@ pub fn addObject(b: *Build, options: ObjectOptions) *Step.Compile {
.sanitize_thread = options.sanitize_thread,
.error_tracing = options.error_tracing,
.code_model = options.code_model,
},
}),
.kind = .obj,
.max_rss = options.max_rss,
.use_llvm = options.use_llvm,
@ -798,22 +830,8 @@ pub fn addObject(b: *Build, options: ObjectOptions) *Step.Compile {
pub const SharedLibraryOptions = struct {
name: []const u8,
/// To choose the same computer as the one building the package, pass the
/// `host` field of the package's `Build` instance.
target: ResolvedTarget,
optimize: std.builtin.OptimizeMode,
code_model: std.builtin.CodeModel = .default,
root_source_file: ?LazyPath = null,
version: ?std.SemanticVersion = null,
max_rss: usize = 0,
link_libc: ?bool = null,
single_threaded: ?bool = null,
pic: ?bool = null,
strip: ?bool = null,
unwind_tables: ?std.builtin.UnwindTables = null,
omit_frame_pointer: ?bool = null,
sanitize_thread: ?bool = null,
error_tracing: ?bool = null,
use_llvm: ?bool = null,
use_lld: ?bool = null,
zig_lib_dir: ?LazyPath = null,
@ -823,13 +841,46 @@ pub const SharedLibraryOptions = struct {
/// Can be set regardless of target. The `.manifest` file will be ignored
/// if the target object format does not support embedded manifests.
win32_manifest: ?LazyPath = null,
/// Prefer populating this field (using e.g. `createModule`) instead of populating
/// the following fields (`root_source_file` etc). In a future release, those fields
/// will be removed, and this field will become non-optional.
root_module: ?*Module = null,
/// Deprecated; prefer populating `root_module`.
root_source_file: ?LazyPath = null,
/// Deprecated; prefer populating `root_module`.
target: ?ResolvedTarget = null,
/// Deprecated; prefer populating `root_module`.
optimize: std.builtin.OptimizeMode = .Debug,
/// Deprecated; prefer populating `root_module`.
code_model: std.builtin.CodeModel = .default,
/// Deprecated; prefer populating `root_module`.
link_libc: ?bool = null,
/// Deprecated; prefer populating `root_module`.
single_threaded: ?bool = null,
/// Deprecated; prefer populating `root_module`.
pic: ?bool = null,
/// Deprecated; prefer populating `root_module`.
strip: ?bool = null,
/// Deprecated; prefer populating `root_module`.
unwind_tables: ?std.builtin.UnwindTables = null,
/// Deprecated; prefer populating `root_module`.
omit_frame_pointer: ?bool = null,
/// Deprecated; prefer populating `root_module`.
sanitize_thread: ?bool = null,
/// Deprecated; prefer populating `root_module`.
error_tracing: ?bool = null,
};
pub fn addSharedLibrary(b: *Build, options: SharedLibraryOptions) *Step.Compile {
return Step.Compile.create(b, .{
if (options.root_module != null and options.target != null) {
@panic("`root_module` and `target` cannot both be populated");
}
return .create(b, .{
.name = options.name,
.root_module = .{
.target = options.target,
.root_module = options.root_module orelse b.createModule(.{
.target = options.target orelse @panic("`root_module` and `target` cannot both be null"),
.optimize = options.optimize,
.root_source_file = options.root_source_file,
.link_libc = options.link_libc,
@ -841,7 +892,7 @@ pub fn addSharedLibrary(b: *Build, options: SharedLibraryOptions) *Step.Compile
.sanitize_thread = options.sanitize_thread,
.error_tracing = options.error_tracing,
.code_model = options.code_model,
},
}),
.kind = .lib,
.linkage = .dynamic,
.version = options.version,
@ -855,32 +906,51 @@ pub fn addSharedLibrary(b: *Build, options: SharedLibraryOptions) *Step.Compile
pub const StaticLibraryOptions = struct {
name: []const u8,
root_source_file: ?LazyPath = null,
/// To choose the same computer as the one building the package, pass the
/// `host` field of the package's `Build` instance.
target: ResolvedTarget,
optimize: std.builtin.OptimizeMode,
code_model: std.builtin.CodeModel = .default,
version: ?std.SemanticVersion = null,
max_rss: usize = 0,
link_libc: ?bool = null,
single_threaded: ?bool = null,
pic: ?bool = null,
strip: ?bool = null,
unwind_tables: ?std.builtin.UnwindTables = null,
omit_frame_pointer: ?bool = null,
sanitize_thread: ?bool = null,
error_tracing: ?bool = null,
use_llvm: ?bool = null,
use_lld: ?bool = null,
zig_lib_dir: ?LazyPath = null,
/// Prefer populating this field (using e.g. `createModule`) instead of populating
/// the following fields (`root_source_file` etc). In a future release, those fields
/// will be removed, and this field will become non-optional.
root_module: ?*Module = null,
/// Deprecated; prefer populating `root_module`.
root_source_file: ?LazyPath = null,
/// Deprecated; prefer populating `root_module`.
target: ?ResolvedTarget = null,
/// Deprecated; prefer populating `root_module`.
optimize: std.builtin.OptimizeMode = .Debug,
/// Deprecated; prefer populating `root_module`.
code_model: std.builtin.CodeModel = .default,
/// Deprecated; prefer populating `root_module`.
link_libc: ?bool = null,
/// Deprecated; prefer populating `root_module`.
single_threaded: ?bool = null,
/// Deprecated; prefer populating `root_module`.
pic: ?bool = null,
/// Deprecated; prefer populating `root_module`.
strip: ?bool = null,
/// Deprecated; prefer populating `root_module`.
unwind_tables: ?std.builtin.UnwindTables = null,
/// Deprecated; prefer populating `root_module`.
omit_frame_pointer: ?bool = null,
/// Deprecated; prefer populating `root_module`.
sanitize_thread: ?bool = null,
/// Deprecated; prefer populating `root_module`.
error_tracing: ?bool = null,
};
pub fn addStaticLibrary(b: *Build, options: StaticLibraryOptions) *Step.Compile {
return Step.Compile.create(b, .{
if (options.root_module != null and options.target != null) {
@panic("`root_module` and `target` cannot both be populated");
}
return .create(b, .{
.name = options.name,
.root_module = .{
.target = options.target,
.root_module = options.root_module orelse b.createModule(.{
.target = options.target orelse @panic("`root_module` and `target` cannot both be null"),
.optimize = options.optimize,
.root_source_file = options.root_source_file,
.link_libc = options.link_libc,
@ -892,7 +962,7 @@ pub fn addStaticLibrary(b: *Build, options: StaticLibraryOptions) *Step.Compile
.sanitize_thread = options.sanitize_thread,
.error_tracing = options.error_tracing,
.code_model = options.code_model,
},
}),
.kind = .lib,
.linkage = .static,
.version = options.version,
@ -905,27 +975,46 @@ pub fn addStaticLibrary(b: *Build, options: StaticLibraryOptions) *Step.Compile
pub const TestOptions = struct {
name: []const u8 = "test",
root_source_file: LazyPath,
target: ?ResolvedTarget = null,
optimize: std.builtin.OptimizeMode = .Debug,
version: ?std.SemanticVersion = null,
max_rss: usize = 0,
/// deprecated: use `.filters = &.{filter}` instead of `.filter = filter`.
/// Deprecated; use `.filters = &.{filter}` instead of `.filter = filter`.
filter: ?[]const u8 = null,
filters: []const []const u8 = &.{},
test_runner: ?LazyPath = null,
link_libc: ?bool = null,
link_libcpp: ?bool = null,
single_threaded: ?bool = null,
pic: ?bool = null,
strip: ?bool = null,
unwind_tables: ?std.builtin.UnwindTables = null,
omit_frame_pointer: ?bool = null,
sanitize_thread: ?bool = null,
error_tracing: ?bool = null,
use_llvm: ?bool = null,
use_lld: ?bool = null,
zig_lib_dir: ?LazyPath = null,
/// Prefer populating this field (using e.g. `createModule`) instead of populating
/// the following fields (`root_source_file` etc). In a future release, those fields
/// will be removed, and this field will become non-optional.
root_module: ?*Module = null,
/// Deprecated; prefer populating `root_module`.
root_source_file: ?LazyPath = null,
/// Deprecated; prefer populating `root_module`.
target: ?ResolvedTarget = null,
/// Deprecated; prefer populating `root_module`.
optimize: std.builtin.OptimizeMode = .Debug,
/// Deprecated; prefer populating `root_module`.
version: ?std.SemanticVersion = null,
/// Deprecated; prefer populating `root_module`.
link_libc: ?bool = null,
/// Deprecated; prefer populating `root_module`.
link_libcpp: ?bool = null,
/// Deprecated; prefer populating `root_module`.
single_threaded: ?bool = null,
/// Deprecated; prefer populating `root_module`.
pic: ?bool = null,
/// Deprecated; prefer populating `root_module`.
strip: ?bool = null,
/// Deprecated; prefer populating `root_module`.
unwind_tables: ?std.builtin.UnwindTables = null,
/// Deprecated; prefer populating `root_module`.
omit_frame_pointer: ?bool = null,
/// Deprecated; prefer populating `root_module`.
sanitize_thread: ?bool = null,
/// Deprecated; prefer populating `root_module`.
error_tracing: ?bool = null,
};
/// Creates an executable containing unit tests.
@ -937,11 +1026,14 @@ pub const TestOptions = struct {
/// two steps are separated because they are independently configured and
/// cached.
pub fn addTest(b: *Build, options: TestOptions) *Step.Compile {
return Step.Compile.create(b, .{
if (options.root_module != null and options.root_source_file != null) {
@panic("`root_module` and `root_source_file` cannot both be populated");
}
return .create(b, .{
.name = options.name,
.kind = .@"test",
.root_module = .{
.root_source_file = options.root_source_file,
.root_module = options.root_module orelse b.createModule(.{
.root_source_file = options.root_source_file orelse @panic("`root_module` and `root_source_file` cannot both be null"),
.target = options.target orelse b.graph.host,
.optimize = options.optimize,
.link_libc = options.link_libc,
@ -953,7 +1045,7 @@ pub fn addTest(b: *Build, options: TestOptions) *Step.Compile {
.omit_frame_pointer = options.omit_frame_pointer,
.sanitize_thread = options.sanitize_thread,
.error_tracing = options.error_tracing,
},
}),
.max_rss = options.max_rss,
.filters = if (options.filter != null and options.filters.len > 0) filters: {
const filters = b.allocator.alloc([]const u8, 1 + options.filters.len) catch @panic("OOM");
@ -979,19 +1071,20 @@ pub const AssemblyOptions = struct {
zig_lib_dir: ?LazyPath = null,
};
/// Deprecated; prefer using `addObject` where the `root_module` has an empty
/// `root_source_file` and contains an assembly file via `Module.addAssemblyFile`.
pub fn addAssembly(b: *Build, options: AssemblyOptions) *Step.Compile {
const obj_step = Step.Compile.create(b, .{
const root_module = b.createModule(.{
.target = options.target,
.optimize = options.optimize,
});
root_module.addAssemblyFile(options.source_file);
return b.addObject(.{
.name = options.name,
.kind = .obj,
.root_module = .{
.target = options.target,
.optimize = options.optimize,
},
.max_rss = options.max_rss,
.zig_lib_dir = options.zig_lib_dir,
.root_module = root_module,
});
obj_step.addAssemblyFile(options.source_file);
return obj_step;
}
/// This function creates a module and adds it to the package's module set, making

View File

@ -1,9 +1,5 @@
/// The one responsible for creating this module.
owner: *std.Build,
/// Tracks the set of steps that depend on this `Module`. This ensures that
/// when making this `Module` depend on other `Module` objects and `Step`
/// objects, respective `Step` dependencies can be added.
depending_steps: std.AutoArrayHashMapUnmanaged(*Step.Compile, void),
root_source_file: ?LazyPath,
/// The modules that are mapped into this module's import table.
/// Use `addImport` rather than modifying this field directly in order to
@ -41,6 +37,10 @@ link_libcpp: ?bool,
/// Symbols to be exported when compiling to WebAssembly.
export_symbol_names: []const []const u8 = &.{},
/// Caches the result of `getGraph` when called multiple times.
/// Use `getGraph` instead of accessing this field directly.
cached_graph: Graph = .{ .modules = &.{}, .names = &.{} },
pub const RPath = union(enum) {
lazy_path: LazyPath,
special: []const u8,
@ -242,59 +242,61 @@ pub const Import = struct {
module: *Module,
};
pub fn init(m: *Module, owner: *std.Build, options: CreateOptions, compile: ?*Step.Compile) void {
pub fn init(
m: *Module,
owner: *std.Build,
value: union(enum) { options: CreateOptions, existing: *const Module },
) void {
const allocator = owner.allocator;
m.* = .{
.owner = owner,
.depending_steps = .{},
.root_source_file = if (options.root_source_file) |lp| lp.dupe(owner) else null,
.import_table = .{},
.resolved_target = options.target,
.optimize = options.optimize,
.link_libc = options.link_libc,
.link_libcpp = options.link_libcpp,
.dwarf_format = options.dwarf_format,
.c_macros = .{},
.include_dirs = .{},
.lib_paths = .{},
.rpaths = .{},
.frameworks = .{},
.link_objects = .{},
.strip = options.strip,
.unwind_tables = options.unwind_tables,
.single_threaded = options.single_threaded,
.stack_protector = options.stack_protector,
.stack_check = options.stack_check,
.sanitize_c = options.sanitize_c,
.sanitize_thread = options.sanitize_thread,
.fuzz = options.fuzz,
.code_model = options.code_model,
.valgrind = options.valgrind,
.pic = options.pic,
.red_zone = options.red_zone,
.omit_frame_pointer = options.omit_frame_pointer,
.error_tracing = options.error_tracing,
.export_symbol_names = &.{},
};
switch (value) {
.options => |options| {
m.* = .{
.owner = owner,
.root_source_file = if (options.root_source_file) |lp| lp.dupe(owner) else null,
.import_table = .{},
.resolved_target = options.target,
.optimize = options.optimize,
.link_libc = options.link_libc,
.link_libcpp = options.link_libcpp,
.dwarf_format = options.dwarf_format,
.c_macros = .{},
.include_dirs = .{},
.lib_paths = .{},
.rpaths = .{},
.frameworks = .{},
.link_objects = .{},
.strip = options.strip,
.unwind_tables = options.unwind_tables,
.single_threaded = options.single_threaded,
.stack_protector = options.stack_protector,
.stack_check = options.stack_check,
.sanitize_c = options.sanitize_c,
.sanitize_thread = options.sanitize_thread,
.fuzz = options.fuzz,
.code_model = options.code_model,
.valgrind = options.valgrind,
.pic = options.pic,
.red_zone = options.red_zone,
.omit_frame_pointer = options.omit_frame_pointer,
.error_tracing = options.error_tracing,
.export_symbol_names = &.{},
};
m.import_table.ensureUnusedCapacity(allocator, options.imports.len) catch @panic("OOM");
for (options.imports) |dep| {
m.import_table.putAssumeCapacity(dep.name, dep.module);
m.import_table.ensureUnusedCapacity(allocator, options.imports.len) catch @panic("OOM");
for (options.imports) |dep| {
m.import_table.putAssumeCapacity(dep.name, dep.module);
}
},
.existing => |existing| {
m.* = existing.*;
},
}
if (compile) |c| {
m.depending_steps.put(allocator, c, {}) catch @panic("OOM");
}
// This logic accesses `depending_steps` which was just modified above.
var it = m.iterateDependencies(null, false);
while (it.next()) |item| addShallowDependencies(m, item.module);
}
pub fn create(owner: *std.Build, options: CreateOptions) *Module {
const m = owner.allocator.create(Module) catch @panic("OOM");
m.init(owner, options, null);
m.init(owner, .{ .options = options });
return m;
}
@ -302,69 +304,6 @@ pub fn create(owner: *std.Build, options: CreateOptions) *Module {
pub fn addImport(m: *Module, name: []const u8, module: *Module) void {
const b = m.owner;
m.import_table.put(b.allocator, b.dupe(name), module) catch @panic("OOM");
var it = module.iterateDependencies(null, false);
while (it.next()) |item| addShallowDependencies(m, item.module);
}
/// Creates step dependencies and updates `depending_steps` of `dependee` so that
/// subsequent calls to `addImport` on `dependee` will additionally create step
/// dependencies on `m`'s `depending_steps`.
fn addShallowDependencies(m: *Module, dependee: *Module) void {
if (dependee.root_source_file) |lazy_path| addLazyPathDependencies(m, dependee, lazy_path);
for (dependee.lib_paths.items) |lib_path| addLazyPathDependencies(m, dependee, lib_path);
for (dependee.rpaths.items) |rpath| switch (rpath) {
.lazy_path => |lp| addLazyPathDependencies(m, dependee, lp),
.special => {},
};
for (dependee.link_objects.items) |link_object| switch (link_object) {
.other_step => |compile| {
addStepDependencies(m, dependee, &compile.step);
addLazyPathDependenciesOnly(m, compile.getEmittedIncludeTree());
},
.static_path,
.assembly_file,
=> |lp| addLazyPathDependencies(m, dependee, lp),
.c_source_file => |x| addLazyPathDependencies(m, dependee, x.file),
.win32_resource_file => |x| addLazyPathDependencies(m, dependee, x.file),
.c_source_files,
.system_lib,
=> {},
};
}
fn addLazyPathDependencies(m: *Module, module: *Module, lazy_path: LazyPath) void {
addLazyPathDependenciesOnly(m, lazy_path);
if (m != module) {
for (m.depending_steps.keys()) |compile| {
module.depending_steps.put(m.owner.allocator, compile, {}) catch @panic("OOM");
}
}
}
fn addLazyPathDependenciesOnly(m: *Module, lazy_path: LazyPath) void {
for (m.depending_steps.keys()) |compile| {
lazy_path.addStepDependencies(&compile.step);
}
}
fn addStepDependencies(m: *Module, module: *Module, dependee: *Step) void {
addStepDependenciesOnly(m, dependee);
if (m != module) {
for (m.depending_steps.keys()) |compile| {
module.depending_steps.put(m.owner.allocator, compile, {}) catch @panic("OOM");
}
}
}
fn addStepDependenciesOnly(m: *Module, dependee: *Step) void {
for (m.depending_steps.keys()) |compile| {
compile.step.dependOn(dependee);
}
}
/// Creates a new module and adds it to be used with `@import`.
@ -380,91 +319,6 @@ pub fn addOptions(m: *Module, module_name: []const u8, options: *Step.Options) v
addImport(m, module_name, options.createModule());
}
pub const DependencyIterator = struct {
allocator: std.mem.Allocator,
index: usize,
set: std.AutoArrayHashMapUnmanaged(Key, []const u8),
chase_dyn_libs: bool,
pub const Key = struct {
/// The compilation that contains the `Module`. Note that a `Module` might be
/// used by more than one compilation.
compile: ?*Step.Compile,
module: *Module,
};
pub const Item = struct {
/// The compilation that contains the `Module`. Note that a `Module` might be
/// used by more than one compilation.
compile: ?*Step.Compile,
module: *Module,
name: []const u8,
};
pub fn deinit(it: *DependencyIterator) void {
it.set.deinit(it.allocator);
it.* = undefined;
}
pub fn next(it: *DependencyIterator) ?Item {
if (it.index >= it.set.count()) {
it.set.clearAndFree(it.allocator);
return null;
}
const key = it.set.keys()[it.index];
const name = it.set.values()[it.index];
it.index += 1;
const module = key.module;
it.set.ensureUnusedCapacity(it.allocator, module.import_table.count()) catch
@panic("OOM");
for (module.import_table.keys(), module.import_table.values()) |dep_name, dep| {
it.set.putAssumeCapacity(.{
.module = dep,
.compile = key.compile,
}, dep_name);
}
if (key.compile != null) {
for (module.link_objects.items) |link_object| switch (link_object) {
.other_step => |compile| {
if (!it.chase_dyn_libs and compile.isDynamicLibrary()) continue;
it.set.put(it.allocator, .{
.module = &compile.root_module,
.compile = compile,
}, "root") catch @panic("OOM");
},
else => {},
};
}
return .{
.compile = key.compile,
.module = key.module,
.name = name,
};
}
};
pub fn iterateDependencies(
m: *Module,
chase_steps: ?*Step.Compile,
chase_dyn_libs: bool,
) DependencyIterator {
var it: DependencyIterator = .{
.allocator = m.owner.allocator,
.index = 0,
.set = .{},
.chase_dyn_libs = chase_dyn_libs,
};
it.set.ensureUnusedCapacity(m.owner.allocator, m.import_table.count() + 1) catch @panic("OOM");
it.set.putAssumeCapacity(.{
.module = m,
.compile = chase_steps,
}, "root");
return it;
}
pub const LinkSystemLibraryOptions = struct {
/// Causes dynamic libraries to be linked regardless of whether they are
/// actually depended on. When false, dynamic libraries with no referenced
@ -547,7 +401,6 @@ pub fn addCSourceFiles(m: *Module, options: AddCSourceFilesOptions) void {
.flags = b.dupeStrings(options.flags),
};
m.link_objects.append(allocator, .{ .c_source_files = c_source_files }) catch @panic("OOM");
addLazyPathDependenciesOnly(m, c_source_files.root);
}
pub fn addCSourceFile(m: *Module, source: CSourceFile) void {
@ -556,7 +409,6 @@ pub fn addCSourceFile(m: *Module, source: CSourceFile) void {
const c_source_file = allocator.create(CSourceFile) catch @panic("OOM");
c_source_file.* = source.dupe(b);
m.link_objects.append(allocator, .{ .c_source_file = c_source_file }) catch @panic("OOM");
addLazyPathDependenciesOnly(m, source.file);
}
/// Resource files must have the extension `.rc`.
@ -573,22 +425,16 @@ pub fn addWin32ResourceFile(m: *Module, source: RcSourceFile) void {
const rc_source_file = allocator.create(RcSourceFile) catch @panic("OOM");
rc_source_file.* = source.dupe(b);
m.link_objects.append(allocator, .{ .win32_resource_file = rc_source_file }) catch @panic("OOM");
addLazyPathDependenciesOnly(m, source.file);
for (source.include_paths) |include_path| {
addLazyPathDependenciesOnly(m, include_path);
}
}
pub fn addAssemblyFile(m: *Module, source: LazyPath) void {
const b = m.owner;
m.link_objects.append(b.allocator, .{ .assembly_file = source.dupe(b) }) catch @panic("OOM");
addLazyPathDependenciesOnly(m, source);
}
pub fn addObjectFile(m: *Module, object: LazyPath) void {
const b = m.owner;
m.link_objects.append(b.allocator, .{ .static_path = object.dupe(b) }) catch @panic("OOM");
addLazyPathDependenciesOnly(m, object);
}
pub fn addObject(m: *Module, object: *Step.Compile) void {
@ -604,51 +450,43 @@ pub fn linkLibrary(m: *Module, library: *Step.Compile) void {
pub fn addAfterIncludePath(m: *Module, lazy_path: LazyPath) void {
const b = m.owner;
m.include_dirs.append(b.allocator, .{ .path_after = lazy_path.dupe(b) }) catch @panic("OOM");
addLazyPathDependenciesOnly(m, lazy_path);
}
pub fn addSystemIncludePath(m: *Module, lazy_path: LazyPath) void {
const b = m.owner;
m.include_dirs.append(b.allocator, .{ .path_system = lazy_path.dupe(b) }) catch @panic("OOM");
addLazyPathDependenciesOnly(m, lazy_path);
}
pub fn addIncludePath(m: *Module, lazy_path: LazyPath) void {
const b = m.owner;
m.include_dirs.append(b.allocator, .{ .path = lazy_path.dupe(b) }) catch @panic("OOM");
addLazyPathDependenciesOnly(m, lazy_path);
}
pub fn addConfigHeader(m: *Module, config_header: *Step.ConfigHeader) void {
const allocator = m.owner.allocator;
m.include_dirs.append(allocator, .{ .config_header_step = config_header }) catch @panic("OOM");
addStepDependenciesOnly(m, &config_header.step);
}
pub fn addSystemFrameworkPath(m: *Module, directory_path: LazyPath) void {
const b = m.owner;
m.include_dirs.append(b.allocator, .{ .framework_path_system = directory_path.dupe(b) }) catch
@panic("OOM");
addLazyPathDependenciesOnly(m, directory_path);
}
pub fn addFrameworkPath(m: *Module, directory_path: LazyPath) void {
const b = m.owner;
m.include_dirs.append(b.allocator, .{ .framework_path = directory_path.dupe(b) }) catch
@panic("OOM");
addLazyPathDependenciesOnly(m, directory_path);
}
pub fn addLibraryPath(m: *Module, directory_path: LazyPath) void {
const b = m.owner;
m.lib_paths.append(b.allocator, directory_path.dupe(b)) catch @panic("OOM");
addLazyPathDependenciesOnly(m, directory_path);
}
pub fn addRPath(m: *Module, directory_path: LazyPath) void {
const b = m.owner;
m.rpaths.append(b.allocator, .{ .lazy_path = directory_path.dupe(b) }) catch @panic("OOM");
addLazyPathDependenciesOnly(m, directory_path);
}
pub fn addRPathSpecial(m: *Module, bytes: []const u8) void {
@ -772,7 +610,6 @@ fn addFlag(
fn linkLibraryOrObject(m: *Module, other: *Step.Compile) void {
const allocator = m.owner.allocator;
_ = other.getEmittedBin(); // Indicate there is a dependency on the outputted binary.
addStepDependenciesOnly(m, &other.step);
if (other.rootModuleTarget().os.tag == .windows and other.isDynamicLibrary()) {
_ = other.getEmittedImplib(); // Indicate dependency on the outputted implib.
@ -780,8 +617,6 @@ fn linkLibraryOrObject(m: *Module, other: *Step.Compile) void {
m.link_objects.append(allocator, .{ .other_step = other }) catch @panic("OOM");
m.include_dirs.append(allocator, .{ .other_step = other }) catch @panic("OOM");
addLazyPathDependenciesOnly(m, other.getEmittedIncludeTree());
}
fn requireKnownTarget(m: *Module) std.Target {
@ -790,6 +625,46 @@ fn requireKnownTarget(m: *Module) std.Target {
return resolved_target.result;
}
/// Elements of `modules` and `names` are matched one-to-one.
pub const Graph = struct {
modules: []const *Module,
names: []const []const u8,
};
/// Intended to be used during the make phase only.
///
/// Given that `root` is the root `Module` of a compilation, return all `Module`s
/// in the module graph, including `root` itself. `root` is guaranteed to be the
/// first module in the returned slice.
pub fn getGraph(root: *Module) Graph {
if (root.cached_graph.modules.len != 0) {
return root.cached_graph;
}
const arena = root.owner.graph.arena;
var modules: std.AutoArrayHashMapUnmanaged(*std.Build.Module, []const u8) = .empty;
var next_idx: usize = 0;
modules.putNoClobber(arena, root, "root") catch @panic("OOM");
while (next_idx < modules.count()) {
const mod = modules.keys()[next_idx];
next_idx += 1;
modules.ensureUnusedCapacity(arena, mod.import_table.count()) catch @panic("OOM");
for (mod.import_table.keys(), mod.import_table.values()) |import_name, other_mod| {
modules.putAssumeCapacity(other_mod, import_name);
}
}
const result: Graph = .{
.modules = modules.keys(),
.names = modules.values(),
};
root.cached_graph = result;
return result;
}
const Module = @This();
const std = @import("std");
const assert = std.debug.assert;

View File

@ -22,7 +22,7 @@ const Path = std.Build.Cache.Path;
pub const base_id: Step.Id = .compile;
step: Step,
root_module: Module,
root_module: *Module,
name: []const u8,
linker_script: ?LazyPath = null,
@ -262,7 +262,7 @@ pub const Entry = union(enum) {
pub const Options = struct {
name: []const u8,
root_module: Module.CreateOptions,
root_module: *Module,
kind: Kind,
linkage: ?std.builtin.LinkMode = null,
version: ?std.SemanticVersion = null,
@ -359,7 +359,8 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
else
owner.fmt("{s} ", .{name});
const resolved_target = options.root_module.target.?;
const resolved_target = options.root_module.resolved_target orelse
@panic("the root Module of a Compile step must be created with a known 'target' field");
const target = resolved_target.result;
const step_name = owner.fmt("{s} {s}{s} {s}", .{
@ -388,7 +389,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
const compile = owner.allocator.create(Compile) catch @panic("OOM");
compile.* = .{
.root_module = undefined,
.root_module = options.root_module,
.verbose_link = false,
.verbose_cc = false,
.linkage = options.linkage,
@ -432,8 +433,6 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
.zig_process = null,
};
compile.root_module.init(owner, options.root_module, compile);
if (options.zig_lib_dir) |lp| {
compile.zig_lib_dir = lp.dupe(compile.step.owner);
lp.addStepDependencies(&compile.step);
@ -583,9 +582,6 @@ pub fn checkObject(compile: *Compile) *Step.CheckObject {
return Step.CheckObject.create(compile.step.owner, compile.getEmittedBin(), compile.rootModuleTarget().ofmt);
}
/// deprecated: use `setLinkerScript`
pub const setLinkerScriptPath = setLinkerScript;
pub fn setLinkerScript(compile: *Compile, source: LazyPath) void {
const b = compile.step.owner;
compile.linker_script = source.dupe(b);
@ -609,16 +605,17 @@ pub fn dependsOnSystemLibrary(compile: *const Compile, name: []const u8) bool {
var is_linking_libc = false;
var is_linking_libcpp = false;
var dep_it = compile.root_module.iterateDependencies(compile, true);
while (dep_it.next()) |module| {
for (module.link_objects.items) |link_object| {
switch (link_object) {
.system_lib => |lib| if (mem.eql(u8, lib.name, name)) return true,
else => continue,
for (compile.getCompileDependencies(true)) |some_compile| {
for (some_compile.root_module.getGraph().modules) |mod| {
for (mod.link_objects.items) |lo| {
switch (lo) {
.system_lib => |lib| if (mem.eql(u8, lib.name, name)) return true,
else => {},
}
}
if (mod.link_libc) is_linking_libc = true;
if (mod.link_libcpp) is_linking_libcpp = true;
}
is_linking_libc = is_linking_libc or module.link_libc == true;
is_linking_libcpp = is_linking_libcpp or module.link_libcpp == true;
}
const target = compile.rootModuleTarget();
@ -675,11 +672,6 @@ pub fn linkLibCpp(compile: *Compile) void {
compile.root_module.link_libcpp = true;
}
/// Deprecated. Use `c.root_module.addCMacro`.
pub fn defineCMacro(c: *Compile, name: []const u8, value: ?[]const u8) void {
c.root_module.addCMacro(name, value orelse "1");
}
const PkgConfigResult = struct {
cflags: []const []const u8,
libs: []const []const u8,
@ -805,16 +797,6 @@ pub fn linkFramework(c: *Compile, name: []const u8) void {
c.root_module.linkFramework(name, .{});
}
/// Deprecated. Use `c.root_module.linkFramework`.
pub fn linkFrameworkNeeded(c: *Compile, name: []const u8) void {
c.root_module.linkFramework(name, .{ .needed = true });
}
/// Deprecated. Use `c.root_module.linkFramework`.
pub fn linkFrameworkWeak(c: *Compile, name: []const u8) void {
c.root_module.linkFramework(name, .{ .weak = true });
}
/// Handy when you have many C/C++ source files and want them all to have the same flags.
pub fn addCSourceFiles(compile: *Compile, options: Module.AddCSourceFilesOptions) void {
compile.root_module.addCSourceFiles(options);
@ -978,23 +960,22 @@ const CliNamedModules = struct {
.modules = .{},
.names = .{},
};
var dep_it = root_module.iterateDependencies(null, false);
const graph = root_module.getGraph();
{
const item = dep_it.next().?;
assert(root_module == item.module);
assert(graph.modules[0] == root_module);
try compile.modules.put(arena, root_module, {});
try compile.names.put(arena, "root", {});
}
while (dep_it.next()) |item| {
var name = item.name;
for (graph.modules[1..], graph.names[1..]) |mod, orig_name| {
var name = orig_name;
var n: usize = 0;
while (true) {
const gop = try compile.names.getOrPut(arena, name);
if (!gop.found_existing) {
try compile.modules.putNoClobber(arena, item.module, {});
try compile.modules.putNoClobber(arena, mod, {});
break;
}
name = try std.fmt.allocPrint(arena, "{s}{d}", .{ item.name, n });
name = try std.fmt.allocPrint(arena, "{s}{d}", .{ orig_name, n });
n += 1;
}
}
@ -1097,279 +1078,278 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
// emitted if there is nothing to link.
var total_linker_objects: usize = @intFromBool(compile.root_module.root_source_file != null);
{
// Fully recursive iteration including dynamic libraries to detect
// libc and libc++ linkage.
var dep_it = compile.root_module.iterateDependencies(compile, true);
while (dep_it.next()) |key| {
if (key.module.link_libc == true) compile.is_linking_libc = true;
if (key.module.link_libcpp == true) compile.is_linking_libcpp = true;
// Fully recursive iteration including dynamic libraries to detect
// libc and libc++ linkage.
for (compile.getCompileDependencies(true)) |some_compile| {
for (some_compile.root_module.getGraph().modules) |mod| {
if (mod.link_libc == true) compile.is_linking_libc = true;
if (mod.link_libcpp == true) compile.is_linking_libcpp = true;
}
}
var cli_named_modules = try CliNamedModules.init(arena, &compile.root_module);
var cli_named_modules = try CliNamedModules.init(arena, compile.root_module);
// For this loop, don't chase dynamic libraries because their link
// objects are already linked.
var dep_it = compile.root_module.iterateDependencies(compile, false);
for (compile.getCompileDependencies(false)) |dep_compile| {
for (dep_compile.root_module.getGraph().modules) |mod| {
// While walking transitive dependencies, if a given link object is
// already included in a library, it should not redundantly be
// placed on the linker line of the dependee.
const my_responsibility = dep_compile == compile;
const already_linked = !my_responsibility and dep_compile.isDynamicLibrary();
while (dep_it.next()) |dep| {
// While walking transitive dependencies, if a given link object is
// already included in a library, it should not redundantly be
// placed on the linker line of the dependee.
const my_responsibility = dep.compile.? == compile;
const already_linked = !my_responsibility and dep.compile.?.isDynamicLibrary();
// Inherit dependencies on darwin frameworks.
if (!already_linked) {
for (dep.module.frameworks.keys(), dep.module.frameworks.values()) |name, info| {
try frameworks.put(arena, name, info);
}
}
// Inherit dependencies on system libraries and static libraries.
for (dep.module.link_objects.items) |link_object| {
switch (link_object) {
.static_path => |static_path| {
if (my_responsibility) {
try zig_args.append(static_path.getPath2(dep.module.owner, step));
total_linker_objects += 1;
}
},
.system_lib => |system_lib| {
const system_lib_gop = try seen_system_libs.getOrPut(arena, system_lib.name);
if (system_lib_gop.found_existing) {
try zig_args.appendSlice(system_lib_gop.value_ptr.*);
continue;
} else {
system_lib_gop.value_ptr.* = &.{};
}
if (already_linked)
continue;
if ((system_lib.search_strategy != prev_search_strategy or
system_lib.preferred_link_mode != prev_preferred_link_mode) and
compile.linkage != .static)
{
switch (system_lib.search_strategy) {
.no_fallback => switch (system_lib.preferred_link_mode) {
.dynamic => try zig_args.append("-search_dylibs_only"),
.static => try zig_args.append("-search_static_only"),
},
.paths_first => switch (system_lib.preferred_link_mode) {
.dynamic => try zig_args.append("-search_paths_first"),
.static => try zig_args.append("-search_paths_first_static"),
},
.mode_first => switch (system_lib.preferred_link_mode) {
.dynamic => try zig_args.append("-search_dylibs_first"),
.static => try zig_args.append("-search_static_first"),
},
}
prev_search_strategy = system_lib.search_strategy;
prev_preferred_link_mode = system_lib.preferred_link_mode;
}
const prefix: []const u8 = prefix: {
if (system_lib.needed) break :prefix "-needed-l";
if (system_lib.weak) break :prefix "-weak-l";
break :prefix "-l";
};
switch (system_lib.use_pkg_config) {
.no => try zig_args.append(b.fmt("{s}{s}", .{ prefix, system_lib.name })),
.yes, .force => {
if (compile.runPkgConfig(system_lib.name)) |result| {
try zig_args.appendSlice(result.cflags);
try zig_args.appendSlice(result.libs);
try seen_system_libs.put(arena, system_lib.name, result.cflags);
} else |err| switch (err) {
error.PkgConfigInvalidOutput,
error.PkgConfigCrashed,
error.PkgConfigFailed,
error.PkgConfigNotInstalled,
error.PackageNotFound,
=> switch (system_lib.use_pkg_config) {
.yes => {
// pkg-config failed, so fall back to linking the library
// by name directly.
try zig_args.append(b.fmt("{s}{s}", .{
prefix,
system_lib.name,
}));
},
.force => {
panic("pkg-config failed for library {s}", .{system_lib.name});
},
.no => unreachable,
},
else => |e| return e,
}
},
}
},
.other_step => |other| {
switch (other.kind) {
.exe => return step.fail("cannot link with an executable build artifact", .{}),
.@"test" => return step.fail("cannot link with a test", .{}),
.obj => {
const included_in_lib_or_obj = !my_responsibility and
(dep.compile.?.kind == .lib or dep.compile.?.kind == .obj);
if (!already_linked and !included_in_lib_or_obj) {
try zig_args.append(other.getEmittedBin().getPath2(b, step));
total_linker_objects += 1;
}
},
.lib => l: {
const other_produces_implib = other.producesImplib();
const other_is_static = other_produces_implib or other.isStaticLibrary();
if (compile.isStaticLibrary() and other_is_static) {
// Avoid putting a static library inside a static library.
break :l;
}
// For DLLs, we must link against the implib.
// For everything else, we directly link
// against the library file.
const full_path_lib = if (other_produces_implib)
other.getGeneratedFilePath("generated_implib", &compile.step)
else
other.getGeneratedFilePath("generated_bin", &compile.step);
try zig_args.append(full_path_lib);
total_linker_objects += 1;
if (other.linkage == .dynamic and
compile.rootModuleTarget().os.tag != .windows)
{
if (fs.path.dirname(full_path_lib)) |dirname| {
try zig_args.append("-rpath");
try zig_args.append(dirname);
}
}
},
}
},
.assembly_file => |asm_file| l: {
if (!my_responsibility) break :l;
if (prev_has_cflags) {
try zig_args.append("-cflags");
try zig_args.append("--");
prev_has_cflags = false;
}
try zig_args.append(asm_file.getPath2(dep.module.owner, step));
total_linker_objects += 1;
},
.c_source_file => |c_source_file| l: {
if (!my_responsibility) break :l;
if (c_source_file.flags.len == 0) {
if (prev_has_cflags) {
try zig_args.append("-cflags");
try zig_args.append("--");
prev_has_cflags = false;
}
} else {
try zig_args.append("-cflags");
for (c_source_file.flags) |arg| {
try zig_args.append(arg);
}
try zig_args.append("--");
prev_has_cflags = true;
}
try zig_args.append(c_source_file.file.getPath2(dep.module.owner, step));
total_linker_objects += 1;
},
.c_source_files => |c_source_files| l: {
if (!my_responsibility) break :l;
if (c_source_files.flags.len == 0) {
if (prev_has_cflags) {
try zig_args.append("-cflags");
try zig_args.append("--");
prev_has_cflags = false;
}
} else {
try zig_args.append("-cflags");
for (c_source_files.flags) |flag| {
try zig_args.append(flag);
}
try zig_args.append("--");
prev_has_cflags = true;
}
const root_path = c_source_files.root.getPath2(dep.module.owner, step);
for (c_source_files.files) |file| {
try zig_args.append(b.pathJoin(&.{ root_path, file }));
}
total_linker_objects += c_source_files.files.len;
},
.win32_resource_file => |rc_source_file| l: {
if (!my_responsibility) break :l;
if (rc_source_file.flags.len == 0 and rc_source_file.include_paths.len == 0) {
if (prev_has_rcflags) {
try zig_args.append("-rcflags");
try zig_args.append("--");
prev_has_rcflags = false;
}
} else {
try zig_args.append("-rcflags");
for (rc_source_file.flags) |arg| {
try zig_args.append(arg);
}
for (rc_source_file.include_paths) |include_path| {
try zig_args.append("/I");
try zig_args.append(include_path.getPath2(dep.module.owner, step));
}
try zig_args.append("--");
prev_has_rcflags = true;
}
try zig_args.append(rc_source_file.file.getPath2(dep.module.owner, step));
total_linker_objects += 1;
},
}
}
// We need to emit the --mod argument here so that the above link objects
// have the correct parent module, but only if the module is part of
// this compilation.
if (!my_responsibility) continue;
if (cli_named_modules.modules.getIndex(dep.module)) |module_cli_index| {
const module_cli_name = cli_named_modules.names.keys()[module_cli_index];
try dep.module.appendZigProcessFlags(&zig_args, step);
// --dep arguments
try zig_args.ensureUnusedCapacity(dep.module.import_table.count() * 2);
for (dep.module.import_table.keys(), dep.module.import_table.values()) |name, import| {
const import_index = cli_named_modules.modules.getIndex(import).?;
const import_cli_name = cli_named_modules.names.keys()[import_index];
zig_args.appendAssumeCapacity("--dep");
if (std.mem.eql(u8, import_cli_name, name)) {
zig_args.appendAssumeCapacity(import_cli_name);
} else {
zig_args.appendAssumeCapacity(b.fmt("{s}={s}", .{ name, import_cli_name }));
// Inherit dependencies on darwin frameworks.
if (!already_linked) {
for (mod.frameworks.keys(), mod.frameworks.values()) |name, info| {
try frameworks.put(arena, name, info);
}
}
// When the CLI sees a -M argument, it determines whether it
// implies the existence of a Zig compilation unit based on
// whether there is a root source file. If there is no root
// source file, then this is not a zig compilation unit - it is
// perhaps a set of linker objects, or C source files instead.
// Linker objects are added to the CLI globally, while C source
// files must have a module parent.
if (dep.module.root_source_file) |lp| {
const src = lp.getPath2(dep.module.owner, step);
try zig_args.append(b.fmt("-M{s}={s}", .{ module_cli_name, src }));
} else if (moduleNeedsCliArg(dep.module)) {
try zig_args.append(b.fmt("-M{s}", .{module_cli_name}));
// Inherit dependencies on system libraries and static libraries.
for (mod.link_objects.items) |link_object| {
switch (link_object) {
.static_path => |static_path| {
if (my_responsibility) {
try zig_args.append(static_path.getPath2(mod.owner, step));
total_linker_objects += 1;
}
},
.system_lib => |system_lib| {
const system_lib_gop = try seen_system_libs.getOrPut(arena, system_lib.name);
if (system_lib_gop.found_existing) {
try zig_args.appendSlice(system_lib_gop.value_ptr.*);
continue;
} else {
system_lib_gop.value_ptr.* = &.{};
}
if (already_linked)
continue;
if ((system_lib.search_strategy != prev_search_strategy or
system_lib.preferred_link_mode != prev_preferred_link_mode) and
compile.linkage != .static)
{
switch (system_lib.search_strategy) {
.no_fallback => switch (system_lib.preferred_link_mode) {
.dynamic => try zig_args.append("-search_dylibs_only"),
.static => try zig_args.append("-search_static_only"),
},
.paths_first => switch (system_lib.preferred_link_mode) {
.dynamic => try zig_args.append("-search_paths_first"),
.static => try zig_args.append("-search_paths_first_static"),
},
.mode_first => switch (system_lib.preferred_link_mode) {
.dynamic => try zig_args.append("-search_dylibs_first"),
.static => try zig_args.append("-search_static_first"),
},
}
prev_search_strategy = system_lib.search_strategy;
prev_preferred_link_mode = system_lib.preferred_link_mode;
}
const prefix: []const u8 = prefix: {
if (system_lib.needed) break :prefix "-needed-l";
if (system_lib.weak) break :prefix "-weak-l";
break :prefix "-l";
};
switch (system_lib.use_pkg_config) {
.no => try zig_args.append(b.fmt("{s}{s}", .{ prefix, system_lib.name })),
.yes, .force => {
if (compile.runPkgConfig(system_lib.name)) |result| {
try zig_args.appendSlice(result.cflags);
try zig_args.appendSlice(result.libs);
try seen_system_libs.put(arena, system_lib.name, result.cflags);
} else |err| switch (err) {
error.PkgConfigInvalidOutput,
error.PkgConfigCrashed,
error.PkgConfigFailed,
error.PkgConfigNotInstalled,
error.PackageNotFound,
=> switch (system_lib.use_pkg_config) {
.yes => {
// pkg-config failed, so fall back to linking the library
// by name directly.
try zig_args.append(b.fmt("{s}{s}", .{
prefix,
system_lib.name,
}));
},
.force => {
panic("pkg-config failed for library {s}", .{system_lib.name});
},
.no => unreachable,
},
else => |e| return e,
}
},
}
},
.other_step => |other| {
switch (other.kind) {
.exe => return step.fail("cannot link with an executable build artifact", .{}),
.@"test" => return step.fail("cannot link with a test", .{}),
.obj => {
const included_in_lib_or_obj = !my_responsibility and
(dep_compile.kind == .lib or dep_compile.kind == .obj);
if (!already_linked and !included_in_lib_or_obj) {
try zig_args.append(other.getEmittedBin().getPath2(b, step));
total_linker_objects += 1;
}
},
.lib => l: {
const other_produces_implib = other.producesImplib();
const other_is_static = other_produces_implib or other.isStaticLibrary();
if (compile.isStaticLibrary() and other_is_static) {
// Avoid putting a static library inside a static library.
break :l;
}
// For DLLs, we must link against the implib.
// For everything else, we directly link
// against the library file.
const full_path_lib = if (other_produces_implib)
other.getGeneratedFilePath("generated_implib", &compile.step)
else
other.getGeneratedFilePath("generated_bin", &compile.step);
try zig_args.append(full_path_lib);
total_linker_objects += 1;
if (other.linkage == .dynamic and
compile.rootModuleTarget().os.tag != .windows)
{
if (fs.path.dirname(full_path_lib)) |dirname| {
try zig_args.append("-rpath");
try zig_args.append(dirname);
}
}
},
}
},
.assembly_file => |asm_file| l: {
if (!my_responsibility) break :l;
if (prev_has_cflags) {
try zig_args.append("-cflags");
try zig_args.append("--");
prev_has_cflags = false;
}
try zig_args.append(asm_file.getPath2(mod.owner, step));
total_linker_objects += 1;
},
.c_source_file => |c_source_file| l: {
if (!my_responsibility) break :l;
if (c_source_file.flags.len == 0) {
if (prev_has_cflags) {
try zig_args.append("-cflags");
try zig_args.append("--");
prev_has_cflags = false;
}
} else {
try zig_args.append("-cflags");
for (c_source_file.flags) |arg| {
try zig_args.append(arg);
}
try zig_args.append("--");
prev_has_cflags = true;
}
try zig_args.append(c_source_file.file.getPath2(mod.owner, step));
total_linker_objects += 1;
},
.c_source_files => |c_source_files| l: {
if (!my_responsibility) break :l;
if (c_source_files.flags.len == 0) {
if (prev_has_cflags) {
try zig_args.append("-cflags");
try zig_args.append("--");
prev_has_cflags = false;
}
} else {
try zig_args.append("-cflags");
for (c_source_files.flags) |flag| {
try zig_args.append(flag);
}
try zig_args.append("--");
prev_has_cflags = true;
}
const root_path = c_source_files.root.getPath2(mod.owner, step);
for (c_source_files.files) |file| {
try zig_args.append(b.pathJoin(&.{ root_path, file }));
}
total_linker_objects += c_source_files.files.len;
},
.win32_resource_file => |rc_source_file| l: {
if (!my_responsibility) break :l;
if (rc_source_file.flags.len == 0 and rc_source_file.include_paths.len == 0) {
if (prev_has_rcflags) {
try zig_args.append("-rcflags");
try zig_args.append("--");
prev_has_rcflags = false;
}
} else {
try zig_args.append("-rcflags");
for (rc_source_file.flags) |arg| {
try zig_args.append(arg);
}
for (rc_source_file.include_paths) |include_path| {
try zig_args.append("/I");
try zig_args.append(include_path.getPath2(mod.owner, step));
}
try zig_args.append("--");
prev_has_rcflags = true;
}
try zig_args.append(rc_source_file.file.getPath2(mod.owner, step));
total_linker_objects += 1;
},
}
}
// We need to emit the --mod argument here so that the above link objects
// have the correct parent module, but only if the module is part of
// this compilation.
if (!my_responsibility) continue;
if (cli_named_modules.modules.getIndex(mod)) |module_cli_index| {
const module_cli_name = cli_named_modules.names.keys()[module_cli_index];
try mod.appendZigProcessFlags(&zig_args, step);
// --dep arguments
try zig_args.ensureUnusedCapacity(mod.import_table.count() * 2);
for (mod.import_table.keys(), mod.import_table.values()) |name, import| {
const import_index = cli_named_modules.modules.getIndex(import).?;
const import_cli_name = cli_named_modules.names.keys()[import_index];
zig_args.appendAssumeCapacity("--dep");
if (std.mem.eql(u8, import_cli_name, name)) {
zig_args.appendAssumeCapacity(import_cli_name);
} else {
zig_args.appendAssumeCapacity(b.fmt("{s}={s}", .{ name, import_cli_name }));
}
}
// When the CLI sees a -M argument, it determines whether it
// implies the existence of a Zig compilation unit based on
// whether there is a root source file. If there is no root
// source file, then this is not a zig compilation unit - it is
// perhaps a set of linker objects, or C source files instead.
// Linker objects are added to the CLI globally, while C source
// files must have a module parent.
if (mod.root_source_file) |lp| {
const src = lp.getPath2(mod.owner, step);
try zig_args.append(b.fmt("-M{s}={s}", .{ module_cli_name, src }));
} else if (moduleNeedsCliArg(mod)) {
try zig_args.append(b.fmt("-M{s}", .{module_cli_name}));
}
}
}
}
@ -2081,3 +2061,35 @@ fn moduleNeedsCliArg(mod: *const Module) bool {
else => continue,
} else false;
}
/// Return the full set of `Step.Compile` which `start` depends on, recursively. `start` itself is
/// always returned as the first element. If `chase_dynamic` is `false`, then dynamic libraries are
/// not included, and their dependencies are not considered; if `chase_dynamic` is `true`, dynamic
/// libraries are treated the same as other linked `Compile`s.
pub fn getCompileDependencies(start: *Compile, chase_dynamic: bool) []const *Compile {
const arena = start.step.owner.graph.arena;
var compiles: std.AutoArrayHashMapUnmanaged(*Compile, void) = .empty;
var next_idx: usize = 0;
compiles.putNoClobber(arena, start, {}) catch @panic("OOM");
while (next_idx < compiles.count()) {
const compile = compiles.keys()[next_idx];
next_idx += 1;
for (compile.root_module.getGraph().modules) |mod| {
for (mod.link_objects.items) |lo| {
switch (lo) {
.other_step => |other_compile| {
if (!chase_dynamic and other_compile.isDynamicLibrary()) continue;
compiles.put(arena, other_compile, {}) catch @panic("OOM");
},
else => {},
}
}
}
}
return compiles.keys();
}

View File

@ -135,9 +135,6 @@ pub fn create(
return objcopy;
}
/// deprecated: use getOutput
pub const getOutputSource = getOutput;
pub fn getOutput(objcopy: *const ObjCopy) std.Build.LazyPath {
return .{ .generated = .{ .file = &objcopy.output_file } };
}

View File

@ -390,20 +390,12 @@ pub fn addOptionPath(
path.addStepDependencies(&options.step);
}
/// Deprecated: use `addOptionPath(options, name, artifact.getEmittedBin())` instead.
pub fn addOptionArtifact(options: *Options, name: []const u8, artifact: *Step.Compile) void {
return addOptionPath(options, name, artifact.getEmittedBin());
}
pub fn createModule(options: *Options) *std.Build.Module {
return options.step.owner.createModule(.{
.root_source_file = options.getOutput(),
});
}
/// deprecated: use `getOutput`
pub const getSource = getOutput;
/// Returns the main artifact of this Build Step which is a Zig source file
/// generated from the key-value pairs of the Options.
pub fn getOutput(options: *Options) LazyPath {

View File

@ -43,9 +43,6 @@ stdio: StdIo,
/// It should be only set using `setStdIn`.
stdin: StdIn,
/// Deprecated: use `addFileInput`
extra_file_dependencies: []const []const u8,
/// Additional input files that, when modified, indicate that the Run step
/// should be re-executed.
/// If the Run step is determined to have side-effects, the Run step is always
@ -178,7 +175,6 @@ pub fn create(owner: *std.Build, name: []const u8) *Run {
.disable_zig_progress = false,
.stdio = .infer_from_args,
.stdin = .none,
.extra_file_dependencies = &.{},
.file_inputs = .{},
.rename_step_with_output_arg = true,
.skip_foreign_checks = false,
@ -364,16 +360,10 @@ pub fn addPrefixedOutputDirectoryArg(
return .{ .generated = .{ .file = &output.generated_file } };
}
/// deprecated: use `addDirectoryArg`
pub const addDirectorySourceArg = addDirectoryArg;
pub fn addDirectoryArg(run: *Run, directory_source: std.Build.LazyPath) void {
run.addPrefixedDirectoryArg("", directory_source);
}
// deprecated: use `addPrefixedDirectoryArg`
pub const addPrefixedDirectorySourceArg = addPrefixedDirectoryArg;
pub fn addPrefixedDirectoryArg(run: *Run, prefix: []const u8, directory_source: std.Build.LazyPath) void {
const b = run.step.owner;
@ -698,9 +688,6 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
hashStdIo(&man.hash, run.stdio);
for (run.extra_file_dependencies) |file_path| {
_ = try man.addFile(b.pathFromRoot(file_path), null);
}
for (run.file_inputs.items) |lazy_path| {
_ = try man.addFile(lazy_path.getPath2(b, step), null);
}
@ -1732,15 +1719,12 @@ fn evalGeneric(run: *Run, child: *std.process.Child) !StdIoResult {
fn addPathForDynLibs(run: *Run, artifact: *Step.Compile) void {
const b = run.step.owner;
var it = artifact.root_module.iterateDependencies(artifact, true);
while (it.next()) |item| {
const other = item.compile.?;
if (item.module == &other.root_module) {
if (item.module.resolved_target.?.result.os.tag == .windows and
other.isDynamicLibrary())
{
addPathDir(run, fs.path.dirname(other.getEmittedBin().getPath2(b, &run.step)).?);
}
const compiles = artifact.getCompileDependencies(true);
for (compiles) |compile| {
if (compile.root_module.resolved_target.?.result.os.tag == .windows and
compile.isDynamicLibrary())
{
addPathDir(run, fs.path.dirname(compile.getEmittedBin().getPath2(b, &run.step)).?);
}
}
}

View File

@ -63,6 +63,7 @@ pub fn getOutput(translate_c: *TranslateC) std.Build.LazyPath {
return .{ .generated = .{ .file = &translate_c.output_file } };
}
/// Deprecated: use `createModule` or `addModule` with `std.Build.addExecutable` instead.
/// Creates a step to build an executable from the translated source.
pub fn addExecutable(translate_c: *TranslateC, options: AddExecutableOptions) *Step.Compile {
return translate_c.step.owner.addExecutable(.{
@ -81,6 +82,9 @@ pub fn addExecutable(translate_c: *TranslateC, options: AddExecutableOptions) *S
pub fn addModule(translate_c: *TranslateC, name: []const u8) *std.Build.Module {
return translate_c.step.owner.addModule(name, .{
.root_source_file = translate_c.getOutput(),
.target = translate_c.target,
.optimize = translate_c.optimize,
.link_libc = translate_c.link_libc,
});
}

View File

@ -6,9 +6,11 @@ pub fn build(b: *std.Build) void {
const exe = b.addExecutable(.{
.name = "bss",
.root_source_file = b.path("main.zig"),
.target = b.graph.host,
.optimize = .Debug,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.target = b.graph.host,
.optimize = .Debug,
}),
});
const run = b.addRunArtifact(exe);

View File

@ -13,19 +13,24 @@ pub fn build(b: *std.Build) void {
fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
const lib_a = b.addStaticLibrary(.{
.name = "a",
.optimize = optimize,
.target = b.graph.host,
.root_module = b.createModule(.{
.root_source_file = null,
.optimize = optimize,
.target = b.graph.host,
}),
});
lib_a.addCSourceFiles(.{
lib_a.root_module.addCSourceFiles(.{
.files = &.{ "c.c", "a.c", "b.c" },
.flags = &.{"-fcommon"},
});
const test_exe = b.addTest(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
}),
});
test_exe.linkLibrary(lib_a);
test_exe.root_module.linkLibrary(lib_a);
test_step.dependOn(&b.addRunArtifact(test_exe).step);
}

View File

@ -13,19 +13,25 @@ pub fn build(b: *std.Build) void {
fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
const lib_a = b.addStaticLibrary(.{
.name = "a",
.optimize = optimize,
.target = b.graph.host,
.root_module = b.createModule(.{
.root_source_file = null,
.optimize = optimize,
.target = b.graph.host,
}),
});
lib_a.addCSourceFiles(.{
lib_a.root_module.addCSourceFiles(.{
.files = &.{"a.c"},
.flags = &.{"-fcommon"},
});
const test_exe = b.addTest(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.target = b.graph.host,
.optimize = optimize,
}),
});
test_exe.linkLibrary(lib_a);
test_exe.root_module.linkLibrary(lib_a);
test_step.dependOn(&b.addRunArtifact(test_exe).step);
}

View File

@ -14,12 +14,15 @@ pub fn build(b: *std.Build) void {
for ([_][]const u8{ "aarch64-linux-gnu.2.27", "aarch64-linux-gnu.2.34" }) |t| {
const exe = b.addExecutable(.{
.name = t,
.target = b.resolveTargetQuery(std.Target.Query.parse(
.{ .arch_os_abi = t },
) catch unreachable),
.root_module = b.createModule(.{
.root_source_file = null,
.target = b.resolveTargetQuery(std.Target.Query.parse(
.{ .arch_os_abi = t },
) catch unreachable),
.link_libc = true,
}),
});
exe.addCSourceFile(.{ .file = b.path("main.c") });
exe.linkLibC();
exe.root_module.addCSourceFile(.{ .file = b.path("main.c") });
// TODO: actually test the output
_ = exe.getEmittedBin();
test_step.dependOn(&exe.step);
@ -53,10 +56,13 @@ pub fn build(b: *std.Build) void {
const exe = b.addExecutable(.{
.name = t,
.target = target,
.root_module = b.createModule(.{
.root_source_file = null,
.target = target,
.link_libc = true,
}),
});
exe.addCSourceFile(.{ .file = b.path("glibc_runtime_check.c") });
exe.linkLibC();
exe.root_module.addCSourceFile(.{ .file = b.path("glibc_runtime_check.c") });
// Only try running the test if the host glibc is known to be good enough. Ideally, the Zig
// test runner would be able to check this, but see https://github.com/ziglang/zig/pull/17702#issuecomment-1831310453
@ -149,10 +155,12 @@ pub fn build(b: *std.Build) void {
const exe = b.addExecutable(.{
.name = t,
.root_source_file = b.path("glibc_runtime_check.zig"),
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("glibc_runtime_check.zig"),
.target = target,
.link_libc = true,
}),
});
exe.linkLibC();
// Only try running the test if the host glibc is known to be good enough. Ideally, the Zig
// test runner would be able to check this, but see https://github.com/ziglang/zig/pull/17702#issuecomment-1831310453

View File

@ -13,27 +13,36 @@ pub fn build(b: *std.Build) void {
fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
const lib_a = b.addStaticLibrary(.{
.name = "a",
.optimize = optimize,
.target = b.graph.host,
.root_module = b.createModule(.{
.root_source_file = null,
.optimize = optimize,
.target = b.graph.host,
}),
});
lib_a.addCSourceFile(.{ .file = b.path("a.c"), .flags = &[_][]const u8{} });
lib_a.addIncludePath(b.path("."));
lib_a.root_module.addCSourceFile(.{ .file = b.path("a.c"), .flags = &[_][]const u8{} });
lib_a.root_module.addIncludePath(b.path("."));
const lib_b = b.addStaticLibrary(.{
.name = "b",
.optimize = optimize,
.target = b.graph.host,
.root_module = b.createModule(.{
.root_source_file = null,
.optimize = optimize,
.target = b.graph.host,
}),
});
lib_b.addCSourceFile(.{ .file = b.path("b.c"), .flags = &[_][]const u8{} });
lib_b.addIncludePath(b.path("."));
lib_b.root_module.addCSourceFile(.{ .file = b.path("b.c"), .flags = &[_][]const u8{} });
lib_b.root_module.addIncludePath(b.path("."));
const test_exe = b.addTest(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.target = b.graph.host,
.optimize = optimize,
}),
});
test_exe.linkLibrary(lib_a);
test_exe.linkLibrary(lib_b);
test_exe.addIncludePath(b.path("."));
test_exe.root_module.linkLibrary(lib_a);
test_exe.root_module.linkLibrary(lib_b);
test_exe.root_module.addIncludePath(b.path("."));
test_step.dependOn(&b.addRunArtifact(test_exe).step);
}

View File

@ -47,81 +47,85 @@ const OverlayOptions = struct {
};
pub fn addExecutable(b: *std.Build, base: Options, overlay: OverlayOptions) *Compile {
return addCompileStep(b, base, overlay, .exe);
return b.addExecutable(.{
.name = overlay.name,
.root_module = createModule(b, base, overlay),
.use_llvm = base.use_llvm,
.use_lld = base.use_lld,
});
}
pub fn addObject(b: *Build, base: Options, overlay: OverlayOptions) *Compile {
return addCompileStep(b, base, overlay, .obj);
return b.addObject(.{
.name = overlay.name,
.root_module = createModule(b, base, overlay),
.use_llvm = base.use_llvm,
.use_lld = base.use_lld,
});
}
pub fn addStaticLibrary(b: *Build, base: Options, overlay: OverlayOptions) *Compile {
return addCompileStep(b, base, overlay, .static_lib);
return b.addStaticLibrary(.{
.name = overlay.name,
.root_module = createModule(b, base, overlay),
.use_llvm = base.use_llvm,
.use_lld = base.use_lld,
});
}
pub fn addSharedLibrary(b: *Build, base: Options, overlay: OverlayOptions) *Compile {
return addCompileStep(b, base, overlay, .shared_lib);
}
fn addCompileStep(
b: *Build,
base: Options,
overlay: OverlayOptions,
kind: enum { exe, obj, shared_lib, static_lib },
) *Compile {
const compile_step = Compile.create(b, .{
return b.addSharedLibrary(.{
.name = overlay.name,
.root_module = .{
.target = base.target,
.optimize = base.optimize,
.root_source_file = rsf: {
const bytes = overlay.zig_source_bytes orelse break :rsf null;
const name = b.fmt("{s}.zig", .{overlay.name});
break :rsf b.addWriteFiles().add(name, bytes);
},
.pic = overlay.pic,
.strip = if (base.strip) |s| s else overlay.strip,
},
.root_module = createModule(b, base, overlay),
.use_llvm = base.use_llvm,
.use_lld = base.use_lld,
.kind = switch (kind) {
.exe => .exe,
.obj => .obj,
.shared_lib, .static_lib => .lib,
},
.linkage = switch (kind) {
.exe, .obj => null,
.shared_lib => .dynamic,
.static_lib => .static,
},
});
}
fn createModule(b: *Build, base: Options, overlay: OverlayOptions) *Build.Module {
const write_files = b.addWriteFiles();
const mod = b.createModule(.{
.target = base.target,
.optimize = base.optimize,
.root_source_file = rsf: {
const bytes = overlay.zig_source_bytes orelse break :rsf null;
const name = b.fmt("{s}.zig", .{overlay.name});
break :rsf write_files.add(name, bytes);
},
.pic = overlay.pic,
.strip = if (base.strip) |s| s else overlay.strip,
});
if (overlay.objcpp_source_bytes) |bytes| {
compile_step.addCSourceFile(.{
.file = b.addWriteFiles().add("a.mm", bytes),
mod.addCSourceFile(.{
.file = write_files.add("a.mm", bytes),
.flags = overlay.objcpp_source_flags,
});
}
if (overlay.objc_source_bytes) |bytes| {
compile_step.addCSourceFile(.{
.file = b.addWriteFiles().add("a.m", bytes),
mod.addCSourceFile(.{
.file = write_files.add("a.m", bytes),
.flags = overlay.objc_source_flags,
});
}
if (overlay.cpp_source_bytes) |bytes| {
compile_step.addCSourceFile(.{
.file = b.addWriteFiles().add("a.cpp", bytes),
mod.addCSourceFile(.{
.file = write_files.add("a.cpp", bytes),
.flags = overlay.cpp_source_flags,
});
}
if (overlay.c_source_bytes) |bytes| {
compile_step.addCSourceFile(.{
.file = b.addWriteFiles().add("a.c", bytes),
mod.addCSourceFile(.{
.file = write_files.add("a.c", bytes),
.flags = overlay.c_source_flags,
});
}
if (overlay.asm_source_bytes) |bytes| {
compile_step.addAssemblyFile(b.addWriteFiles().add("a.s", bytes));
mod.addAssemblyFile(write_files.add("a.s", bytes));
}
return compile_step;
return mod;
}
pub fn addRunArtifact(comp: *Compile) *Run {

View File

@ -57,13 +57,15 @@ fn add(b: *Build, test_step: *Step, files: []const LazyPath, optimize: std.built
{
const exe = b.addExecutable(.{
.name = "test1",
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = b.graph.host,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = b.graph.host,
}),
});
for (files) |file| {
exe.addCSourceFile(.{ .file = file, .flags = &flags });
exe.root_module.addCSourceFile(.{ .file = file, .flags = &flags });
}
const run_cmd = b.addRunArtifact(exe);
@ -75,30 +77,33 @@ fn add(b: *Build, test_step: *Step, files: []const LazyPath, optimize: std.built
// using static librairies
{
const mod_a = b.createModule(.{ .target = b.graph.host, .optimize = optimize });
const mod_b = b.createModule(.{ .target = b.graph.host, .optimize = optimize });
for (files, 1..) |file, i| {
const mod = if (i & 1 == 0) mod_a else mod_b;
mod.addCSourceFile(.{ .file = file, .flags = &flags });
}
const lib_a = b.addStaticLibrary(.{
.name = "test2_a",
.target = b.graph.host,
.optimize = optimize,
.root_module = mod_a,
});
const lib_b = b.addStaticLibrary(.{
.name = "test2_b",
.target = b.graph.host,
.optimize = optimize,
.root_module = mod_b,
});
for (files, 1..) |file, i| {
const lib = if (i & 1 == 0) lib_a else lib_b;
lib.addCSourceFile(.{ .file = file, .flags = &flags });
}
const exe = b.addExecutable(.{
.name = "test2",
.root_source_file = b.path("main.zig"),
.target = b.graph.host,
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.target = b.graph.host,
.optimize = optimize,
}),
});
exe.linkLibrary(lib_a);
exe.linkLibrary(lib_b);
exe.root_module.linkLibrary(lib_a);
exe.root_module.linkLibrary(lib_b);
const run_cmd = b.addRunArtifact(exe);
run_cmd.skip_foreign_checks = true;
@ -109,37 +114,41 @@ fn add(b: *Build, test_step: *Step, files: []const LazyPath, optimize: std.built
// using static librairies and object files
{
const mod_a = b.createModule(.{ .target = b.graph.host, .optimize = optimize });
const mod_b = b.createModule(.{ .target = b.graph.host, .optimize = optimize });
for (files, 1..) |file, i| {
const obj_mod = b.createModule(.{ .target = b.graph.host, .optimize = optimize });
obj_mod.addCSourceFile(.{ .file = file, .flags = &flags });
const obj = b.addObject(.{
.name = b.fmt("obj_{}", .{i}),
.root_module = obj_mod,
});
const lib_mod = if (i & 1 == 0) mod_a else mod_b;
lib_mod.addObject(obj);
}
const lib_a = b.addStaticLibrary(.{
.name = "test3_a",
.target = b.graph.host,
.optimize = optimize,
.root_module = mod_a,
});
const lib_b = b.addStaticLibrary(.{
.name = "test3_b",
.target = b.graph.host,
.optimize = optimize,
.root_module = mod_b,
});
for (files, 1..) |file, i| {
const obj = b.addObject(.{
.name = b.fmt("obj_{}", .{i}),
.target = b.graph.host,
.optimize = optimize,
});
obj.addCSourceFile(.{ .file = file, .flags = &flags });
const lib = if (i & 1 == 0) lib_a else lib_b;
lib.addObject(obj);
}
const exe = b.addExecutable(.{
.name = "test3",
.root_source_file = b.path("main.zig"),
.target = b.graph.host,
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.target = b.graph.host,
.optimize = optimize,
}),
});
exe.linkLibrary(lib_a);
exe.linkLibrary(lib_b);
exe.root_module.linkLibrary(lib_a);
exe.root_module.linkLibrary(lib_b);
const run_cmd = b.addRunArtifact(exe);
run_cmd.skip_foreign_checks = true;

View File

@ -17,10 +17,12 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize
// and therefore link with its archive file.
const lib = b.addExecutable(.{
.name = "main",
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.strip = false,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.strip = false,
}),
});
lib.entry = .disabled;
lib.use_llvm = false;

View File

@ -6,13 +6,15 @@ pub fn build(b: *std.Build) void {
// Library with explicitly set cpu features
const lib = b.addExecutable(.{
.name = "lib",
.root_source_file = b.path("main.zig"),
.optimize = .Debug,
.target = b.resolveTargetQuery(.{
.cpu_arch = .wasm32,
.cpu_model = .{ .explicit = &std.Target.wasm.cpu.mvp },
.cpu_features_add = std.Target.wasm.featureSet(&.{.atomics}),
.os_tag = .freestanding,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.optimize = .Debug,
.target = b.resolveTargetQuery(.{
.cpu_arch = .wasm32,
.cpu_model = .{ .explicit = &std.Target.wasm.cpu.mvp },
.cpu_features_add = std.Target.wasm.featureSet(&.{.atomics}),
.os_tag = .freestanding,
}),
}),
});
lib.entry = .disabled;

View File

@ -16,10 +16,12 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.Opt
{
const lib = b.addExecutable(.{
.name = "lib",
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.optimize = optimize_mode,
.strip = false,
.root_module = b.createModule(.{
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.optimize = optimize_mode,
.strip = false,
}),
});
lib.entry = .disabled;
lib.use_llvm = false;
@ -64,10 +66,12 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.Opt
{
const lib = b.addExecutable(.{
.name = "lib",
.root_source_file = b.path("lib2.zig"),
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.optimize = optimize_mode,
.strip = false,
.root_module = b.createModule(.{
.root_source_file = b.path("lib2.zig"),
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.optimize = optimize_mode,
.strip = false,
}),
});
lib.entry = .disabled;
lib.use_llvm = false;

View File

@ -11,9 +11,11 @@ pub fn build(b: *std.Build) void {
const lib = b.addExecutable(.{
.name = "lib",
.root_source_file = b.path("lib.zig"),
.optimize = .ReleaseSafe, // to make the output deterministic in address positions
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.root_module = b.createModule(.{
.root_source_file = b.path("lib.zig"),
.optimize = .ReleaseSafe, // to make the output deterministic in address positions
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
}),
});
lib.entry = .disabled;
lib.use_lld = false;

View File

@ -15,9 +15,11 @@ pub fn build(b: *std.Build) void {
fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
const no_export = b.addExecutable(.{
.name = "no-export",
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
}),
});
no_export.entry = .disabled;
no_export.use_llvm = false;
@ -25,9 +27,11 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize
const dynamic_export = b.addExecutable(.{
.name = "dynamic",
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
}),
});
dynamic_export.entry = .disabled;
dynamic_export.rdynamic = true;
@ -36,9 +40,11 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize
const force_export = b.addExecutable(.{
.name = "force",
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
}),
});
force_export.entry = .disabled;
force_export.root_module.export_symbol_names = &.{"foo"};

View File

@ -13,9 +13,11 @@ pub fn build(b: *std.Build) void {
fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
const lib = b.addExecutable(.{
.name = "lib",
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.optimize = optimize,
}),
});
lib.entry = .disabled;
lib.import_symbols = true; // import `a` and `b`

View File

@ -15,9 +15,11 @@ pub fn build(b: *std.Build) void {
fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
const exe = b.addExecutable(.{
.name = "extern",
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .wasi }),
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .wasi }),
}),
});
exe.addCSourceFile(.{ .file = b.path("foo.c"), .flags = &.{} });
exe.use_llvm = false;

View File

@ -15,9 +15,11 @@ pub fn build(b: *std.Build) void {
fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
const import_table = b.addExecutable(.{
.name = "import_table",
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.optimize = optimize,
}),
});
import_table.entry = .disabled;
import_table.use_llvm = false;
@ -27,9 +29,11 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize
const export_table = b.addExecutable(.{
.name = "export_table",
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.optimize = optimize,
}),
});
export_table.entry = .disabled;
export_table.use_llvm = false;
@ -39,9 +43,11 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize
const regular_table = b.addExecutable(.{
.name = "regular_table",
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.optimize = optimize,
}),
});
regular_table.entry = .disabled;
regular_table.use_llvm = false;

View File

@ -6,31 +6,36 @@ pub fn build(b: *std.Build) void {
// Wasm Object file which we will use to infer the features from
const c_obj = b.addObject(.{
.name = "c_obj",
.optimize = .Debug,
.target = b.resolveTargetQuery(.{
.cpu_arch = .wasm32,
.cpu_model = .{ .explicit = &std.Target.wasm.cpu.bleeding_edge },
.os_tag = .freestanding,
.root_module = b.createModule(.{
.root_source_file = null,
.optimize = .Debug,
.target = b.resolveTargetQuery(.{
.cpu_arch = .wasm32,
.cpu_model = .{ .explicit = &std.Target.wasm.cpu.bleeding_edge },
.os_tag = .freestanding,
}),
}),
});
c_obj.addCSourceFile(.{ .file = b.path("foo.c"), .flags = &.{} });
c_obj.root_module.addCSourceFile(.{ .file = b.path("foo.c"), .flags = &.{} });
// Wasm library that doesn't have any features specified. This will
// infer its featureset from other linked object files.
const lib = b.addExecutable(.{
.name = "lib",
.root_source_file = b.path("main.zig"),
.optimize = .Debug,
.target = b.resolveTargetQuery(.{
.cpu_arch = .wasm32,
.cpu_model = .{ .explicit = &std.Target.wasm.cpu.mvp },
.os_tag = .freestanding,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.optimize = .Debug,
.target = b.resolveTargetQuery(.{
.cpu_arch = .wasm32,
.cpu_model = .{ .explicit = &std.Target.wasm.cpu.mvp },
.os_tag = .freestanding,
}),
}),
});
lib.entry = .disabled;
lib.use_llvm = false;
lib.use_lld = false;
lib.addObject(c_obj);
lib.root_module.addObject(c_obj);
// Verify the result contains the features from the C Object file.
const check = lib.checkObject();

View File

@ -16,10 +16,12 @@ pub fn build(b: *std.Build) void {
fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
const lib = b.addExecutable(.{
.name = "lib",
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.optimize = optimize,
.strip = false,
.root_module = b.createModule(.{
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.optimize = optimize,
.strip = false,
}),
});
lib.entry = .disabled;
lib.use_llvm = false;

View File

@ -15,10 +15,12 @@ pub fn build(b: *std.Build) void {
fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
const lib = b.addExecutable(.{
.name = "lib",
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.optimize = optimize,
.strip = false,
.root_module = b.createModule(.{
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.optimize = optimize,
.strip = false,
}),
});
lib.entry = .disabled;
lib.use_llvm = false;

View File

@ -13,16 +13,18 @@ pub fn build(b: *std.Build) void {
fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.OptimizeMode) void {
const exe = b.addExecutable(.{
.name = "lib",
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{
.cpu_arch = .wasm32,
.cpu_model = .{ .explicit = &std.Target.wasm.cpu.mvp },
.cpu_features_add = std.Target.wasm.featureSet(&.{ .atomics, .bulk_memory }),
.os_tag = .freestanding,
.root_module = b.createModule(.{
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{
.cpu_arch = .wasm32,
.cpu_model = .{ .explicit = &std.Target.wasm.cpu.mvp },
.cpu_features_add = std.Target.wasm.featureSet(&.{ .atomics, .bulk_memory }),
.os_tag = .freestanding,
}),
.optimize = optimize_mode,
.strip = false,
.single_threaded = false,
}),
.optimize = optimize_mode,
.strip = false,
.single_threaded = false,
});
exe.entry = .disabled;
exe.use_lld = false;

View File

@ -15,10 +15,12 @@ pub fn build(b: *std.Build) void {
fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
const lib = b.addExecutable(.{
.name = "lib",
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.optimize = optimize,
.strip = false,
.root_module = b.createModule(.{
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.optimize = optimize,
.strip = false,
}),
});
lib.entry = .disabled;
lib.use_llvm = false;

View File

@ -15,10 +15,12 @@ pub fn build(b: *std.Build) void {
fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
const exe = b.addExecutable(.{
.name = "lib",
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.optimize = optimize,
.strip = false,
.root_module = b.createModule(.{
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .freestanding }),
.optimize = optimize,
.strip = false,
}),
});
exe.entry = .disabled;
exe.use_llvm = false;

View File

@ -572,7 +572,10 @@ pub fn lowerToTranslateCSteps(
});
translate_c.step.name = b.fmt("{s} translate-c", .{annotated_case_name});
const run_exe = translate_c.addExecutable(.{});
const run_exe = b.addExecutable(.{
.name = "translated_c",
.root_module = translate_c.createModule(),
});
run_exe.step.name = b.fmt("{s} build-exe", .{annotated_case_name});
run_exe.linkLibC();
const run = b.addRunArtifact(run_exe);
@ -660,34 +663,37 @@ pub fn lowerToBuildSteps(
file_sources.put(file.path, writefiles.add(file.path, file.src)) catch @panic("OOM");
}
const artifact = if (case.is_test) b.addTest(.{
const mod = b.createModule(.{
.root_source_file = root_source_file,
.name = case.name,
.target = case.target,
.optimize = case.optimize_mode,
});
if (case.link_libc) mod.link_libc = true;
if (case.pic) |pic| mod.pic = pic;
for (case.deps.items) |dep| {
mod.addAnonymousImport(dep.name, .{
.root_source_file = file_sources.get(dep.path).?,
});
}
const artifact = if (case.is_test) b.addTest(.{
.name = case.name,
.root_module = mod,
}) else switch (case.output_mode) {
.Obj => b.addObject(.{
.root_source_file = root_source_file,
.name = case.name,
.target = case.target,
.optimize = case.optimize_mode,
.root_module = mod,
}),
.Lib => b.addStaticLibrary(.{
.root_source_file = root_source_file,
.name = case.name,
.target = case.target,
.optimize = case.optimize_mode,
.root_module = mod,
}),
.Exe => b.addExecutable(.{
.root_source_file = root_source_file,
.name = case.name,
.target = case.target,
.optimize = case.optimize_mode,
.root_module = mod,
}),
};
if (case.link_libc) artifact.linkLibC();
if (case.pic) |pic| artifact.root_module.pic = pic;
if (case.pie) |pie| artifact.pie = pie;
switch (case.backend) {
@ -701,12 +707,6 @@ pub fn lowerToBuildSteps(
},
}
for (case.deps.items) |dep| {
artifact.root_module.addAnonymousImport(dep.name, .{
.root_source_file = file_sources.get(dep.path).?,
});
}
switch (update.case) {
.Compile => {
// Force the binary to be emitted if requested.

View File

@ -89,19 +89,22 @@ pub fn addCase(self: *CompareOutput, case: TestCase) void {
switch (case.special) {
Special.Asm => {
const annotated_case_name = fmt.allocPrint(self.b.allocator, "run assemble-and-link {s}", .{
const annotated_case_name = b.fmt("run assemble-and-link {s}", .{
case.name,
}) catch @panic("OOM");
});
for (self.test_filters) |test_filter| {
if (mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
} else if (self.test_filters.len > 0) return;
const exe = b.addExecutable(.{
.name = "test",
.target = b.graph.host,
.optimize = .Debug,
.root_module = b.createModule(.{
.root_source_file = null,
.target = b.graph.host,
.optimize = .Debug,
}),
});
exe.addAssemblyFile(first_file);
exe.root_module.addAssemblyFile(first_file);
const run = b.addRunArtifact(exe);
run.setName(annotated_case_name);
@ -112,22 +115,22 @@ pub fn addCase(self: *CompareOutput, case: TestCase) void {
},
Special.None => {
for (self.optimize_modes) |optimize| {
const annotated_case_name = fmt.allocPrint(self.b.allocator, "run compare-output {s} ({s})", .{
const annotated_case_name = b.fmt("run compare-output {s} ({s})", .{
case.name, @tagName(optimize),
}) catch @panic("OOM");
});
for (self.test_filters) |test_filter| {
if (mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
} else if (self.test_filters.len > 0) return;
const exe = b.addExecutable(.{
.name = "test",
.root_source_file = first_file,
.optimize = optimize,
.target = b.graph.host,
.root_module = b.createModule(.{
.root_source_file = first_file,
.optimize = optimize,
.target = b.graph.host,
}),
});
if (case.link_libc) {
exe.linkSystemLibrary("c");
}
if (case.link_libc) exe.root_module.link_libc = true;
const run = b.addRunArtifact(exe);
run.setName(annotated_case_name);
@ -140,20 +143,20 @@ pub fn addCase(self: *CompareOutput, case: TestCase) void {
Special.RuntimeSafety => {
// TODO iterate over self.optimize_modes and test this in both
// debug and release safe mode
const annotated_case_name = fmt.allocPrint(self.b.allocator, "run safety {s}", .{case.name}) catch @panic("OOM");
const annotated_case_name = b.fmt("run safety {s}", .{case.name});
for (self.test_filters) |test_filter| {
if (mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
} else if (self.test_filters.len > 0) return;
const exe = b.addExecutable(.{
.name = "test",
.root_source_file = first_file,
.target = b.graph.host,
.optimize = .Debug,
.root_module = b.createModule(.{
.root_source_file = first_file,
.target = b.graph.host,
.optimize = .Debug,
}),
});
if (case.link_libc) {
exe.linkSystemLibrary("c");
}
if (case.link_libc) exe.root_module.link_libc = true;
const run = b.addRunArtifact(exe);
run.setName(annotated_case_name);
@ -168,7 +171,6 @@ pub fn addCase(self: *CompareOutput, case: TestCase) void {
const CompareOutput = @This();
const std = @import("std");
const ArrayList = std.ArrayList;
const fmt = std.fmt;
const mem = std.mem;
const fs = std.fs;
const OptimizeMode = std.builtin.OptimizeMode;

View File

@ -2414,8 +2414,8 @@ fn addTest(
} else return;
}
const files_wf = db.b.addWriteFiles();
const exe = db.b.addExecutable(.{
.name = name,
const mod = db.b.createModule(.{
.target = target.resolved,
.root_source_file = files_wf.add(files[0].path, files[0].source),
.optimize = target.optimize_mode,
@ -2423,15 +2423,21 @@ fn addTest(
.single_threaded = target.single_threaded,
.pic = target.pic,
.strip = false,
.use_llvm = false,
.use_lld = false,
});
for (files[1..]) |file| {
const path = files_wf.add(file.path, file.source);
if (file.import) |import| exe.root_module.addImport(import, db.b.createModule(.{
if (file.import) |import| mod.addImport(import, db.b.createModule(.{
.root_source_file = path,
}));
}
const exe = db.b.addExecutable(.{
.name = name,
.root_module = mod,
.use_llvm = false,
.use_lld = false,
});
const commands_wf = db.b.addWriteFiles();
const run = std.Build.Step.Run.create(db.b, db.b.fmt("run {s} {s}", .{ name, target.test_name_suffix }));
run.addArgs(db_argv1);

View File

@ -84,7 +84,10 @@ pub fn addCase(self: *RunTranslatedCContext, case: *const TestCase) void {
});
translate_c.step.name = b.fmt("{s} translate-c", .{annotated_case_name});
const exe = translate_c.addExecutable(.{});
const exe = b.addExecutable(.{
.name = "translated_c",
.root_module = translate_c.createModule(),
});
exe.step.name = b.fmt("{s} build-exe", .{annotated_case_name});
exe.linkLibC();
const run = b.addRunArtifact(exe);

View File

@ -44,9 +44,9 @@ fn addExpect(
for (mode_config.exclude_os) |tag| if (tag == builtin.os.tag) return;
const b = self.b;
const annotated_case_name = fmt.allocPrint(b.allocator, "check {s} ({s})", .{
const annotated_case_name = b.fmt("check {s} ({s})", .{
name, @tagName(optimize_mode),
}) catch @panic("OOM");
});
for (self.test_filters) |test_filter| {
if (mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
} else if (self.test_filters.len > 0) return;
@ -55,10 +55,12 @@ fn addExpect(
const source_zig = write_files.add("source.zig", source);
const exe = b.addExecutable(.{
.name = "test",
.root_source_file = source_zig,
.optimize = optimize_mode,
.target = b.graph.host,
.error_tracing = mode_config.error_tracing,
.root_module = b.createModule(.{
.root_source_file = source_zig,
.optimize = optimize_mode,
.target = b.graph.host,
.error_tracing = mode_config.error_tracing,
}),
});
const run = b.addRunArtifact(exe);
@ -83,5 +85,4 @@ const std = @import("std");
const builtin = @import("builtin");
const Step = std.Build.Step;
const OptimizeMode = std.builtin.OptimizeMode;
const fmt = std.fmt;
const mem = std.mem;

View File

@ -47,9 +47,11 @@ pub fn build(b: *std.Build) void {
}) |tool_src_path| {
const tool = b.addTest(.{
.name = std.fs.path.stem(tool_src_path),
.root_source_file = b.path(tool_src_path),
.optimize = .Debug,
.target = tools_target,
.root_module = b.createModule(.{
.root_source_file = b.path(tool_src_path),
.optimize = .Debug,
.target = tools_target,
}),
});
const run = b.addRunArtifact(tool);
tools_tests_step.dependOn(&run.step);

View File

@ -20,22 +20,25 @@ fn add(
) void {
const target = b.graph.host;
const exe_c = b.addExecutable(.{
.name = c_name,
const c_mod = b.createModule(.{
.optimize = optimize,
.target = target,
});
exe_c.addCSourceFile(.{ .file = b.path("test.c"), .flags = &[0][]const u8{} });
exe_c.linkLibC();
c_mod.addCSourceFile(.{ .file = b.path("test.c"), .flags = &[0][]const u8{} });
c_mod.link_libc = true;
const exe_cpp = b.addExecutable(.{
.name = cpp_name,
const exe_c = b.addExecutable(.{ .name = c_name, .root_module = c_mod });
const cpp_mod = b.createModule(.{
.optimize = optimize,
.target = target,
});
cpp_mod.addCSourceFile(.{ .file = b.path("test.cpp"), .flags = &[0][]const u8{} });
cpp_mod.link_libcpp = true;
const exe_cpp = b.addExecutable(.{ .name = cpp_name, .root_module = cpp_mod });
b.default_step.dependOn(&exe_cpp.step);
exe_cpp.addCSourceFile(.{ .file = b.path("test.cpp"), .flags = &[0][]const u8{} });
exe_cpp.linkLibCpp();
switch (target.result.os.tag) {
.windows => {

View File

@ -12,16 +12,20 @@ pub fn build(b: *std.Build) void {
const child = b.addExecutable(.{
.name = "child",
.root_source_file = b.path("child.zig"),
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("child.zig"),
.optimize = optimize,
.target = target,
}),
});
const main = b.addExecutable(.{
.name = "main",
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = target,
}),
});
const run = b.addRunArtifact(main);
run.addArtifactArg(child);

View File

@ -14,19 +14,24 @@ pub fn build(b: *std.Build) void {
const exe = b.addExecutable(.{
.name = "main",
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = target,
}),
});
const lib = b.addSharedLibrary(.{
.name = "shared_lib",
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = null,
.optimize = optimize,
.target = target,
.link_libc = true,
}),
});
lib.addCSourceFile(.{ .file = b.path("shared_lib.c"), .flags = &.{"-gdwarf"} });
lib.linkLibC();
exe.linkLibrary(lib);
lib.root_module.addCSourceFile(.{ .file = b.path("shared_lib.c"), .flags = &.{"-gdwarf"} });
exe.root_module.linkLibrary(lib);
const run = b.addRunArtifact(exe);
run.expectExitCode(0);

View File

@ -12,11 +12,14 @@ pub fn build(b: *std.Build) void {
const exe = b.addExecutable(.{
.name = "main",
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = null,
.optimize = optimize,
.target = target,
.link_libc = true,
}),
});
exe.linkLibC();
exe.addCSourceFile(.{
exe.root_module.addCSourceFile(.{
.file = b.path("main.c"),
.flags = &.{},
});

View File

@ -6,23 +6,23 @@ pub fn build(b: *std.Build) void {
const optimize: std.builtin.OptimizeMode = .Debug;
const shared = b.createModule(.{
.root_source_file = b.path("shared.zig"),
});
const exe = b.addExecutable(.{
.name = "test",
const main_mod = b.createModule(.{
.root_source_file = b.path("test.zig"),
.target = b.graph.host,
.optimize = optimize,
});
exe.root_module.addAnonymousImport("foo", .{
.root_source_file = b.path("foo.zig"),
.imports = &.{.{ .name = "shared", .module = shared }},
});
exe.root_module.addAnonymousImport("bar", .{
.root_source_file = b.path("bar.zig"),
.imports = &.{.{ .name = "shared", .module = shared }},
const shared_mod = b.createModule(.{ .root_source_file = b.path("shared.zig") });
const foo_mod = b.createModule(.{ .root_source_file = b.path("foo.zig") });
const bar_mod = b.createModule(.{ .root_source_file = b.path("bar.zig") });
main_mod.addImport("foo", foo_mod);
main_mod.addImport("bar", bar_mod);
foo_mod.addImport("shared", shared_mod);
bar_mod.addImport("shared", shared_mod);
const exe = b.addExecutable(.{
.name = "test",
.root_module = main_mod,
});
const run = b.addRunArtifact(exe);

View File

@ -4,29 +4,36 @@ pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const mod = b.addModule("mod", .{
const shared_mod = b.createModule(.{
.root_source_file = b.path("mod.zig"),
.target = target,
.optimize = optimize,
});
const lib = b.addStaticLibrary(.{
.name = "lib",
const lib_mod = b.createModule(.{
.root_source_file = b.path("lib.zig"),
.target = target,
.optimize = optimize,
});
lib.root_module.addImport("mod", mod);
const exe = b.addExecutable(.{
.name = "app",
const exe_mod = b.createModule(.{
.root_source_file = b.path("main.zig"),
.target = target,
.optimize = optimize,
});
exe.root_module.addImport("mod", mod);
exe.root_module.linkLibrary(lib);
lib_mod.addImport("mod", shared_mod);
exe_mod.addImport("mod", shared_mod);
const lib = b.addStaticLibrary(.{
.name = "lib",
.root_module = lib_mod,
});
exe_mod.linkLibrary(lib);
const exe = b.addExecutable(.{
.name = "app",
.root_module = exe_mod,
});
b.installArtifact(exe);
}

View File

@ -11,10 +11,13 @@ pub fn build(b: *std.Build) void {
const generated_main_c = write_files.add("main.c", "");
const exe = b.addExecutable(.{
.name = "test",
.target = b.graph.host,
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = null,
.target = b.graph.host,
.optimize = optimize,
}),
});
exe.addCSourceFiles(.{
exe.root_module.addCSourceFiles(.{
.root = generated_main_c.dirname(),
.files = &.{"main.c"},
});
@ -26,11 +29,13 @@ pub fn build(b: *std.Build) void {
const dir = write_files.addCopyDirectory(b.path("inc"), "", .{});
const exe = b.addExecutable(.{
.name = "test",
.root_source_file = b.path("inctest.zig"),
.target = b.graph.host,
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("inctest.zig"),
.target = b.graph.host,
.optimize = optimize,
}),
});
exe.addIncludePath(dir);
exe.root_module.addIncludePath(dir);
b.step("copydir", "").dependOn(&exe.step);
test_step.dependOn(&exe.step);
}

View File

@ -6,22 +6,26 @@ pub fn build(b: *std.Build) void {
const optimize: std.builtin.OptimizeMode = .Debug;
const foo = b.createModule(.{
.root_source_file = b.path("foo.zig"),
});
const bar = b.createModule(.{
.root_source_file = b.path("bar.zig"),
});
foo.addImport("bar", bar);
bar.addImport("foo", foo);
const exe = b.addExecutable(.{
.name = "test",
const main_mod = b.createModule(.{
.root_source_file = b.path("test.zig"),
.target = b.graph.host,
.optimize = optimize,
});
exe.root_module.addImport("foo", foo);
const foo_mod = b.createModule(.{
.root_source_file = b.path("foo.zig"),
});
const bar_mod = b.createModule(.{
.root_source_file = b.path("bar.zig"),
});
main_mod.addImport("foo", foo_mod);
foo_mod.addImport("bar", bar_mod);
bar_mod.addImport("foo", foo_mod);
const exe = b.addExecutable(.{
.name = "test",
.root_module = main_mod,
});
const run = b.addRunArtifact(exe);
test_step.dependOn(&run.step);

View File

@ -6,18 +6,22 @@ pub fn build(b: *std.Build) void {
const optimize: std.builtin.OptimizeMode = .Debug;
const foo = b.createModule(.{
.root_source_file = b.path("foo.zig"),
});
foo.addImport("foo", foo);
const exe = b.addExecutable(.{
.name = "test",
const main_mod = b.createModule(.{
.root_source_file = b.path("test.zig"),
.target = b.graph.host,
.optimize = optimize,
});
exe.root_module.addImport("foo", foo);
const foo_mod = b.createModule(.{
.root_source_file = b.path("foo.zig"),
});
main_mod.addImport("foo", foo_mod);
foo_mod.addImport("foo", foo_mod);
const exe = b.addExecutable(.{
.name = "test",
.root_module = main_mod,
});
const run = b.addRunArtifact(exe);
test_step.dependOn(&run.step);

View File

@ -6,16 +6,22 @@ pub fn build(b: *std.Build) void {
const optimize: std.builtin.OptimizeMode = .Debug;
const exe = b.addExecutable(.{
.name = "test",
const main_mod = b.createModule(.{
.root_source_file = b.path("test.zig"),
.target = b.graph.host,
.optimize = optimize,
});
exe.root_module.addAnonymousImport("foo", .{
const foo_mod = b.createModule(.{
.root_source_file = b.path("foo.zig"),
});
main_mod.addImport("foo", foo_mod);
const exe = b.addExecutable(.{
.name = "test",
.root_module = main_mod,
});
const run = b.addRunArtifact(exe);
test_step.dependOn(&run.step);
}

View File

@ -6,21 +6,26 @@ pub fn build(b: *std.Build) void {
const optimize: std.builtin.OptimizeMode = .Debug;
const shared = b.createModule(.{
.root_source_file = b.path("shared.zig"),
});
const exe = b.addExecutable(.{
.name = "test",
const main_mod = b.createModule(.{
.root_source_file = b.path("test.zig"),
.target = b.graph.host,
.optimize = optimize,
});
exe.root_module.addAnonymousImport("foo", .{
const foo_mod = b.createModule(.{
.root_source_file = b.path("foo.zig"),
.imports = &.{.{ .name = "shared", .module = shared }},
});
exe.root_module.addImport("shared", shared);
const shared_mod = b.createModule(.{
.root_source_file = b.path("shared.zig"),
});
main_mod.addImport("foo", foo_mod);
main_mod.addImport("shared", shared_mod);
foo_mod.addImport("shared", shared_mod);
const exe = b.addExecutable(.{
.name = "test",
.root_module = main_mod,
});
const run = b.addRunArtifact(exe);
test_step.dependOn(&run.step);

View File

@ -7,19 +7,22 @@ pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "depend_on_main_mod",
const main_mod = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
const foo_module = b.addModule("foo", .{
const foo_mod = b.createModule(.{
.root_source_file = b.path("src/foo.zig"),
});
foo_module.addImport("root2", &exe.root_module);
exe.root_module.addImport("foo", foo_module);
foo_mod.addImport("root2", main_mod);
main_mod.addImport("foo", foo_mod);
const exe = b.addExecutable(.{
.name = "depend_on_main_mod",
.root_module = main_mod,
});
const run_cmd = b.addRunArtifact(exe);
run_cmd.expectExitCode(0);

View File

@ -10,24 +10,30 @@ pub fn build(b: *std.Build) void {
const touch = b.addExecutable(.{
.name = "touch",
.root_source_file = touch_src,
.optimize = .Debug,
.target = target,
.root_module = b.createModule(.{
.root_source_file = touch_src,
.optimize = .Debug,
.target = target,
}),
});
const generated = b.addRunArtifact(touch).addOutputFileArg("subdir" ++ std.fs.path.sep_str ++ "generated.txt");
const exists_in = b.addExecutable(.{
.name = "exists_in",
.root_source_file = b.path("exists_in.zig"),
.optimize = .Debug,
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("exists_in.zig"),
.optimize = .Debug,
.target = target,
}),
});
const has_basename = b.addExecutable(.{
.name = "has_basename",
.root_source_file = b.path("has_basename.zig"),
.optimize = .Debug,
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("has_basename.zig"),
.optimize = .Debug,
.target = target,
}),
});
// Known path:

View File

@ -6,18 +6,21 @@ pub fn build(b: *std.Build) void {
const bootloader = b.addExecutable(.{
.name = "bootloader",
.root_source_file = b.path("bootloader.zig"),
.target = b.resolveTargetQuery(.{
.cpu_arch = .x86,
.os_tag = .freestanding,
.root_module = b.createModule(.{
.root_source_file = b.path("bootloader.zig"),
.target = b.resolveTargetQuery(.{
.cpu_arch = .x86,
.os_tag = .freestanding,
}),
.optimize = .ReleaseSmall,
}),
.optimize = .ReleaseSmall,
});
const exe = b.addTest(.{
const exe = b.addTest(.{ .root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.target = b.graph.host,
.optimize = .Debug,
});
}) });
exe.root_module.addAnonymousImport("bootloader.elf", .{
.root_source_file = bootloader.getEmittedBin(),
});

View File

@ -4,10 +4,11 @@ pub fn build(b: *std.Build) void {
const test_step = b.step("test", "Test it");
b.default_step = test_step;
const main = b.addTest(.{
const main = b.addTest(.{ .root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.target = b.graph.host,
.optimize = b.standardOptimizeOption(.{}),
});
}) });
// TODO: actually check these two artifacts for correctness
_ = main.getEmittedBin();
_ = main.getEmittedAsm();

View File

@ -8,9 +8,11 @@ pub fn build(b: *std.Build) void {
const obj = b.addObject(.{
.name = "main",
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = b.graph.host,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = b.graph.host,
}),
});
_ = obj.getEmittedAsm();
b.default_step.dependOn(&obj.step);

View File

@ -8,9 +8,11 @@ pub fn build(b: *std.Build) void {
const obj = b.addObject(.{
.name = "main",
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = b.graph.host,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = b.graph.host,
}),
});
_ = obj.getEmittedLlvmIr();
_ = obj.getEmittedLlvmBc();

View File

@ -21,9 +21,11 @@ pub fn build(b: *std.Build) void {
const main = b.addExecutable(.{
.name = "main",
.root_source_file = b.path("main.zig"),
.target = b.graph.host,
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.target = b.graph.host,
.optimize = optimize,
}),
});
const run = b.addRunArtifact(main);

View File

@ -8,22 +8,28 @@ pub fn build(b: *std.Build) void {
const obj = b.addObject(.{
.name = "exports",
.root_source_file = b.path("exports.zig"),
.target = b.graph.host,
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("exports.zig"),
.target = b.graph.host,
.optimize = optimize,
}),
});
const shared = b.addSharedLibrary(.{
.name = "shared",
.root_module = b.createModule(.{
.root_source_file = null,
.target = b.graph.host,
.optimize = optimize,
.link_libc = true,
}),
});
if (b.graph.host.result.abi == .msvc) shared.root_module.addCMacro("API", "__declspec(dllexport)");
shared.root_module.addCSourceFile(.{ .file = b.path("shared.c"), .flags = &.{} });
const test_exe = b.addTest(.{ .root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.target = b.graph.host,
.optimize = optimize,
.link_libc = true,
});
if (b.graph.host.result.abi == .msvc) shared.defineCMacro("API", "__declspec(dllexport)");
shared.addCSourceFile(.{ .file = b.path("shared.c"), .flags = &.{} });
const test_exe = b.addTest(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
});
}) });
test_exe.addObject(obj);
test_exe.linkLibrary(shared);

View File

@ -9,24 +9,30 @@ pub fn build(b: *std.Build) void {
const obj1 = b.addStaticLibrary(.{
.name = "obj1",
.root_source_file = b.path("obj1.zig"),
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("obj1.zig"),
.optimize = optimize,
.target = target,
}),
});
const obj2 = b.addStaticLibrary(.{
.name = "obj2",
.root_source_file = b.path("obj2.zig"),
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("obj2.zig"),
.optimize = optimize,
.target = target,
}),
});
const main = b.addTest(.{
const main_mod = b.createModule(.{
.root_source_file = b.path("main.zig"),
.target = b.graph.host,
.optimize = optimize,
});
main.linkLibrary(obj1);
main.linkLibrary(obj2);
main_mod.linkLibrary(obj1);
main_mod.linkLibrary(obj2);
const main = b.addTest(.{ .root_module = main_mod });
test_step.dependOn(&b.addRunArtifact(main).step);
}

View File

@ -8,18 +8,24 @@ pub fn build(b: *std.Build) void {
const libfoo = b.addStaticLibrary(.{
.name = "foo",
.target = b.resolveTargetQuery(.{}),
.optimize = .Debug,
.root_module = b.createModule(.{
.root_source_file = null,
.target = b.resolveTargetQuery(.{}),
.optimize = .Debug,
}),
});
libfoo.addCSourceFile(.{ .file = empty_c });
libfoo.root_module.addCSourceFile(.{ .file = empty_c });
const exe = b.addExecutable(.{
.name = "exe",
.target = b.resolveTargetQuery(.{}),
.optimize = .Debug,
.link_libc = true,
.root_module = b.createModule(.{
.root_source_file = null,
.target = b.resolveTargetQuery(.{}),
.optimize = .Debug,
.link_libc = true,
}),
});
exe.addCSourceFile(.{ .file = b.addWriteFiles().add("main.c",
exe.root_module.addCSourceFile(.{ .file = b.addWriteFiles().add("main.c",
\\#include <stdio.h>
\\#include <foo/a.h>
\\#include <foo/sub_dir/b.h>
@ -40,9 +46,10 @@ pub fn build(b: *std.Build) void {
if (libfoo.installed_headers_include_tree != null) std.debug.panic("include tree step was created before linking", .{});
// Link before we have registered all headers for installation,
// Link (and get the include tree) before we have registered all headers for installation,
// to verify that the lazily created write files step is properly taken into account.
exe.linkLibrary(libfoo);
exe.root_module.linkLibrary(libfoo);
_ = libfoo.getEmittedIncludeTree();
if (libfoo.installed_headers_include_tree == null) std.debug.panic("include tree step was not created after linking", .{});
@ -56,10 +63,13 @@ pub fn build(b: *std.Build) void {
const libbar = b.addStaticLibrary(.{
.name = "bar",
.target = b.resolveTargetQuery(.{}),
.optimize = .Debug,
.root_module = b.createModule(.{
.root_source_file = null,
.target = b.resolveTargetQuery(.{}),
.optimize = .Debug,
}),
});
libbar.addCSourceFile(.{ .file = empty_c });
libbar.root_module.addCSourceFile(.{ .file = empty_c });
libbar.installHeader(b.addWriteFiles().add("bar.h",
\\#define BAR_X "X"
\\
@ -78,9 +88,11 @@ pub fn build(b: *std.Build) void {
});
const check_exists = b.addExecutable(.{
.name = "check_exists",
.root_source_file = b.path("check_exists.zig"),
.target = b.resolveTargetQuery(.{}),
.optimize = .Debug,
.root_module = b.createModule(.{
.root_source_file = b.path("check_exists.zig"),
.target = b.resolveTargetQuery(.{}),
.optimize = .Debug,
}),
});
const run_check_exists = b.addRunArtifact(check_exists);
run_check_exists.addArgs(&.{

View File

@ -16,9 +16,11 @@ pub fn build(b: *std.Build) void {
const elf = b.addExecutable(.{
.name = "zig-nrf52-blink.elf",
.root_source_file = b.path("main.zig"),
.target = target,
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.target = target,
.optimize = optimize,
}),
});
const hex_step = elf.addObjCopy(.{

View File

@ -18,16 +18,19 @@ pub fn build(b: *std.Build) void {
const exe = b.addExecutable(.{
.name = "main",
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = null,
.optimize = optimize,
.target = target,
.link_libc = true,
}),
});
exe.addCSourceFile(.{ .file = b.path("main.m"), .flags = &.{} });
exe.addSystemIncludePath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/usr/include" }) });
exe.addSystemFrameworkPath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/System/Library/Frameworks" }) });
exe.addLibraryPath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/usr/lib" }) });
exe.linkFramework("Foundation");
exe.linkFramework("UIKit");
exe.linkLibC();
exe.root_module.addCSourceFile(.{ .file = b.path("main.m"), .flags = &.{} });
exe.root_module.addSystemIncludePath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/usr/include" }) });
exe.root_module.addSystemFrameworkPath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/System/Library/Frameworks" }) });
exe.root_module.addLibraryPath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/usr/lib" }) });
exe.root_module.linkFramework("Foundation", .{});
exe.root_module.linkFramework("UIKit", .{});
const check = exe.checkObject();
check.checkInHeaders();

View File

@ -15,9 +15,11 @@ pub fn build(b: *std.Build) void {
const exe = b.addExecutable(.{
.name = "zigtest",
.root_source_file = b.path("main.zig"),
.target = target,
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.target = target,
.optimize = optimize,
}),
});
b.installArtifact(exe);
@ -25,21 +27,21 @@ pub fn build(b: *std.Build) void {
"test.c",
};
exe.addCSourceFiles(.{ .files = &c_sources });
exe.linkLibC();
exe.root_module.addCSourceFiles(.{ .files = &c_sources });
exe.root_module.link_libc = true;
var i: i32 = 0;
while (i < 1000) : (i += 1) {
exe.defineCMacro("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
exe.root_module.addCMacro("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
}
exe.defineCMacro("FOO", "42");
exe.defineCMacro("BAR", "\"BAR\"");
exe.defineCMacro("BAZ",
exe.root_module.addCMacro("FOO", "42");
exe.root_module.addCMacro("BAR", "\"BAR\"");
exe.root_module.addCMacro("BAZ",
\\"\"BAZ\""
);
exe.defineCMacro("QUX", "\"Q\" \"UX\"");
exe.defineCMacro("QUUX", "\"QU\\\"UX\"");
exe.root_module.addCMacro("QUX", "\"Q\" \"UX\"");
exe.root_module.addCMacro("QUUX", "\"QU\\\"UX\"");
b.default_step.dependOn(&exe.step);

View File

@ -10,16 +10,18 @@ pub fn build(b: *std.Build) void {
const exe = b.addExecutable(.{
.name = "main",
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = target,
}),
});
const c_sources = [_][]const u8{
"test.c",
};
exe.addCSourceFiles(.{ .files = &c_sources });
exe.linkLibC();
exe.root_module.addCSourceFiles(.{ .files = &c_sources });
exe.root_module.link_libc = true;
const run_cmd = b.addRunArtifact(exe);
run_cmd.expectExitCode(0);

View File

@ -5,15 +5,24 @@ pub fn build(b: *std.Build) void {
b.default_step = test_step;
const test1 = b.addTest(.{
.root_source_file = b.path("test_root/empty.zig"),
.root_module = b.createModule(.{
.root_source_file = b.path("test_root/empty.zig"),
.target = b.graph.host,
}),
.test_runner = "src/main.zig",
});
const test2 = b.addTest(.{
.root_source_file = b.path("src/empty.zig"),
.root_module = b.createModule(.{
.root_source_file = b.path("src/empty.zig"),
.target = b.graph.host,
}),
.test_runner = "src/main.zig",
});
const test3 = b.addTest(.{
.root_source_file = b.path("empty.zig"),
.root_module = b.createModule(.{
.root_source_file = b.path("empty.zig"),
.target = b.graph.host,
}),
.test_runner = "src/main.zig",
});

View File

@ -9,9 +9,11 @@ pub fn build(b: *std.Build) void {
const obj = b.addObject(.{
.name = "test",
.root_source_file = b.path("test.zig"),
.target = target,
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("test.zig"),
.target = target,
.optimize = optimize,
}),
});
// TODO: actually check the output

View File

@ -16,20 +16,25 @@ pub fn build(b: *std.Build) void {
const optimize: std.builtin.OptimizeMode = .Debug;
const obj = b.addObject(.{
.name = "issue_5825",
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = target,
}),
});
const exe = b.addExecutable(.{
.name = "issue_5825",
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = null,
.optimize = optimize,
.target = target,
}),
});
exe.subsystem = .Console;
exe.linkSystemLibrary("kernel32");
exe.linkSystemLibrary("ntdll");
exe.addObject(obj);
exe.root_module.linkSystemLibrary("kernel32", .{});
exe.root_module.linkSystemLibrary("ntdll", .{});
exe.root_module.addObject(obj);
// TODO: actually check the output
_ = exe.getEmittedBin();

View File

@ -4,9 +4,10 @@ pub fn build(b: *std.Build) void {
const test_step = b.step("test", "Test it");
b.default_step = test_step;
const test_artifact = b.addTest(.{
const test_artifact = b.addTest(.{ .root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
});
.target = b.graph.host,
}) });
test_artifact.addIncludePath(b.path("a_directory"));
// TODO: actually check the output

View File

@ -15,11 +15,13 @@ pub fn build(b: *std.Build) !void {
const kernel = b.addExecutable(.{
.name = "kernel",
.root_source_file = b.path("./main.zig"),
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("./main.zig"),
.optimize = optimize,
.target = target,
}),
});
kernel.addObjectFile(b.path("./boot.S"));
kernel.root_module.addObjectFile(b.path("./boot.S"));
kernel.setLinkerScript(b.path("./linker.ld"));
b.installArtifact(kernel);

View File

@ -11,12 +11,14 @@ pub fn build(b: *std.Build) void {
{
const exe = b.addExecutable(.{
.name = "mt",
.root_source_file = b.path("mt.zig"),
.target = target,
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("mt.zig"),
.target = target,
.optimize = optimize,
.link_libcpp = true,
}),
});
exe.linkLibCpp();
exe.addCSourceFile(.{ .file = b.path("mt_doit.cpp") });
exe.root_module.addCSourceFile(.{ .file = b.path("mt_doit.cpp") });
link_step.dependOn(&exe.step);
b.installArtifact(exe);
run_step.dependOn(&b.addRunArtifact(exe).step);
@ -24,13 +26,15 @@ pub fn build(b: *std.Build) void {
{
const exe = b.addExecutable(.{
.name = "st",
.root_source_file = b.path("st.zig"),
.target = target,
.optimize = optimize,
.single_threaded = true,
.root_module = b.createModule(.{
.root_source_file = b.path("st.zig"),
.target = target,
.optimize = optimize,
.link_libcpp = true,
.single_threaded = true,
}),
});
exe.linkLibCpp();
exe.addCSourceFile(.{ .file = b.path("st_doit.cpp") });
exe.root_module.addCSourceFile(.{ .file = b.path("st_doit.cpp") });
link_step.dependOn(&exe.step);
b.installArtifact(exe);
run_step.dependOn(&b.addRunArtifact(exe).step);

View File

@ -12,17 +12,21 @@ pub fn build(b: *std.Build) void {
const lib = b.addSharedLibrary(.{
.name = "add",
.root_source_file = b.path("add.zig"),
.version = .{ .major = 1, .minor = 0, .patch = 0 },
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("add.zig"),
.optimize = optimize,
.target = target,
}),
});
const main = b.addExecutable(.{
.name = "main",
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = target,
}),
});
const run = b.addRunArtifact(main);

View File

@ -18,12 +18,14 @@ pub fn build(b: *std.Build) void {
fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
const exe = b.addExecutable(.{
.name = "test",
.root_source_file = b.path("main.zig"),
.target = b.graph.host,
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.target = b.graph.host,
.optimize = optimize,
.link_libc = true,
}),
});
exe.addCSourceFile(.{ .file = b.path("test.c"), .flags = &[_][]const u8{"-std=c11"} });
exe.linkLibC();
exe.root_module.addCSourceFile(.{ .file = b.path("test.c"), .flags = &[_][]const u8{"-std=c11"} });
const run_cmd = b.addRunArtifact(exe);
run_cmd.skip_foreign_checks = true;

View File

@ -9,22 +9,27 @@ pub fn build(b: *std.Build) void {
const obj = b.addObject(.{
.name = "base64",
.root_source_file = b.path("base64.zig"),
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("base64.zig"),
.optimize = optimize,
.target = target,
}),
});
const exe = b.addExecutable(.{
.name = "test",
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = null,
.optimize = optimize,
.target = target,
.link_libc = true,
}),
});
exe.addCSourceFile(.{
exe.root_module.addCSourceFile(.{
.file = b.path("test.c"),
.flags = &[_][]const u8{"-std=c99"},
});
exe.addObject(obj);
exe.linkSystemLibrary("c");
exe.root_module.addObject(obj);
b.default_step.dependOn(&exe.step);

View File

@ -1,11 +1,11 @@
const std = @import("std");
pub fn build(b: *std.Build) void {
const main = b.addTest(.{
const main = b.addTest(.{ .root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = b.graph.host,
.optimize = .Debug,
});
}) });
const options = b.addOptions();
main.addOptions("build_options", options);

View File

@ -11,9 +11,11 @@ pub fn build(b: *std.Build) void {
});
const main = b.addTest(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = target,
}),
});
main.pie = true;

View File

@ -8,9 +8,11 @@ pub fn build(b: *std.Build) void {
const exe = b.addExecutable(.{
.name = "test",
.root_source_file = b.path("test.zig"),
.optimize = optimize,
.target = b.graph.host,
.root_module = b.createModule(.{
.root_source_file = b.path("test.zig"),
.optimize = optimize,
.target = b.graph.host,
}),
});
exe.root_module.addAnonymousImport("my_pkg", .{ .root_source_file = b.path("pkg.zig") });

View File

@ -9,9 +9,11 @@ pub fn build(b: *std.Build) void {
const exe = b.addExecutable(.{
.name = "create-file",
.root_source_file = b.path("main.zig"),
.target = target,
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.target = target,
.optimize = optimize,
}),
});
{

View File

@ -9,9 +9,11 @@ pub fn build(b: *std.Build) void {
const create_file_exe = b.addExecutable(.{
.name = "create_file",
.root_source_file = b.path("create_file.zig"),
.target = target,
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("create_file.zig"),
.target = target,
.optimize = optimize,
}),
});
const create_first = b.addRunArtifact(create_file_exe);

View File

@ -15,16 +15,20 @@ pub fn build(b: *std.Build) void {
const main = b.addExecutable(.{
.name = "main",
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = target,
}),
});
const create_symlink_exe = b.addExecutable(.{
.name = "create-symlink",
.root_source_file = b.path("create-symlink.zig"),
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("create-symlink.zig"),
.optimize = optimize,
.target = target,
}),
});
var run_create_symlink = b.addRunArtifact(create_symlink_exe);

View File

@ -8,23 +8,28 @@ pub fn build(b: *std.Build) void {
const target = b.graph.host;
const lib = b.addSharedLibrary(.{
.name = "mathtest",
.root_source_file = b.path("mathtest.zig"),
.version = .{ .major = 1, .minor = 0, .patch = 0 },
.target = target,
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("mathtest.zig"),
.target = target,
.optimize = optimize,
}),
});
const exe = b.addExecutable(.{
.name = "test",
.target = target,
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = null,
.target = target,
.optimize = optimize,
.link_libc = true,
}),
});
exe.addCSourceFile(.{
exe.root_module.addCSourceFile(.{
.file = b.path("test.c"),
.flags = &[_][]const u8{"-std=c99"},
});
exe.linkLibrary(lib);
exe.linkSystemLibrary("c");
exe.root_module.linkLibrary(lib);
const run_cmd = b.addRunArtifact(exe);
test_step.dependOn(&run_cmd.step);

View File

@ -42,11 +42,13 @@ pub fn build(b: *std.Build) void {
if (case.is_exe) {
const exe = b.addExecutable(.{
.name = std.fs.path.stem(case.src_path),
.root_source_file = b.path(case.src_path),
.optimize = optimize,
.target = resolved_target,
.root_module = b.createModule(.{
.root_source_file = b.path(case.src_path),
.optimize = optimize,
.target = resolved_target,
}),
});
if (case.link_libc) exe.linkLibC();
if (case.link_libc) exe.root_module.link_libc = true;
_ = exe.getEmittedBin();
@ -56,11 +58,13 @@ pub fn build(b: *std.Build) void {
if (case.is_test) {
const exe = b.addTest(.{
.name = std.fs.path.stem(case.src_path),
.root_source_file = b.path(case.src_path),
.optimize = optimize,
.target = resolved_target,
.root_module = b.createModule(.{
.root_source_file = b.path(case.src_path),
.optimize = optimize,
.target = resolved_target,
}),
});
if (case.link_libc) exe.linkLibC();
if (case.link_libc) exe.root_module.link_libc = true;
const run = b.addRunArtifact(exe);
step.dependOn(&run.step);

View File

@ -20,11 +20,13 @@ pub fn build(b: *std.Build) void {
{
const exe = b.addExecutable(.{
.name = "unwind_fp",
.root_source_file = b.path("unwind.zig"),
.target = target,
.optimize = optimize,
.unwind_tables = if (target.result.isDarwin()) .@"async" else null,
.omit_frame_pointer = false,
.root_module = b.createModule(.{
.root_source_file = b.path("unwind.zig"),
.target = target,
.optimize = optimize,
.unwind_tables = if (target.result.isDarwin()) .@"async" else null,
.omit_frame_pointer = false,
}),
});
const run_cmd = b.addRunArtifact(exe);
@ -43,11 +45,13 @@ pub fn build(b: *std.Build) void {
{
const exe = b.addExecutable(.{
.name = "unwind_nofp",
.root_source_file = b.path("unwind.zig"),
.target = target,
.optimize = optimize,
.unwind_tables = .@"async",
.omit_frame_pointer = true,
.root_module = b.createModule(.{
.root_source_file = b.path("unwind.zig"),
.target = target,
.optimize = optimize,
.unwind_tables = .@"async",
.omit_frame_pointer = true,
}),
});
const run_cmd = b.addRunArtifact(exe);
@ -66,27 +70,32 @@ pub fn build(b: *std.Build) void {
{
const c_shared_lib = b.addSharedLibrary(.{
.name = "c_shared_lib",
.target = target,
.optimize = optimize,
.strip = false,
.root_module = b.createModule(.{
.root_source_file = null,
.target = target,
.optimize = optimize,
.link_libc = true,
.strip = false,
}),
});
if (target.result.os.tag == .windows)
c_shared_lib.defineCMacro("LIB_API", "__declspec(dllexport)");
c_shared_lib.root_module.addCMacro("LIB_API", "__declspec(dllexport)");
c_shared_lib.addCSourceFile(.{
c_shared_lib.root_module.addCSourceFile(.{
.file = b.path("shared_lib.c"),
.flags = &.{"-fomit-frame-pointer"},
});
c_shared_lib.linkLibC();
const exe = b.addExecutable(.{
.name = "shared_lib_unwind",
.root_source_file = b.path("shared_lib_unwind.zig"),
.target = target,
.optimize = optimize,
.unwind_tables = if (target.result.isDarwin()) .@"async" else null,
.omit_frame_pointer = true,
.root_module = b.createModule(.{
.root_source_file = b.path("shared_lib_unwind.zig"),
.target = target,
.optimize = optimize,
.unwind_tables = if (target.result.isDarwin()) .@"async" else null,
.omit_frame_pointer = true,
}),
});
exe.linkLibrary(c_shared_lib);
@ -117,14 +126,16 @@ pub fn build(b: *std.Build) void {
inline for (no_os_targets) |os_tag| {
const exe = b.addExecutable(.{
.name = "unwind_freestanding",
.root_source_file = b.path("unwind_freestanding.zig"),
.target = b.resolveTargetQuery(.{
.cpu_arch = .x86_64,
.os_tag = os_tag,
.root_module = b.createModule(.{
.root_source_file = b.path("unwind_freestanding.zig"),
.target = b.resolveTargetQuery(.{
.cpu_arch = .x86_64,
.os_tag = os_tag,
}),
.optimize = optimize,
.unwind_tables = null,
.omit_frame_pointer = false,
}),
.optimize = optimize,
.unwind_tables = null,
.omit_frame_pointer = false,
});
// This "freestanding" binary is runnable because it invokes the

View File

@ -8,18 +8,22 @@ pub fn build(b: *std.Build) void {
const foo = b.addStaticLibrary(.{
.name = "foo",
.optimize = optimize,
.target = b.graph.host,
.root_module = b.createModule(.{
.root_source_file = null,
.optimize = optimize,
.target = b.graph.host,
}),
});
foo.addCSourceFile(.{ .file = b.path("foo.c"), .flags = &[_][]const u8{} });
foo.addIncludePath(b.path("."));
foo.root_module.addCSourceFile(.{ .file = b.path("foo.c"), .flags = &[_][]const u8{} });
foo.root_module.addIncludePath(b.path("."));
const test_exe = b.addTest(.{
const test_exe = b.addTest(.{ .root_module = b.createModule(.{
.root_source_file = b.path("foo.zig"),
.target = b.graph.host,
.optimize = optimize,
});
test_exe.linkLibrary(foo);
test_exe.addIncludePath(b.path("."));
}) });
test_exe.root_module.linkLibrary(foo);
test_exe.root_module.addIncludePath(b.path("."));
test_step.dependOn(&b.addRunArtifact(test_exe).step);
}

View File

@ -9,10 +9,12 @@ pub fn build(b: *std.Build) void {
const main = b.addExecutable(.{
.name = "main",
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = target,
.strip = true,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = target,
.strip = true,
}),
});
// TODO: actually check the output

View File

@ -7,9 +7,12 @@ pub fn build(b: *std.Build) void {
const optimize: std.builtin.OptimizeMode = .Debug;
const main = b.addTest(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.strip = true,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.target = b.graph.host,
.optimize = optimize,
.strip = true,
}),
});
test_step.dependOn(&b.addRunArtifact(main).step);

View File

@ -1,19 +1,21 @@
const std = @import("std");
pub fn build(b: *std.Build) void {
const t = b.addTest(.{
const test_mod = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = b.graph.host,
});
const module1 = b.createModule(.{ .root_source_file = b.path("module1/main.zig") });
const module2 = b.createModule(.{ .root_source_file = b.path("module2/main.zig") });
module2.addImport("module1", module1);
test_mod.addImport("module2", module2);
const t = b.addTest(.{
.root_module = test_mod,
.test_runner = b.path("test_runner/main.zig"),
});
const module1 = b.createModule(.{ .root_source_file = b.path("module1/main.zig") });
const module2 = b.createModule(.{
.root_source_file = b.path("module2/main.zig"),
.imports = &.{.{ .name = "module1", .module = module1 }},
});
t.root_module.addImport("module2", module2);
const test_step = b.step("test", "Run unit tests");
test_step.dependOn(&b.addRunArtifact(t).step);
b.default_step = test_step;

View File

@ -6,9 +6,10 @@ pub fn build(b: *std.Build) void {
const test_step = b.step("test", "Test the program");
b.default_step = test_step;
const test_exe = b.addTest(.{
const test_exe = b.addTest(.{ .root_module = b.createModule(.{
.target = b.graph.host,
.root_source_file = b.path("test.zig"),
});
}) });
test_exe.test_runner = b.path("test_runner.zig");
const test_run = b.addRunArtifact(test_exe);

View File

@ -6,11 +6,12 @@ pub fn build(b: *std.Build) void {
const optimize: std.builtin.OptimizeMode = .Debug;
const main = b.addTest(.{
const main = b.addTest(.{ .root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.target = b.graph.host,
.optimize = optimize,
});
main.addIncludePath(b.path("."));
}) });
main.root_module.addIncludePath(b.path("."));
test_step.dependOn(&b.addRunArtifact(main).step);
}

View File

@ -11,32 +11,39 @@ pub fn build(b: *std.Build) !void {
const lib_gnu = b.addStaticLibrary(.{
.name = "toargv-gnu",
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{
.abi = .gnu,
.root_module = b.createModule(.{
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{
.abi = .gnu,
}),
.optimize = optimize,
}),
.optimize = optimize,
});
const verify_gnu = b.addExecutable(.{
.name = "verify-gnu",
.target = b.resolveTargetQuery(.{
.abi = .gnu,
.root_module = b.createModule(.{
.root_source_file = null,
.target = b.resolveTargetQuery(.{
.abi = .gnu,
}),
.optimize = optimize,
}),
.optimize = optimize,
});
verify_gnu.addCSourceFile(.{
verify_gnu.root_module.addCSourceFile(.{
.file = b.path("verify.c"),
.flags = &.{ "-DUNICODE", "-D_UNICODE" },
});
verify_gnu.mingw_unicode_entry_point = true;
verify_gnu.linkLibrary(lib_gnu);
verify_gnu.linkLibC();
verify_gnu.root_module.linkLibrary(lib_gnu);
verify_gnu.root_module.link_libc = true;
const fuzz = b.addExecutable(.{
.name = "fuzz",
.root_source_file = b.path("fuzz.zig"),
.target = b.graph.host,
.optimize = optimize,
.root_module = b.createModule(.{
.root_source_file = b.path("fuzz.zig"),
.target = b.graph.host,
.optimize = optimize,
}),
});
const fuzz_max_iterations = b.option(u64, "iterations", "The max fuzz iterations (default: 100)") orelse 100;
@ -69,25 +76,30 @@ pub fn build(b: *std.Build) !void {
if (has_msvc) {
const lib_msvc = b.addStaticLibrary(.{
.name = "toargv-msvc",
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{
.abi = .msvc,
.root_module = b.createModule(.{
.root_source_file = b.path("lib.zig"),
.target = b.resolveTargetQuery(.{
.abi = .msvc,
}),
.optimize = optimize,
}),
.optimize = optimize,
});
const verify_msvc = b.addExecutable(.{
.name = "verify-msvc",
.target = b.resolveTargetQuery(.{
.abi = .msvc,
.root_module = b.createModule(.{
.root_source_file = null,
.target = b.resolveTargetQuery(.{
.abi = .msvc,
}),
.optimize = optimize,
}),
.optimize = optimize,
});
verify_msvc.addCSourceFile(.{
verify_msvc.root_module.addCSourceFile(.{
.file = b.path("verify.c"),
.flags = &.{ "-DUNICODE", "-D_UNICODE" },
});
verify_msvc.linkLibrary(lib_msvc);
verify_msvc.linkLibC();
verify_msvc.root_module.linkLibrary(lib_msvc);
verify_msvc.root_module.link_libc = true;
const run_msvc = b.addRunArtifact(fuzz);
run_msvc.setName("fuzz-msvc");

View File

@ -12,16 +12,20 @@ pub fn build(b: *std.Build) !void {
const echo_args = b.addExecutable(.{
.name = "echo-args",
.root_source_file = b.path("echo-args.zig"),
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("echo-args.zig"),
.optimize = optimize,
.target = target,
}),
});
const test_exe = b.addExecutable(.{
.name = "test",
.root_source_file = b.path("test.zig"),
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("test.zig"),
.optimize = optimize,
.target = target,
}),
});
const run = b.addRunArtifact(test_exe);
@ -33,9 +37,11 @@ pub fn build(b: *std.Build) !void {
const fuzz = b.addExecutable(.{
.name = "fuzz",
.root_source_file = b.path("fuzz.zig"),
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("fuzz.zig"),
.optimize = optimize,
.target = target,
}),
});
const fuzz_max_iterations = b.option(u64, "iterations", "The max fuzz iterations (default: 100)") orelse 100;

View File

@ -13,11 +13,14 @@ pub fn build(b: *std.Build) void {
{
const exe = b.addExecutable(.{
.name = "main",
.target = target,
.optimize = .Debug,
.link_libc = true,
.root_module = b.createModule(.{
.root_source_file = null,
.target = target,
.optimize = .Debug,
.link_libc = true,
}),
});
exe.addCSourceFile(.{ .file = b.path("main.c") });
exe.root_module.addCSourceFile(.{ .file = b.path("main.c") });
_ = exe.getEmittedBin();
test_step.dependOn(&exe.step);
@ -26,12 +29,15 @@ pub fn build(b: *std.Build) void {
{
const exe = b.addExecutable(.{
.name = "wmain",
.target = target,
.optimize = .Debug,
.link_libc = true,
.root_module = b.createModule(.{
.root_source_file = null,
.target = target,
.optimize = .Debug,
.link_libc = true,
}),
});
exe.mingw_unicode_entry_point = true;
exe.addCSourceFile(.{ .file = b.path("wmain.c") });
exe.root_module.addCSourceFile(.{ .file = b.path("wmain.c") });
_ = exe.getEmittedBin();
test_step.dependOn(&exe.step);
@ -40,12 +46,15 @@ pub fn build(b: *std.Build) void {
{
const exe = b.addExecutable(.{
.name = "winmain",
.target = target,
.optimize = .Debug,
.link_libc = true,
.root_module = b.createModule(.{
.root_source_file = null,
.target = target,
.optimize = .Debug,
.link_libc = true,
}),
});
// Note: `exe.subsystem = .Windows;` is not necessary
exe.addCSourceFile(.{ .file = b.path("winmain.c") });
exe.root_module.addCSourceFile(.{ .file = b.path("winmain.c") });
_ = exe.getEmittedBin();
test_step.dependOn(&exe.step);
@ -54,13 +63,16 @@ pub fn build(b: *std.Build) void {
{
const exe = b.addExecutable(.{
.name = "wwinmain",
.target = target,
.optimize = .Debug,
.link_libc = true,
.root_module = b.createModule(.{
.root_source_file = null,
.target = target,
.optimize = .Debug,
.link_libc = true,
}),
});
exe.mingw_unicode_entry_point = true;
// Note: `exe.subsystem = .Windows;` is not necessary
exe.addCSourceFile(.{ .file = b.path("wwinmain.c") });
exe.root_module.addCSourceFile(.{ .file = b.path("wwinmain.c") });
_ = exe.getEmittedBin();
test_step.dependOn(&exe.step);

View File

@ -28,11 +28,13 @@ fn add(
) void {
const exe = b.addExecutable(.{
.name = "zig_resource_test",
.root_source_file = b.path("main.zig"),
.target = target,
.optimize = .Debug,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.target = target,
.optimize = .Debug,
}),
});
exe.addWin32ResourceFile(.{
exe.root_module.addWin32ResourceFile(.{
.file = b.path("res/zig.rc"),
.flags = &.{"/c65001"}, // UTF-8 code page
.include_paths = &.{

View File

@ -12,16 +12,20 @@ pub fn build(b: *std.Build) void {
const hello = b.addExecutable(.{
.name = "hello",
.root_source_file = b.path("hello.zig"),
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("hello.zig"),
.optimize = optimize,
.target = target,
}),
});
const main = b.addExecutable(.{
.name = "main",
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = target,
.root_module = b.createModule(.{
.root_source_file = b.path("main.zig"),
.optimize = optimize,
.target = target,
}),
});
const run = b.addRunArtifact(main);

View File

@ -11,7 +11,7 @@ pub fn build(b: *std.Build) void {
}
fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void {
const unit_tests = b.addTest(.{
const unit_tests = b.addTest(.{ .root_module = b.createModule(.{
.root_source_file = b.path("src/main.zig"),
.target = b.resolveTargetQuery(.{
.os_tag = .wasi,
@ -19,7 +19,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize
.cpu_features_add = std.Target.wasm.featureSet(&.{.bulk_memory}),
}),
.optimize = optimize,
});
}) });
const run_unit_tests = b.addRunArtifact(unit_tests);
run_unit_tests.skip_foreign_checks = true;

View File

@ -1106,9 +1106,11 @@ pub fn addStackTraceTests(
) *Step {
const check_exe = b.addExecutable(.{
.name = "check-stack-trace",
.root_source_file = b.path("test/src/check-stack-trace.zig"),
.target = b.graph.host,
.optimize = .Debug,
.root_module = b.createModule(.{
.root_source_file = b.path("test/src/check-stack-trace.zig"),
.target = b.graph.host,
.optimize = .Debug,
}),
});
const cases = b.allocator.create(StackTracesContext) catch @panic("OOM");
@ -1330,7 +1332,7 @@ pub fn addCliTests(b: *std.Build) *Step {
run5.step.dependOn(&run4.step);
const unformatted_code_utf16 = "\xff\xfe \x00 \x00 \x00 \x00/\x00/\x00 \x00n\x00o\x00 \x00r\x00e\x00a\x00s\x00o\x00n\x00";
const fmt6_path = std.fs.path.join(b.allocator, &.{ tmp_path, "fmt6.zig" }) catch @panic("OOM");
const fmt6_path = b.pathJoin(&.{ tmp_path, "fmt6.zig" });
const write6 = b.addUpdateSourceFiles();
write6.addBytesToSource(unformatted_code_utf16, fmt6_path);
write6.step.dependOn(&run5.step);
@ -1514,18 +1516,20 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
options.max_rss;
const these_tests = b.addTest(.{
.root_source_file = b.path(options.root_src),
.optimize = test_target.optimize_mode,
.target = resolved_target,
.root_module = b.createModule(.{
.root_source_file = b.path(options.root_src),
.optimize = test_target.optimize_mode,
.target = resolved_target,
.link_libc = test_target.link_libc,
.pic = test_target.pic,
.strip = test_target.strip,
.single_threaded = test_target.single_threaded,
}),
.max_rss = max_rss,
.filters = options.test_filters,
.link_libc = test_target.link_libc,
.single_threaded = test_target.single_threaded,
.use_llvm = test_target.use_llvm,
.use_lld = test_target.use_lld,
.zig_lib_dir = b.path("lib"),
.pic = test_target.pic,
.strip = test_target.strip,
});
if (options.no_builtin) these_tests.no_builtin = true;
if (options.build_options) |build_options| {
@ -1561,12 +1565,17 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
var altered_query = test_target.target;
altered_query.ofmt = null;
const compile_c = b.addExecutable(.{
.name = qualified_name,
const compile_c = b.createModule(.{
.root_source_file = null,
.link_libc = test_target.link_libc,
.target = b.resolveTargetQuery(altered_query),
});
const compile_c_exe = b.addExecutable(.{
.name = qualified_name,
.root_module = compile_c,
.zig_lib_dir = b.path("lib"),
});
compile_c.addCSourceFile(.{
.file = these_tests.getEmittedBin(),
.flags = &.{
@ -1611,22 +1620,22 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
continue;
}
if (test_target.link_libc == false) {
compile_c.subsystem = .Console;
compile_c.linkSystemLibrary("kernel32");
compile_c.linkSystemLibrary("ntdll");
compile_c_exe.subsystem = .Console;
compile_c.linkSystemLibrary("kernel32", .{});
compile_c.linkSystemLibrary("ntdll", .{});
}
if (mem.eql(u8, options.name, "std")) {
if (test_target.link_libc == false) {
compile_c.linkSystemLibrary("shell32");
compile_c.linkSystemLibrary("advapi32");
compile_c.linkSystemLibrary("shell32", .{});
compile_c.linkSystemLibrary("advapi32", .{});
}
compile_c.linkSystemLibrary("crypt32");
compile_c.linkSystemLibrary("ws2_32");
compile_c.linkSystemLibrary("ole32");
compile_c.linkSystemLibrary("crypt32", .{});
compile_c.linkSystemLibrary("ws2_32", .{});
compile_c.linkSystemLibrary("ole32", .{});
}
}
const run = b.addRunArtifact(compile_c);
const run = b.addRunArtifact(compile_c_exe);
run.skip_foreign_checks = true;
run.enableTestRunnerMode();
run.setName(b.fmt("run test {s}", .{qualified_name}));
@ -1675,6 +1684,20 @@ pub fn addCAbiTests(b: *std.Build, options: CAbiTestOptions) *Step {
continue;
}
const test_mod = b.createModule(.{
.root_source_file = b.path("test/c_abi/main.zig"),
.target = resolved_target,
.optimize = optimize_mode,
.link_libc = true,
.pic = c_abi_target.pic,
.strip = c_abi_target.strip,
});
test_mod.addCSourceFile(.{
.file = b.path("test/c_abi/cfuncs.c"),
.flags = &.{"-std=c99"},
});
for (c_abi_target.c_defines) |define| test_mod.addCMacro(define, "1");
const test_step = b.addTest(.{
.name = b.fmt("test-c-abi-{s}-{s}-{s}{s}{s}{s}", .{
triple_txt,
@ -1691,20 +1714,10 @@ pub fn addCAbiTests(b: *std.Build, options: CAbiTestOptions) *Step {
if (c_abi_target.use_lld == false) "-no-lld" else "",
if (c_abi_target.pic == true) "-pic" else "",
}),
.root_source_file = b.path("test/c_abi/main.zig"),
.target = resolved_target,
.optimize = optimize_mode,
.link_libc = true,
.root_module = test_mod,
.use_llvm = c_abi_target.use_llvm,
.use_lld = c_abi_target.use_lld,
.pic = c_abi_target.pic,
.strip = c_abi_target.strip,
});
test_step.addCSourceFile(.{
.file = b.path("test/c_abi/cfuncs.c"),
.flags = &.{"-std=c99"},
});
for (c_abi_target.c_defines) |define| test_step.defineCMacro(define, null);
// This test is intentionally trying to check if the external ABI is
// done properly. LTO would be a hindrance to this.
@ -1784,9 +1797,11 @@ pub fn addDebuggerTests(b: *std.Build, options: DebuggerContext.Options) ?*Step
pub fn addIncrementalTests(b: *std.Build, test_step: *Step) !void {
const incr_check = b.addExecutable(.{
.name = "incr-check",
.root_source_file = b.path("tools/incr-check.zig"),
.target = b.graph.host,
.optimize = .Debug,
.root_module = b.createModule(.{
.root_source_file = b.path("tools/incr-check.zig"),
.target = b.graph.host,
.optimize = .Debug,
}),
});
var dir = try b.build_root.handle.openDir("test/incremental", .{ .iterate = true });