mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
Implement WriteFile.addCopyDirectory
This commit is contained in:
parent
2c7be4f8dd
commit
e16db29887
@ -493,7 +493,10 @@ fn addHeaderInstallationToIncludeTree(cs: *Compile, installation: HeaderInstalla
|
||||
_ = wf.addCopyFile(file.source, file.dest_rel_path);
|
||||
},
|
||||
.directory => |dir| {
|
||||
_ = dir; // TODO
|
||||
_ = wf.addCopyDirectory(dir.source, dir.dest_rel_path, .{
|
||||
.exclude_extensions = dir.options.exclude_extensions,
|
||||
.include_extensions = dir.options.include_extensions,
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -15,9 +15,11 @@ const ArrayList = std.ArrayList;
|
||||
const WriteFile = @This();
|
||||
|
||||
step: Step,
|
||||
/// The elements here are pointers because we need stable pointers for the
|
||||
/// GeneratedFile field.
|
||||
|
||||
// The elements here are pointers because we need stable pointers for the GeneratedFile field.
|
||||
files: std.ArrayListUnmanaged(*File),
|
||||
directories: std.ArrayListUnmanaged(*Directory),
|
||||
|
||||
output_source_files: std.ArrayListUnmanaged(OutputSourceFile),
|
||||
generated_directory: std.Build.GeneratedFile,
|
||||
|
||||
@ -33,6 +35,33 @@ pub const File = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub const Directory = struct {
|
||||
source: std.Build.LazyPath,
|
||||
sub_path: []const u8,
|
||||
options: Options,
|
||||
generated_dir: std.Build.GeneratedFile,
|
||||
|
||||
pub const Options = 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 = &.{".h"},
|
||||
|
||||
pub fn dupe(self: Options, b: *std.Build) Options {
|
||||
return .{
|
||||
.exclude_extensions = b.dupeStrings(self.exclude_extensions),
|
||||
.include_extensions = if (self.include_extensions) |incs| b.dupeStrings(incs) else null,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub fn getPath(self: *Directory) std.Build.LazyPath {
|
||||
return .{ .generated = &self.generated_dir };
|
||||
}
|
||||
};
|
||||
|
||||
pub const OutputSourceFile = struct {
|
||||
contents: Contents,
|
||||
sub_path: []const u8,
|
||||
@ -53,6 +82,7 @@ pub fn create(owner: *std.Build) *WriteFile {
|
||||
.makeFn = make,
|
||||
}),
|
||||
.files = .{},
|
||||
.directories = .{},
|
||||
.output_source_files = .{},
|
||||
.generated_directory = .{ .step = &wf.step },
|
||||
};
|
||||
@ -96,6 +126,28 @@ pub fn addCopyFile(wf: *WriteFile, source: std.Build.LazyPath, sub_path: []const
|
||||
return file.getPath();
|
||||
}
|
||||
|
||||
pub fn addCopyDirectory(
|
||||
wf: *WriteFile,
|
||||
source: std.Build.LazyPath,
|
||||
sub_path: []const u8,
|
||||
options: Directory.Options,
|
||||
) std.Build.LazyPath {
|
||||
const b = wf.step.owner;
|
||||
const gpa = b.allocator;
|
||||
const dir = gpa.create(Directory) catch @panic("OOM");
|
||||
dir.* = .{
|
||||
.source = source.dupe(b),
|
||||
.sub_path = b.dupePath(sub_path),
|
||||
.options = options.dupe(b),
|
||||
.generated_dir = .{ .step = &wf.step },
|
||||
};
|
||||
wf.directories.append(gpa, dir) catch @panic("OOM");
|
||||
|
||||
wf.maybeUpdateName();
|
||||
source.addStepDependencies(&wf.step);
|
||||
return dir.getPath();
|
||||
}
|
||||
|
||||
/// A path relative to the package root.
|
||||
/// Be careful with this because it updates source files. This should not be
|
||||
/// used as part of the normal build process, but as a utility occasionally
|
||||
@ -130,11 +182,16 @@ pub fn getDirectory(wf: *WriteFile) std.Build.LazyPath {
|
||||
}
|
||||
|
||||
fn maybeUpdateName(wf: *WriteFile) void {
|
||||
if (wf.files.items.len == 1) {
|
||||
if (wf.files.items.len == 1 and wf.directories.items.len == 0) {
|
||||
// First time adding a file; update name.
|
||||
if (std.mem.eql(u8, wf.step.name, "WriteFile")) {
|
||||
wf.step.name = wf.step.owner.fmt("WriteFile {s}", .{wf.files.items[0].sub_path});
|
||||
}
|
||||
} else if (wf.directories.items.len == 1 and wf.files.items.len == 0) {
|
||||
// First time adding a directory; update name.
|
||||
if (std.mem.eql(u8, wf.step.name, "WriteFile")) {
|
||||
wf.step.name = wf.step.owner.fmt("WriteFile {s}", .{wf.directories.items[0].sub_path});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,6 +266,12 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
|
||||
},
|
||||
}
|
||||
}
|
||||
for (wf.directories.items) |dir| {
|
||||
man.hash.addBytes(dir.source.getPath2(b, step));
|
||||
man.hash.addBytes(dir.sub_path);
|
||||
for (dir.options.exclude_extensions) |ext| man.hash.addBytes(ext);
|
||||
if (dir.options.include_extensions) |incs| for (incs) |inc| man.hash.addBytes(inc);
|
||||
}
|
||||
|
||||
if (try step.cacheHit(&man)) {
|
||||
const digest = man.final();
|
||||
@ -233,6 +296,8 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
|
||||
};
|
||||
defer cache_dir.close();
|
||||
|
||||
const cwd = fs.cwd();
|
||||
|
||||
for (wf.files.items) |file| {
|
||||
if (fs.path.dirname(file.sub_path)) |dirname| {
|
||||
cache_dir.makePath(dirname) catch |err| {
|
||||
@ -252,7 +317,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
|
||||
.copy => |file_source| {
|
||||
const source_path = file_source.getPath(b);
|
||||
const prev_status = fs.Dir.updateFile(
|
||||
fs.cwd(),
|
||||
cwd,
|
||||
source_path,
|
||||
cache_dir,
|
||||
file.sub_path,
|
||||
@ -279,6 +344,64 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
|
||||
cache_path, file.sub_path,
|
||||
});
|
||||
}
|
||||
for (wf.directories.items) |dir| {
|
||||
const full_src_dir_path = dir.source.getPath2(b, step);
|
||||
const dest_dirname = dir.sub_path;
|
||||
|
||||
if (dest_dirname.len != 0) {
|
||||
cache_dir.makePath(dest_dirname) catch |err| {
|
||||
return step.fail("unable to make path '{}{s}{c}{s}': {s}", .{
|
||||
b.cache_root, cache_path, fs.path.sep, dest_dirname, @errorName(err),
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
var src_dir = b.build_root.handle.openDir(full_src_dir_path, .{ .iterate = true }) catch |err| {
|
||||
return step.fail("unable to open source directory '{s}': {s}", .{
|
||||
full_src_dir_path, @errorName(err),
|
||||
});
|
||||
};
|
||||
defer src_dir.close();
|
||||
|
||||
var it = try src_dir.walk(b.allocator);
|
||||
next_entry: while (try it.next()) |entry| {
|
||||
for (dir.options.exclude_extensions) |ext| {
|
||||
if (std.mem.endsWith(u8, entry.path, ext)) continue :next_entry;
|
||||
}
|
||||
if (dir.options.include_extensions) |incs| {
|
||||
for (incs) |inc| {
|
||||
if (std.mem.endsWith(u8, entry.path, inc)) break;
|
||||
} else {
|
||||
continue :next_entry;
|
||||
}
|
||||
}
|
||||
const full_src_entry_path = b.pathJoin(&.{ full_src_dir_path, entry.path });
|
||||
const dest_path = b.pathJoin(&.{ dest_dirname, entry.path });
|
||||
switch (entry.kind) {
|
||||
.directory => try cache_dir.makePath(dest_path),
|
||||
.file => {
|
||||
const prev_status = fs.Dir.updateFile(
|
||||
cwd,
|
||||
full_src_entry_path,
|
||||
cache_dir,
|
||||
dest_path,
|
||||
.{},
|
||||
) catch |err| {
|
||||
return step.fail("unable to update file from '{s}' to '{}{s}{c}{s}': {s}", .{
|
||||
full_src_entry_path,
|
||||
b.cache_root,
|
||||
cache_path,
|
||||
fs.path.sep,
|
||||
dest_path,
|
||||
@errorName(err),
|
||||
});
|
||||
};
|
||||
_ = prev_status;
|
||||
},
|
||||
else => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try step.writeManifest(&man);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user