mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-05-08 17:40:59 -04:00
185 lines
6.4 KiB
Zig
185 lines
6.4 KiB
Zig
//! WriteFile is used to create a directory in an appropriate location inside
|
|
//! the local cache which has a set of files that have either been generated
|
|
//! during the build, or are copied from the source package.
|
|
const WriteFile = @This();
|
|
|
|
const std = @import("std");
|
|
const Step = std.Build.Step;
|
|
const Configuration = std.Build.Configuration;
|
|
|
|
step: Step,
|
|
embeds: std.ArrayList(Embed) = .empty,
|
|
copies: std.ArrayList(Copy) = .empty,
|
|
directories: std.ArrayList(Directory) = .empty,
|
|
generated_directory: Configuration.GeneratedFileIndex,
|
|
mode: Mode = .whole_cached,
|
|
|
|
pub const base_tag: Step.Tag = .write_file;
|
|
|
|
pub const Mode = union(enum) {
|
|
/// Default mode. Integrates with the cache system. The directory should be
|
|
/// read-only during the make phase. Any different inputs result in
|
|
/// different "o" subdirectory.
|
|
whole_cached,
|
|
/// In this mode, the directory will be placed inside "tmp" rather than
|
|
/// "o", and caching will be skipped. During the `make` phase, the step
|
|
/// will always do all the file system operations, and on successful build
|
|
/// completion, the dir will be deleted along with all other tmp
|
|
/// directories. The directory is therefore eligible to be used for
|
|
/// mutations by other steps.
|
|
tmp,
|
|
/// The operations will not be performed against a freshly created
|
|
/// directory, but instead act against a temporary directory.
|
|
mutate: std.Build.LazyPath,
|
|
};
|
|
|
|
pub const Embed = Configuration.Step.WriteFile.Embed;
|
|
|
|
pub const Copy = struct {
|
|
sub_path: Configuration.String,
|
|
src_file: std.Build.LazyPath,
|
|
};
|
|
|
|
pub const Directory = struct {
|
|
sub_path: Configuration.String,
|
|
src_path: std.Build.LazyPath,
|
|
exclude_extensions: Configuration.OptionalStringList,
|
|
include_extensions: Configuration.OptionalStringList,
|
|
};
|
|
|
|
pub fn create(owner: *std.Build) *WriteFile {
|
|
const graph = owner.graph;
|
|
const wf = graph.create(WriteFile);
|
|
wf.* = .{
|
|
.step = .init(.{
|
|
.tag = base_tag,
|
|
.name = "WriteFile",
|
|
.owner = owner,
|
|
}),
|
|
.generated_directory = graph.addGeneratedFile(&wf.step),
|
|
};
|
|
return wf;
|
|
}
|
|
|
|
/// Writes `contents` to a file at `sub_path` relative to the output
|
|
/// directory.
|
|
///
|
|
/// `sub_path` may be a basename, or it may include subdirectories, which are
|
|
/// created as needed.
|
|
pub fn add(wf: *WriteFile, sub_path: []const u8, contents: []const u8) std.Build.LazyPath {
|
|
const graph = wf.step.owner.graph;
|
|
const wc = &graph.wip_configuration;
|
|
const arena = graph.arena;
|
|
|
|
wf.embeds.append(arena, .{
|
|
.sub_path = wc.addString(sub_path) catch @panic("OOM"),
|
|
.contents = wc.addBytes(contents) catch @panic("OOM"),
|
|
}) catch @panic("OOM");
|
|
|
|
wf.maybeUpdateName();
|
|
|
|
return .{
|
|
.generated = .{
|
|
.index = wf.generated_directory,
|
|
.sub_path = graph.dupeString(sub_path),
|
|
},
|
|
};
|
|
}
|
|
|
|
/// Copies the provided file to `sub_path` relative to the output directory.
|
|
///
|
|
/// `sub_path` may be a basename, or it may include subdirectories, which are
|
|
/// created as needed.
|
|
pub fn addCopyFile(wf: *WriteFile, src_file: std.Build.LazyPath, sub_path: []const u8) std.Build.LazyPath {
|
|
const graph = wf.step.owner.graph;
|
|
const wc = &graph.wip_configuration;
|
|
const arena = graph.arena;
|
|
|
|
wf.copies.append(arena, .{
|
|
.sub_path = wc.addString(sub_path) catch @panic("OOM"),
|
|
.src_file = src_file.dupe(graph),
|
|
}) catch @panic("OOM");
|
|
|
|
wf.maybeUpdateName();
|
|
|
|
src_file.addStepDependencies(&wf.step);
|
|
|
|
return .{ .generated = .{
|
|
.index = wf.generated_directory,
|
|
.sub_path = graph.dupePath(sub_path),
|
|
} };
|
|
}
|
|
|
|
pub const CopyDirectoryOptions = struct {
|
|
/// File paths that end in any of these suffixes will be excluded from copying.
|
|
exclude_extensions: []const []const u8 = &.{},
|
|
/// Only file paths that end in any of these suffixes will be included in copying.
|
|
/// `null` means that all suffixes will be included.
|
|
/// `exclude_extensions` takes precedence over `include_extensions`.
|
|
include_extensions: ?[]const []const u8 = null,
|
|
};
|
|
|
|
/// Copy files matching the specified exclude/include patterns to the specified
|
|
/// subdirectory relative to this step's generated directory.
|
|
///
|
|
/// The returned value is a lazy path to the generated subdirectory.
|
|
pub fn addCopyDirectory(
|
|
wf: *WriteFile,
|
|
src_path: std.Build.LazyPath,
|
|
sub_path: []const u8,
|
|
options: CopyDirectoryOptions,
|
|
) std.Build.LazyPath {
|
|
const graph = wf.step.owner.graph;
|
|
const wc = &graph.wip_configuration;
|
|
const arena = graph.arena;
|
|
|
|
wf.directories.append(arena, .{
|
|
.sub_path = wc.addString(sub_path) catch @panic("OOM"),
|
|
.src_path = src_path.dupe(graph),
|
|
.exclude_extensions = if (options.exclude_extensions.len != 0)
|
|
.init(wc.addStringList(options.exclude_extensions) catch @panic("OOM"))
|
|
else
|
|
.none,
|
|
.include_extensions = if (options.include_extensions) |list|
|
|
.init(wc.addStringList(list) catch @panic("OOM"))
|
|
else
|
|
.none,
|
|
}) catch @panic("OOM");
|
|
|
|
wf.maybeUpdateName();
|
|
|
|
src_path.addStepDependencies(&wf.step);
|
|
|
|
return .{
|
|
.generated = .{
|
|
.index = wf.generated_directory,
|
|
.sub_path = graph.dupePath(sub_path),
|
|
},
|
|
};
|
|
}
|
|
|
|
/// Returns a `LazyPath` representing the base directory that contains all the
|
|
/// files from this `WriteFile`.
|
|
pub fn getDirectory(wf: *WriteFile) std.Build.LazyPath {
|
|
return .{ .generated = .{ .index = wf.generated_directory } };
|
|
}
|
|
|
|
fn maybeUpdateName(wf: *WriteFile) void {
|
|
const graph = wf.step.owner.graph;
|
|
const wc = &graph.wip_configuration;
|
|
const files_count = wf.embeds.items.len + wf.copies.items.len;
|
|
if (files_count == 1 and wf.directories.items.len == 0) {
|
|
// First time adding a file; update name.
|
|
const sub_path = if (wf.embeds.items.len == 1) wf.embeds.items[0].sub_path else wf.copies.items[0].sub_path;
|
|
if (std.mem.eql(u8, wf.step.name, "WriteFile")) {
|
|
wf.step.name = wf.step.owner.fmt("WriteFile {s}", .{wc.stringSlice(sub_path)});
|
|
}
|
|
} else if (wf.directories.items.len == 1 and files_count == 0) {
|
|
// First time adding a directory; update name.
|
|
const dir_name = wc.stringSlice(wf.directories.items[0].sub_path);
|
|
if (std.mem.eql(u8, wf.step.name, "WriteFile")) {
|
|
wf.step.name = wf.step.owner.fmt("WriteFile {s}", .{dir_name});
|
|
}
|
|
}
|
|
}
|