Skip to content

Commit

Permalink
zig build system: change target, compilation, and module APIs
Browse files Browse the repository at this point in the history
Introduce the concept of "target query" and "resolved target". A target
query is what the user specifies, with some things left to default. A
resolved target has the default things discovered and populated.
In the future, std.zig.CrossTarget will be rename to std.Target.Query.
Introduces `std.Build.resolveTargetQuery` to get from one to the other.

The concept of `main_mod_path` is gone, no longer supported. You have to
put the root source file at the module root now.

* remove deprecated API
* update build.zig for the breaking API changes in this branch
* move std.Build.Step.Compile.BuildId to std.zig.BuildId
* add more options to std.Build.ExecutableOptions, std.Build.ObjectOptions,
  std.Build.SharedLibraryOptions, std.Build.StaticLibraryOptions, and
  std.Build.TestOptions.
* remove `std.Build.constructCMacro`. There is no use for this API.
* deprecate `std.Build.Step.Compile.defineCMacro`. Instead,
  `std.Build.Module.addCMacro` is provided.
  - remove `std.Build.Step.Compile.defineCMacroRaw`.
* deprecate `std.Build.Step.Compile.linkFrameworkNeeded`
  - use `std.Build.Module.linkFramework`
* deprecate `std.Build.Step.Compile.linkFrameworkWeak`
  - use `std.Build.Module.linkFramework`
* move more logic into `std.Build.Module`
* allow `target` and `optimize` to be `null` when creating a Module.
  Along with other fields, those unspecified options will be inherited
  from parent `Module` when inserted into an import table.
* the `target` field of `addExecutable` is now required. pass `b.host`
  to get the host target.
  • Loading branch information
andrewrk committed Jan 2, 2024
1 parent 579f572 commit 142471f
Show file tree
Hide file tree
Showing 122 changed files with 1,812 additions and 1,338 deletions.
92 changes: 53 additions & 39 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ pub fn build(b: *std.Build) !void {
const docgen_exe = b.addExecutable(.{
.name = "docgen",
.root_source_file = .{ .path = "tools/docgen.zig" },
.target = .{},
.target = b.host,
.optimize = .Debug,
.single_threaded = single_threaded,
});
docgen_exe.single_threaded = single_threaded;

const docgen_cmd = b.addRunArtifact(docgen_exe);
docgen_cmd.addArgs(&.{ "--zig", b.zig_exe });
Expand Down Expand Up @@ -89,11 +89,11 @@ pub fn build(b: *std.Build) !void {
const check_case_exe = b.addExecutable(.{
.name = "check-case",
.root_source_file = .{ .path = "test/src/Cases.zig" },
.target = b.host,
.optimize = optimize,
.main_mod_path = .{ .path = "." },
.single_threaded = single_threaded,
});
check_case_exe.stack_size = stack_size;
check_case_exe.single_threaded = single_threaded;

const skip_debug = b.option(bool, "skip-debug", "Main test suite skips debug builds") orelse false;
const skip_release = b.option(bool, "skip-release", "Main test suite skips release builds") orelse false;
Expand Down Expand Up @@ -194,14 +194,18 @@ pub fn build(b: *std.Build) !void {
break :blk 4;
};

const exe = addCompilerStep(b, optimize, target);
exe.strip = strip;
const exe = addCompilerStep(b, .{
.optimize = optimize,
.target = target,
.strip = strip,
.sanitize_thread = sanitize_thread,
.single_threaded = single_threaded,
});
exe.pie = pie;
exe.sanitize_thread = sanitize_thread;
exe.entitlements = entitlements;

exe.build_id = b.option(
std.Build.Step.Compile.BuildId,
std.zig.BuildId,
"build-id",
"Request creation of '.note.gnu.build-id' section",
);
Expand All @@ -217,9 +221,7 @@ pub fn build(b: *std.Build) !void {

test_step.dependOn(&exe.step);

exe.single_threaded = single_threaded;

if (target.isWindows() and target.getAbi() == .gnu) {
if (target.target.os.tag == .windows and target.target.abi == .gnu) {
// LTO is currently broken on mingw, this can be removed when it's fixed.
exe.want_lto = false;
check_case_exe.want_lto = false;
Expand All @@ -230,7 +232,7 @@ pub fn build(b: *std.Build) !void {
exe.use_lld = use_llvm;

const exe_options = b.addOptions();
exe.addOptions("build_options", exe_options);
exe.root_module.addOptions("build_options", exe_options);

exe_options.addOption(u32, "mem_leak_frames", mem_leak_frames);
exe_options.addOption(bool, "skip_non_native", skip_non_native);
Expand Down Expand Up @@ -345,7 +347,7 @@ pub fn build(b: *std.Build) !void {
try addStaticLlvmOptionsToExe(exe);
try addStaticLlvmOptionsToExe(check_case_exe);
}
if (target.isWindows()) {
if (target.target.os.tag == .windows) {
inline for (.{ exe, check_case_exe }) |artifact| {
artifact.linkSystemLibrary("version");
artifact.linkSystemLibrary("uuid");
Expand All @@ -369,19 +371,19 @@ pub fn build(b: *std.Build) !void {
);

// On mingw, we need to opt into windows 7+ to get some features required by tracy.
const tracy_c_flags: []const []const u8 = if (target.isWindows() and target.getAbi() == .gnu)
const tracy_c_flags: []const []const u8 = if (target.target.os.tag == .windows and target.target.abi == .gnu)
&[_][]const u8{ "-DTRACY_ENABLE=1", "-fno-sanitize=undefined", "-D_WIN32_WINNT=0x601" }
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 });
if (!enable_llvm) {
exe.linkSystemLibraryName("c++");
exe.root_module.linkSystemLibrary("c++", .{ .use_pkg_config = .no });
}
exe.linkLibC();

if (target.isWindows()) {
if (target.target.os.tag == .windows) {
exe.linkSystemLibrary("dbghelp");
exe.linkSystemLibrary("ws2_32");
}
Expand All @@ -390,7 +392,7 @@ pub fn build(b: *std.Build) !void {
const test_filter = b.option([]const u8, "test-filter", "Skip tests that do not match filter");

const test_cases_options = b.addOptions();
check_case_exe.addOptions("build_options", test_cases_options);
check_case_exe.root_module.addOptions("build_options", test_cases_options);

test_cases_options.addOption(bool, "enable_tracy", false);
test_cases_options.addOption(bool, "enable_logging", enable_logging);
Expand Down Expand Up @@ -540,16 +542,19 @@ pub fn build(b: *std.Build) !void {
fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
const semver = try std.SemanticVersion.parse(version);

var target: std.zig.CrossTarget = .{
var target_query: std.zig.CrossTarget = .{
.cpu_arch = .wasm32,
.os_tag = .wasi,
};
target.cpu_features_add.addFeature(@intFromEnum(std.Target.wasm.Feature.bulk_memory));
target_query.cpu_features_add.addFeature(@intFromEnum(std.Target.wasm.Feature.bulk_memory));

const exe = addCompilerStep(b, .ReleaseSmall, target);
const exe = addCompilerStep(b, .{
.optimize = .ReleaseSmall,
.target = b.resolveTargetQuery(target_query),
});

const exe_options = b.addOptions();
exe.addOptions("build_options", exe_options);
exe.root_module.addOptions("build_options", exe_options);

exe_options.addOption(u32, "mem_leak_frames", 0);
exe_options.addOption(bool, "have_llvm", false);
Expand Down Expand Up @@ -584,33 +589,40 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
update_zig1_step.dependOn(&copy_zig_h.step);
}

fn addCompilerStep(
b: *std.Build,
const AddCompilerStepOptions = struct {
optimize: std.builtin.OptimizeMode,
target: std.zig.CrossTarget,
) *std.Build.Step.Compile {
target: std.Build.ResolvedTarget,
strip: ?bool = null,
sanitize_thread: ?bool = null,
single_threaded: ?bool = null,
};

fn addCompilerStep(b: *std.Build, options: AddCompilerStepOptions) *std.Build.Step.Compile {
const exe = b.addExecutable(.{
.name = "zig",
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
.target = options.target,
.optimize = options.optimize,
.max_rss = 7_000_000_000,
.strip = options.strip,
.sanitize_thread = options.sanitize_thread,
.single_threaded = options.single_threaded,
});
exe.stack_size = stack_size;

const aro_options = b.addOptions();
aro_options.addOption([]const u8, "version_str", "aro-zig");
const aro_options_module = aro_options.createModule();
const aro_backend = b.createModule(.{
.source_file = .{ .path = "deps/aro/backend.zig" },
.dependencies = &.{.{
.root_source_file = .{ .path = "deps/aro/backend.zig" },
.imports = &.{.{
.name = "build_options",
.module = aro_options_module,
}},
});
const aro_module = b.createModule(.{
.source_file = .{ .path = "deps/aro/aro.zig" },
.dependencies = &.{
.root_source_file = .{ .path = "deps/aro/aro.zig" },
.imports = &.{
.{
.name = "build_options",
.module = aro_options_module,
Expand All @@ -625,7 +637,7 @@ fn addCompilerStep(
},
});

exe.addModule("aro", aro_module);
exe.root_module.addImport("aro", aro_module);
return exe;
}

Expand All @@ -649,7 +661,7 @@ fn addCmakeCfgOptionsToExe(
exe: *std.Build.Step.Compile,
use_zig_libcxx: bool,
) !void {
if (exe.target.isDarwin()) {
if (exe.rootModuleTarget().isDarwin()) {
// useful for package maintainers
exe.headerpad_max_install_names = true;
}
Expand Down Expand Up @@ -677,8 +689,8 @@ fn addCmakeCfgOptionsToExe(
// against system-provided LLVM, Clang, LLD.
const need_cpp_includes = true;
const static = cfg.llvm_linkage == .static;
const lib_suffix = if (static) exe.target.staticLibSuffix()[1..] else exe.target.dynamicLibSuffix()[1..];
switch (exe.target.getOsTag()) {
const lib_suffix = if (static) exe.rootModuleTarget().staticLibSuffix()[1..] else exe.rootModuleTarget().dynamicLibSuffix()[1..];
switch (exe.rootModuleTarget().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.
Expand All @@ -694,7 +706,7 @@ fn addCmakeCfgOptionsToExe(
exe.linkLibCpp();
},
.windows => {
if (exe.target.getAbi() != .msvc) exe.linkLibCpp();
if (exe.rootModuleTarget().abi != .msvc) exe.linkLibCpp();
},
.freebsd => {
if (static) {
Expand Down Expand Up @@ -756,12 +768,12 @@ fn addStaticLlvmOptionsToExe(exe: *std.Build.Step.Compile) !void {
exe.linkSystemLibrary("z");
exe.linkSystemLibrary("zstd");

if (exe.target.getOs().tag != .windows or exe.target.getAbi() != .msvc) {
if (exe.rootModuleTarget().os.tag != .windows or exe.rootModuleTarget().abi != .msvc) {
// This means we rely on clang-or-zig-built LLVM, Clang, LLD libraries.
exe.linkSystemLibrary("c++");
}

if (exe.target.getOs().tag == .windows) {
if (exe.rootModuleTarget().os.tag == .windows) {
exe.linkSystemLibrary("version");
exe.linkSystemLibrary("uuid");
exe.linkSystemLibrary("ole32");
Expand Down Expand Up @@ -810,7 +822,9 @@ fn addCMakeLibraryList(exe: *std.Build.Step.Compile, list: []const u8) void {
while (it.next()) |lib| {
if (mem.startsWith(u8, lib, "-l")) {
exe.linkSystemLibrary(lib["-l".len..]);
} else if (exe.target.isWindows() and mem.endsWith(u8, lib, ".lib") and !fs.path.isAbsolute(lib)) {
} else if (exe.rootModuleTarget().os.tag == .windows and
mem.endsWith(u8, lib, ".lib") and !fs.path.isAbsolute(lib))
{
exe.linkSystemLibrary(lib[0 .. lib.len - ".lib".len]);
} else {
exe.addObjectFile(.{ .cwd_relative = lib });
Expand Down
4 changes: 2 additions & 2 deletions deps/aro/build/GenerateDef.zig
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub const Options = struct {
pub const Kind = enum { dafsa, named };
};

pub fn create(owner: *std.Build, options: Options) std.Build.ModuleDependency {
pub fn create(owner: *std.Build, options: Options) std.Build.Module.Import {
const self = owner.allocator.create(GenerateDef) catch @panic("OOM");
const path = owner.pathJoin(&.{ options.src_prefix, options.name });

Expand All @@ -39,7 +39,7 @@ pub fn create(owner: *std.Build, options: Options) std.Build.ModuleDependency {
.generated_file = .{ .step = &self.step },
};
const module = self.step.owner.createModule(.{
.source_file = .{ .generated = &self.generated_file },
.root_source_file = .{ .generated = &self.generated_file },
});
return .{
.module = module,
Expand Down
7 changes: 6 additions & 1 deletion lib/build_runner.zig
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ pub fn main() !void {
return error.InvalidArgs;
};

const host = try std.zig.system.NativeTargetInfo.detect(.{});
const detected = try std.zig.system.NativeTargetInfo.detect(.{});
const host: std.Build.ResolvedTarget = .{
.query = .{},
.target = detected.target,
.dynamic_linker = detected.dynamic_linker,
};

const build_root_directory: std.Build.Cache.Directory = .{
.path = build_root,
Expand Down
Loading

0 comments on commit 142471f

Please sign in to comment.