mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-05-30 04:45:22 +03:00
configurer: get InstallDir and Options steps compiling
This commit is contained in:
@@ -26,7 +26,6 @@
|
||||
- but artifact install steps also add paths for dyn libs on windows
|
||||
* no more "artifact arg" to run step. if you want to run the post-install binary, get the lazy path
|
||||
from the install step.
|
||||
* -D options which are files need to be accounted for in the configure cache
|
||||
|
||||
|
||||
## Release Notes
|
||||
|
||||
@@ -208,7 +208,8 @@ pub fn build(b: *std.Build) !void {
|
||||
.single_threaded = single_threaded,
|
||||
});
|
||||
exe.pie = pie;
|
||||
exe.entitlements = entitlements;
|
||||
// https://codeberg.org/ziglang/zig/issues/32173
|
||||
exe.entitlements = if (entitlements) |p| .{ .cwd_relative = p } else null;
|
||||
exe.use_new_linker = b.option(bool, "new-linker", "Use the new linker");
|
||||
|
||||
const use_llvm = b.option(bool, "use-llvm", "Use the llvm backend");
|
||||
@@ -1498,11 +1499,13 @@ fn generateLangRef(b: *std.Build) std.Build.LazyPath {
|
||||
}),
|
||||
});
|
||||
|
||||
var dir = b.build_root.handle.openDir(io, "doc/langref", .{ .iterate = true }) catch |err| {
|
||||
std.debug.panic("unable to open '{f}doc/langref' directory: {s}", .{
|
||||
b.build_root, @errorName(err),
|
||||
});
|
||||
const langref_path: std.Build.Cache.Path = .{
|
||||
.root_dir = b.build_root,
|
||||
.sub_path = "doc/langref",
|
||||
};
|
||||
|
||||
var dir = langref_path.root_dir.handle.openDir(io, langref_path.sub_path, .{ .iterate = true }) catch |err|
|
||||
std.debug.panic("unable to open directory {f}: {t}", .{ langref_path, err });
|
||||
defer dir.close(io);
|
||||
|
||||
var wf = b.addWriteFiles();
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
const InstallDir = @This();
|
||||
|
||||
const std = @import("std");
|
||||
const Configuration = std.Build.Configuration;
|
||||
|
||||
const Step = @import("../Step.zig");
|
||||
const Maker = @import("../../Maker.zig");
|
||||
|
||||
pub fn make(
|
||||
install_dir: *InstallDir,
|
||||
step_index: Configuration.Step.Index,
|
||||
maker: *Maker,
|
||||
progress_node: std.Progress.Node,
|
||||
) !void {
|
||||
const graph = maker.graph;
|
||||
const arena = maker.graph.arena; // TODO don't leak into process arena
|
||||
const io = graph.io;
|
||||
const step = maker.stepByIndex(step_index);
|
||||
|
||||
step.clearWatchInputs();
|
||||
const dest_prefix = b.getInstallPath(install_dir.options.install_dir, install_dir.options.install_subdir);
|
||||
const src_dir_path = install_dir.options.source_dir.getPath3(b, step);
|
||||
const need_derived_inputs = try step.addDirectoryWatchInput(install_dir.options.source_dir);
|
||||
var src_dir = src_dir_path.root_dir.handle.openDir(io, src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| {
|
||||
return step.fail("unable to open source directory '{f}': {t}", .{ src_dir_path, err });
|
||||
};
|
||||
defer src_dir.close(io);
|
||||
var it = try src_dir.walk(arena);
|
||||
var all_cached = true;
|
||||
next_entry: while (try it.next(io)) |entry| {
|
||||
for (install_dir.options.exclude_extensions) |ext| {
|
||||
if (std.mem.endsWith(u8, entry.path, ext)) continue :next_entry;
|
||||
}
|
||||
if (install_dir.options.include_extensions) |incs| {
|
||||
for (incs) |inc| {
|
||||
if (std.mem.endsWith(u8, entry.path, inc)) break;
|
||||
} else {
|
||||
continue :next_entry;
|
||||
}
|
||||
}
|
||||
|
||||
const src_path = try install_dir.options.source_dir.join(arena, entry.path);
|
||||
const dest_path = b.pathJoin(&.{ dest_prefix, entry.path });
|
||||
switch (entry.kind) {
|
||||
.directory => {
|
||||
if (need_derived_inputs) _ = try step.addDirectoryWatchInput(src_path);
|
||||
const p = try step.installDir(dest_path);
|
||||
all_cached = all_cached and p == .existed;
|
||||
},
|
||||
.file => {
|
||||
for (install_dir.options.blank_extensions) |ext| {
|
||||
if (std.mem.endsWith(u8, entry.path, ext)) {
|
||||
try b.truncateFile(dest_path);
|
||||
continue :next_entry;
|
||||
}
|
||||
}
|
||||
|
||||
const p = try step.installFile(src_path, dest_path);
|
||||
all_cached = all_cached and p == .fresh;
|
||||
},
|
||||
else => continue,
|
||||
}
|
||||
}
|
||||
|
||||
step.result_cached = all_cached;
|
||||
}
|
||||
@@ -19,6 +19,7 @@ pub fn make(
|
||||
const conf = &maker.scanned_config.configuration;
|
||||
const conf_step = step_index.ptr(conf);
|
||||
const conf_if = conf_step.extended.get(conf.extra).install_file;
|
||||
|
||||
try step.singleUnchangingWatchInput(maker, arena, conf_if.source.get(conf));
|
||||
const p = try maker.installLazyPathSub(arena, conf_if.source, conf_if.dest_dir, conf_if.dest_sub_path.slice(conf), step_index);
|
||||
step.result_cached = p == .fresh;
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
const Options = @This();
|
||||
|
||||
const std = @import("std");
|
||||
const Configuration = std.Build.Configuration;
|
||||
|
||||
const Step = @import("../Step.zig");
|
||||
const Maker = @import("../../Maker.zig");
|
||||
|
||||
|
||||
fn make(
|
||||
options: *Options,
|
||||
step_index: Configuration.Step.Index,
|
||||
maker: *Maker,
|
||||
progress_node: std.Progress.Node,
|
||||
) !void {
|
||||
// This step completes so quickly that no progress reporting is necessary.
|
||||
_ = progress_node;
|
||||
|
||||
const graph = maker.graph;
|
||||
const step = maker.stepByIndex(step_index);
|
||||
const io = graph.io;
|
||||
const cache_root = graph.local_cache_root;
|
||||
|
||||
for (options.args.items) |arg| {
|
||||
options.addOption(
|
||||
[]const u8,
|
||||
arg.name,
|
||||
arg.path.getPath2(b, step),
|
||||
);
|
||||
}
|
||||
if (!step.inputs.populated()) for (options.args.items) |arg| {
|
||||
try step.addWatchInput(arg.path);
|
||||
};
|
||||
|
||||
const basename = "options.zig";
|
||||
|
||||
// Hash contents to file name.
|
||||
var hash = graph.cache.hash;
|
||||
// Random bytes to make unique. Refresh this with new random bytes when
|
||||
// implementation is modified in a non-backwards-compatible way.
|
||||
hash.add(@as(u32, 0xad95e922));
|
||||
hash.addBytes(options.contents.items);
|
||||
const sub_path = "c" ++ fs.path.sep_str ++ hash.final() ++ fs.path.sep_str ++ basename;
|
||||
|
||||
options.generated_file.path = try cache_root.join(arena, &.{sub_path});
|
||||
|
||||
// Optimize for the hot path. Stat the file, and if it already exists,
|
||||
// cache hit.
|
||||
if (cache_root.handle.access(io, sub_path, .{})) |_| {
|
||||
// This is the hot path, success.
|
||||
step.result_cached = true;
|
||||
return;
|
||||
} else |outer_err| switch (outer_err) {
|
||||
error.FileNotFound => {
|
||||
var atomic_file = cache_root.handle.createFileAtomic(io, sub_path, .{
|
||||
.replace = false,
|
||||
.make_path = true,
|
||||
}) catch |err| return step.fail("failed to create temporary path for '{f}{s}': {t}", .{
|
||||
cache_root, sub_path, err,
|
||||
});
|
||||
defer atomic_file.deinit(io);
|
||||
|
||||
atomic_file.file.writeStreamingAll(io, options.contents.items) catch |err| {
|
||||
return step.fail("failed to write options to temporary path for '{f}{s}': {t}", .{
|
||||
cache_root, sub_path, err,
|
||||
});
|
||||
};
|
||||
|
||||
atomic_file.link(io) catch |err| switch (err) {
|
||||
error.PathAlreadyExists => {
|
||||
step.result_cached = true;
|
||||
return;
|
||||
},
|
||||
else => return step.fail("failed to link temporary file into '{f}{s}': {t}", .{
|
||||
cache_root, sub_path, err,
|
||||
}),
|
||||
};
|
||||
},
|
||||
else => |e| return step.fail("unable to access options file '{f}{s}': {t}", .{
|
||||
cache_root, sub_path, e,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
+7
-7
@@ -99,19 +99,19 @@ pub const Graph = struct {
|
||||
return @enumFromInt(graph.generated_files.items.len - 1);
|
||||
}
|
||||
|
||||
pub fn dupeString(graph: *Graph, bytes: []const u8) []const u8 {
|
||||
pub fn dupeString(graph: *const Graph, bytes: []const u8) []const u8 {
|
||||
return graph.arena.dupe(u8, bytes) catch @panic("OOM");
|
||||
}
|
||||
|
||||
pub fn dupePath(graph: *Graph, bytes: []const u8) []const u8 {
|
||||
pub fn dupePath(graph: *const Graph, bytes: []const u8) []const u8 {
|
||||
const arena = graph.arena;
|
||||
if (builtin.os.tag != .windows) return graph.arena.dupe(u8, bytes) catch @panic("OOM");
|
||||
if (builtin.os.tag != .windows) return arena.dupe(u8, bytes) catch @panic("OOM");
|
||||
const the_copy = arena.dupe(u8, bytes) catch @panic("OOM");
|
||||
mem.replaceScalar(u8, the_copy, '/', '\\');
|
||||
return the_copy;
|
||||
}
|
||||
|
||||
pub fn dupeStrings(graph: *Graph, strings: []const []const u8) []const []const u8 {
|
||||
pub fn dupeStrings(graph: *const Graph, strings: []const []const u8) []const []const u8 {
|
||||
const arena = graph.arena;
|
||||
const array = arena.alloc([]const u8, strings.len) catch @panic("OOM");
|
||||
for (array, strings) |*dest, source| dest.* = dupeString(graph, source);
|
||||
@@ -2186,7 +2186,7 @@ pub const LazyPath = union(enum) {
|
||||
///
|
||||
/// The `b` parameter is only used for its allocator. All *Build instances
|
||||
/// share the same allocator.
|
||||
pub fn dupe(lazy_path: LazyPath, graph: *Graph) LazyPath {
|
||||
pub fn dupe(lazy_path: LazyPath, graph: *const Graph) LazyPath {
|
||||
return switch (lazy_path) {
|
||||
.src_path => |sp| .{ .src_path = .{ .owner = sp.owner, .sub_path = sp.owner.dupePath(sp.sub_path) } },
|
||||
.cwd_relative => |p| .{ .cwd_relative = graph.dupePath(p) },
|
||||
@@ -2245,9 +2245,9 @@ pub const InstallDir = union(enum) {
|
||||
custom: []const u8,
|
||||
|
||||
/// Duplicates the install directory including the path if set to custom.
|
||||
pub fn dupe(dir: InstallDir, builder: *Build) InstallDir {
|
||||
pub fn dupe(dir: InstallDir, graph: *const Graph) InstallDir {
|
||||
if (dir == .custom) {
|
||||
return .{ .custom = builder.dupe(dir.custom) };
|
||||
return .{ .custom = graph.dupeString(dir.custom) };
|
||||
} else {
|
||||
return dir;
|
||||
}
|
||||
|
||||
@@ -1039,10 +1039,20 @@ pub const Step = extern struct {
|
||||
|
||||
pub const InstallDir = struct {
|
||||
flags: @This().Flags,
|
||||
source_dir: LazyPath.Index,
|
||||
dest_dir: InstallDestDir,
|
||||
dest_sub_path: Storage.FlagOptional(.flags, .dest_sub_path, String),
|
||||
exclude_extensions: Storage.FlagLengthPrefixedList(.flags, .exclude_extensions, String),
|
||||
include_extensions: Storage.FlagLengthPrefixedList(.flags, .include_extensions, String),
|
||||
blank_extensions: Storage.FlagLengthPrefixedList(.flags, .blank_extensions, String),
|
||||
|
||||
pub const Flags = packed struct(u32) {
|
||||
tag: Tag = .install_dir,
|
||||
_: u27 = 0,
|
||||
dest_sub_path: bool,
|
||||
exclude_extensions: bool,
|
||||
include_extensions: bool,
|
||||
blank_extensions: bool,
|
||||
_: u23 = 0,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1069,10 +1079,19 @@ pub const Step = extern struct {
|
||||
|
||||
pub const Options = struct {
|
||||
flags: @This().Flags,
|
||||
generated_file: GeneratedFileIndex,
|
||||
contents: Bytes,
|
||||
args: Storage.FlagLengthPrefixedList(.flags, .args, Arg),
|
||||
|
||||
pub const Arg = extern struct {
|
||||
name: String,
|
||||
path: LazyPath.Index,
|
||||
};
|
||||
|
||||
pub const Flags = packed struct(u32) {
|
||||
tag: Tag = .options,
|
||||
_: u27 = 0,
|
||||
args: bool,
|
||||
_: u26 = 0,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
const InstallDir = @This();
|
||||
|
||||
const std = @import("std");
|
||||
const mem = std.mem;
|
||||
const fs = std.fs;
|
||||
const Step = std.Build.Step;
|
||||
const LazyPath = std.Build.LazyPath;
|
||||
const InstallDir = @This();
|
||||
|
||||
step: Step,
|
||||
options: Options,
|
||||
@@ -28,83 +29,29 @@ pub const Options = struct {
|
||||
/// `@import("test.zig")` would be a compile error.
|
||||
blank_extensions: []const []const u8 = &.{},
|
||||
|
||||
fn dupe(opts: Options, b: *std.Build) Options {
|
||||
fn dupe(opts: Options, graph: *const std.Build.Graph) Options {
|
||||
return .{
|
||||
.source_dir = opts.source_dir.dupe(b),
|
||||
.install_dir = opts.install_dir.dupe(b),
|
||||
.install_subdir = b.dupe(opts.install_subdir),
|
||||
.exclude_extensions = b.dupeStrings(opts.exclude_extensions),
|
||||
.include_extensions = if (opts.include_extensions) |incs| b.dupeStrings(incs) else null,
|
||||
.blank_extensions = b.dupeStrings(opts.blank_extensions),
|
||||
.source_dir = opts.source_dir.dupe(graph),
|
||||
.install_dir = opts.install_dir.dupe(graph),
|
||||
.install_subdir = graph.dupeString(opts.install_subdir),
|
||||
.exclude_extensions = graph.dupeStrings(opts.exclude_extensions),
|
||||
.include_extensions = if (opts.include_extensions) |incs| graph.dupeStrings(incs) else null,
|
||||
.blank_extensions = graph.dupeStrings(opts.blank_extensions),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn create(owner: *std.Build, options: Options) *InstallDir {
|
||||
const install_dir = owner.allocator.create(InstallDir) catch @panic("OOM");
|
||||
const graph = owner.graph;
|
||||
install_dir.* = .{
|
||||
.step = Step.init(.{
|
||||
.tag = base_tag,
|
||||
.name = owner.fmt("install {s}/", .{options.source_dir.getDisplayName()}),
|
||||
.owner = owner,
|
||||
.makeFn = make,
|
||||
}),
|
||||
.options = options.dupe(owner),
|
||||
.options = options.dupe(graph),
|
||||
};
|
||||
options.source_dir.addStepDependencies(&install_dir.step);
|
||||
return install_dir;
|
||||
}
|
||||
|
||||
fn make(step: *Step, options: Step.MakeOptions) !void {
|
||||
_ = options;
|
||||
const b = step.owner;
|
||||
const io = b.graph.io;
|
||||
const install_dir: *InstallDir = @fieldParentPtr("step", step);
|
||||
step.clearWatchInputs();
|
||||
const arena = b.allocator;
|
||||
const dest_prefix = b.getInstallPath(install_dir.options.install_dir, install_dir.options.install_subdir);
|
||||
const src_dir_path = install_dir.options.source_dir.getPath3(b, step);
|
||||
const need_derived_inputs = try step.addDirectoryWatchInput(install_dir.options.source_dir);
|
||||
var src_dir = src_dir_path.root_dir.handle.openDir(io, src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| {
|
||||
return step.fail("unable to open source directory '{f}': {t}", .{ src_dir_path, err });
|
||||
};
|
||||
defer src_dir.close(io);
|
||||
var it = try src_dir.walk(arena);
|
||||
var all_cached = true;
|
||||
next_entry: while (try it.next(io)) |entry| {
|
||||
for (install_dir.options.exclude_extensions) |ext| {
|
||||
if (mem.endsWith(u8, entry.path, ext)) continue :next_entry;
|
||||
}
|
||||
if (install_dir.options.include_extensions) |incs| {
|
||||
for (incs) |inc| {
|
||||
if (mem.endsWith(u8, entry.path, inc)) break;
|
||||
} else {
|
||||
continue :next_entry;
|
||||
}
|
||||
}
|
||||
|
||||
const src_path = try install_dir.options.source_dir.join(b.allocator, entry.path);
|
||||
const dest_path = b.pathJoin(&.{ dest_prefix, entry.path });
|
||||
switch (entry.kind) {
|
||||
.directory => {
|
||||
if (need_derived_inputs) _ = try step.addDirectoryWatchInput(src_path);
|
||||
const p = try step.installDir(dest_path);
|
||||
all_cached = all_cached and p == .existed;
|
||||
},
|
||||
.file => {
|
||||
for (install_dir.options.blank_extensions) |ext| {
|
||||
if (mem.endsWith(u8, entry.path, ext)) {
|
||||
try b.truncateFile(dest_path);
|
||||
continue :next_entry;
|
||||
}
|
||||
}
|
||||
|
||||
const p = try step.installFile(src_path, dest_path);
|
||||
all_cached = all_cached and p == .fresh;
|
||||
},
|
||||
else => continue,
|
||||
}
|
||||
}
|
||||
|
||||
step.result_cached = all_cached;
|
||||
}
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
const InstallFile = @This();
|
||||
|
||||
const std = @import("std");
|
||||
const Step = std.Build.Step;
|
||||
const LazyPath = std.Build.LazyPath;
|
||||
const InstallDir = std.Build.InstallDir;
|
||||
const InstallFile = @This();
|
||||
const assert = std.debug.assert;
|
||||
|
||||
pub const base_tag: Step.Tag = .install_file;
|
||||
|
||||
step: Step,
|
||||
source: LazyPath,
|
||||
dir: InstallDir,
|
||||
dest_rel_path: []const u8,
|
||||
|
||||
pub const base_tag: Step.Tag = .install_file;
|
||||
|
||||
pub fn create(
|
||||
owner: *std.Build,
|
||||
source: LazyPath,
|
||||
@@ -19,16 +20,18 @@ pub fn create(
|
||||
dest_rel_path: []const u8,
|
||||
) *InstallFile {
|
||||
assert(dest_rel_path.len != 0);
|
||||
const install_file = owner.allocator.create(InstallFile) catch @panic("OOM");
|
||||
const graph = owner.graph;
|
||||
const arena = graph.arena;
|
||||
const install_file = arena.create(InstallFile) catch @panic("OOM");
|
||||
install_file.* = .{
|
||||
.step = Step.init(.{
|
||||
.tag = base_tag,
|
||||
.name = owner.fmt("install {s} to {s}", .{ source.getDisplayName(), dest_rel_path }),
|
||||
.owner = owner,
|
||||
}),
|
||||
.source = source.dupe(owner),
|
||||
.dir = dir.dupe(owner),
|
||||
.dest_rel_path = owner.dupePath(dest_rel_path),
|
||||
.source = source.dupe(graph),
|
||||
.dir = dir.dupe(graph),
|
||||
.dest_rel_path = graph.dupePath(dest_rel_path),
|
||||
};
|
||||
source.addStepDependencies(&install_file.step);
|
||||
return install_file;
|
||||
|
||||
@@ -9,15 +9,19 @@ const Step = std.Build.Step;
|
||||
const LazyPath = std.Build.LazyPath;
|
||||
const Configuration = std.Build.Configuration;
|
||||
|
||||
pub const base_tag: Step.Tag = .options;
|
||||
|
||||
step: Step,
|
||||
generated_file: Configuration.GeneratedFileIndex,
|
||||
|
||||
contents: std.ArrayList(u8),
|
||||
args: std.ArrayList(Arg),
|
||||
encountered_types: std.StringHashMapUnmanaged(void),
|
||||
|
||||
pub const base_tag: Step.Tag = .options;
|
||||
|
||||
pub const Arg = struct {
|
||||
name: []const u8,
|
||||
path: LazyPath,
|
||||
};
|
||||
|
||||
pub fn create(owner: *std.Build) *Options {
|
||||
const graph = owner.graph;
|
||||
const arena = graph.arena;
|
||||
@@ -28,7 +32,6 @@ pub fn create(owner: *std.Build) *Options {
|
||||
.tag = base_tag,
|
||||
.name = "options",
|
||||
.owner = owner,
|
||||
.makeFn = make,
|
||||
}),
|
||||
.generated_file = graph.addGeneratedFile(&options.step),
|
||||
.contents = .empty,
|
||||
@@ -439,240 +442,3 @@ pub fn createModule(options: *Options) *std.Build.Module {
|
||||
pub fn getOutput(options: *Options) LazyPath {
|
||||
return .{ .generated = .{ .index = options.generated_file } };
|
||||
}
|
||||
|
||||
fn make(step: *Step, make_options: Step.MakeOptions) !void {
|
||||
// This step completes so quickly that no progress reporting is necessary.
|
||||
_ = make_options;
|
||||
|
||||
const b = step.owner;
|
||||
const io = b.graph.io;
|
||||
const options: *Options = @fieldParentPtr("step", step);
|
||||
|
||||
for (options.args.items) |item| {
|
||||
options.addOption(
|
||||
[]const u8,
|
||||
item.name,
|
||||
item.path.getPath2(b, step),
|
||||
);
|
||||
}
|
||||
if (!step.inputs.populated()) for (options.args.items) |item| {
|
||||
try step.addWatchInput(item.path);
|
||||
};
|
||||
|
||||
const basename = "options.zig";
|
||||
|
||||
// Hash contents to file name.
|
||||
var hash = b.graph.cache.hash;
|
||||
// Random bytes to make unique. Refresh this with new random bytes when
|
||||
// implementation is modified in a non-backwards-compatible way.
|
||||
hash.add(@as(u32, 0xad95e922));
|
||||
hash.addBytes(options.contents.items);
|
||||
const sub_path = "c" ++ fs.path.sep_str ++ hash.final() ++ fs.path.sep_str ++ basename;
|
||||
|
||||
options.generated_file.path = try b.cache_root.join(b.allocator, &.{sub_path});
|
||||
|
||||
// Optimize for the hot path. Stat the file, and if it already exists,
|
||||
// cache hit.
|
||||
if (b.cache_root.handle.access(io, sub_path, .{})) |_| {
|
||||
// This is the hot path, success.
|
||||
step.result_cached = true;
|
||||
return;
|
||||
} else |outer_err| switch (outer_err) {
|
||||
error.FileNotFound => {
|
||||
var atomic_file = b.cache_root.handle.createFileAtomic(io, sub_path, .{
|
||||
.replace = false,
|
||||
.make_path = true,
|
||||
}) catch |err| return step.fail("failed to create temporary path for '{f}{s}': {t}", .{
|
||||
b.cache_root, sub_path, err,
|
||||
});
|
||||
defer atomic_file.deinit(io);
|
||||
|
||||
atomic_file.file.writeStreamingAll(io, options.contents.items) catch |err| {
|
||||
return step.fail("failed to write options to temporary path for '{f}{s}': {t}", .{
|
||||
b.cache_root, sub_path, err,
|
||||
});
|
||||
};
|
||||
|
||||
atomic_file.link(io) catch |err| switch (err) {
|
||||
error.PathAlreadyExists => {
|
||||
step.result_cached = true;
|
||||
return;
|
||||
},
|
||||
else => return step.fail("failed to link temporary file into '{f}{s}': {t}", .{
|
||||
b.cache_root, sub_path, err,
|
||||
}),
|
||||
};
|
||||
},
|
||||
else => |e| return step.fail("unable to access options file '{f}{s}': {t}", .{
|
||||
b.cache_root, sub_path, e,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
const Arg = struct {
|
||||
name: []const u8,
|
||||
path: LazyPath,
|
||||
};
|
||||
|
||||
test Options {
|
||||
if (builtin.os.tag == .wasi) return error.SkipZigTest;
|
||||
|
||||
const io = std.testing.io;
|
||||
|
||||
var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
|
||||
defer arena.deinit();
|
||||
|
||||
const cwd = try std.process.currentPathAlloc(io, std.testing.allocator);
|
||||
defer std.testing.allocator.free(cwd);
|
||||
|
||||
var graph: std.Build.Graph = .{
|
||||
.io = io,
|
||||
.arena = arena.allocator(),
|
||||
.cache = .{
|
||||
.io = io,
|
||||
.gpa = arena.allocator(),
|
||||
.manifest_dir = Io.Dir.cwd(),
|
||||
.cwd = cwd,
|
||||
},
|
||||
.zig_exe = "test",
|
||||
.environ_map = std.process.Environ.Map.init(arena.allocator()),
|
||||
.global_cache_root = .{ .path = "test", .handle = Io.Dir.cwd() },
|
||||
.host = .{
|
||||
.query = .{},
|
||||
.result = try std.zig.system.resolveTargetQuery(io, .{}),
|
||||
},
|
||||
.zig_lib_directory = std.Build.Cache.Directory.cwd(),
|
||||
.time_report = false,
|
||||
};
|
||||
|
||||
var builder = try std.Build.create(
|
||||
&graph,
|
||||
.{ .path = "test", .handle = Io.Dir.cwd() },
|
||||
.{ .path = "test", .handle = Io.Dir.cwd() },
|
||||
&.{},
|
||||
);
|
||||
|
||||
const options = builder.addOptions();
|
||||
|
||||
const KeywordEnum = enum {
|
||||
@"0.8.1",
|
||||
};
|
||||
|
||||
const NormalEnum = enum {
|
||||
foo,
|
||||
bar,
|
||||
};
|
||||
|
||||
const nested_array = [2][2]u16{
|
||||
[2]u16{ 300, 200 },
|
||||
[2]u16{ 300, 200 },
|
||||
};
|
||||
const nested_slice: []const []const u16 = &[_][]const u16{ &nested_array[0], &nested_array[1] };
|
||||
|
||||
const NormalStruct = struct {
|
||||
hello: ?[]const u8,
|
||||
world: bool = true,
|
||||
};
|
||||
|
||||
const NestedStruct = struct {
|
||||
normal_struct: NormalStruct,
|
||||
normal_enum: NormalEnum = .foo,
|
||||
};
|
||||
|
||||
options.addOption(usize, "option1", 1);
|
||||
options.addOption(?usize, "option2", null);
|
||||
options.addOption(?usize, "option3", 3);
|
||||
options.addOption(comptime_int, "option4", 4);
|
||||
options.addOption(comptime_float, "option5", 5.01);
|
||||
options.addOption([]const u8, "string", "zigisthebest");
|
||||
options.addOption(?[]const u8, "optional_string", null);
|
||||
options.addOption([2][2]u16, "nested_array", nested_array);
|
||||
options.addOption([]const []const u16, "nested_slice", nested_slice);
|
||||
options.addOption(KeywordEnum, "keyword_enum", .@"0.8.1");
|
||||
options.addOption(std.SemanticVersion, "semantic_version", try std.SemanticVersion.parse("0.1.2-foo+bar"));
|
||||
options.addOption(NormalEnum, "normal1_enum", NormalEnum.foo);
|
||||
options.addOption(NormalEnum, "normal2_enum", NormalEnum.bar);
|
||||
options.addOption(NormalStruct, "normal1_struct", NormalStruct{
|
||||
.hello = "foo",
|
||||
});
|
||||
options.addOption(NormalStruct, "normal2_struct", NormalStruct{
|
||||
.hello = null,
|
||||
.world = false,
|
||||
});
|
||||
options.addOption(NestedStruct, "nested_struct", NestedStruct{
|
||||
.normal_struct = .{ .hello = "bar" },
|
||||
});
|
||||
|
||||
try std.testing.expectEqualStrings(
|
||||
\\pub const option1: usize = 1;
|
||||
\\pub const option2: ?usize = null;
|
||||
\\pub const option3: ?usize = 3;
|
||||
\\pub const option4: comptime_int = 4;
|
||||
\\pub const option5: comptime_float = 5.01;
|
||||
\\pub const string: []const u8 = "zigisthebest";
|
||||
\\pub const optional_string: ?[]const u8 = null;
|
||||
\\pub const nested_array: [2][2]u16 = [2][2]u16 {
|
||||
\\ [2]u16 {
|
||||
\\ 300,
|
||||
\\ 200,
|
||||
\\ },
|
||||
\\ [2]u16 {
|
||||
\\ 300,
|
||||
\\ 200,
|
||||
\\ },
|
||||
\\};
|
||||
\\pub const nested_slice: []const []const u16 = &[_][]const u16 {
|
||||
\\ &[_]u16 {
|
||||
\\ 300,
|
||||
\\ 200,
|
||||
\\ },
|
||||
\\ &[_]u16 {
|
||||
\\ 300,
|
||||
\\ 200,
|
||||
\\ },
|
||||
\\};
|
||||
\\pub const @"Build.Step.Options.decltest.Options.KeywordEnum" = enum (u0) {
|
||||
\\ @"0.8.1" = 0,
|
||||
\\};
|
||||
\\pub const keyword_enum: @"Build.Step.Options.decltest.Options.KeywordEnum" = .@"0.8.1";
|
||||
\\pub const semantic_version: @import("std").SemanticVersion = .{
|
||||
\\ .major = 0,
|
||||
\\ .minor = 1,
|
||||
\\ .patch = 2,
|
||||
\\ .pre = "foo",
|
||||
\\ .build = "bar",
|
||||
\\};
|
||||
\\pub const @"Build.Step.Options.decltest.Options.NormalEnum" = enum (u1) {
|
||||
\\ foo = 0,
|
||||
\\ bar = 1,
|
||||
\\};
|
||||
\\pub const normal1_enum: @"Build.Step.Options.decltest.Options.NormalEnum" = .foo;
|
||||
\\pub const normal2_enum: @"Build.Step.Options.decltest.Options.NormalEnum" = .bar;
|
||||
\\pub const @"Build.Step.Options.decltest.Options.NormalStruct" = struct {
|
||||
\\ hello: ?[]const u8,
|
||||
\\ world: bool = true,
|
||||
\\};
|
||||
\\pub const normal1_struct: @"Build.Step.Options.decltest.Options.NormalStruct" = .{
|
||||
\\ .hello = "foo",
|
||||
\\ .world = true,
|
||||
\\};
|
||||
\\pub const normal2_struct: @"Build.Step.Options.decltest.Options.NormalStruct" = .{
|
||||
\\ .hello = null,
|
||||
\\ .world = false,
|
||||
\\};
|
||||
\\pub const @"Build.Step.Options.decltest.Options.NestedStruct" = struct {
|
||||
\\ normal_struct: @"Build.Step.Options.decltest.Options.NormalStruct",
|
||||
\\ normal_enum: @"Build.Step.Options.decltest.Options.NormalEnum" = .foo,
|
||||
\\};
|
||||
\\pub const nested_struct: @"Build.Step.Options.decltest.Options.NestedStruct" = .{
|
||||
\\ .normal_struct = .{
|
||||
\\ .hello = "bar",
|
||||
\\ .world = true,
|
||||
\\ },
|
||||
\\ .normal_enum = .foo,
|
||||
\\};
|
||||
\\
|
||||
, options.contents.items);
|
||||
|
||||
_ = try std.zig.Ast.parse(arena.allocator(), try options.contents.toOwnedSliceSentinel(arena.allocator(), 0), .zig);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user