Commit d703270545
Changed files (5)
lib/std/build/InstallDirStep.zig
@@ -6,10 +6,14 @@ const Step = build.Step;
const Builder = build.Builder;
const InstallDir = std.build.InstallDir;
const InstallDirStep = @This();
+const log = std.log;
step: Step,
builder: *Builder,
options: Options,
+/// This is used by the build system when a file being installed comes from one
+/// package but is being installed by another.
+override_source_builder: ?*Builder = null,
pub const base_id = .install_dir;
@@ -53,8 +57,14 @@ pub fn init(
fn make(step: *Step) !void {
const self = @fieldParentPtr(InstallDirStep, "step", step);
const dest_prefix = self.builder.getInstallPath(self.options.install_dir, self.options.install_subdir);
- const full_src_dir = self.builder.pathFromRoot(self.options.source_dir);
- var src_dir = try std.fs.cwd().openIterableDir(full_src_dir, .{});
+ const src_builder = self.override_source_builder orelse self.builder;
+ const full_src_dir = src_builder.pathFromRoot(self.options.source_dir);
+ var src_dir = std.fs.cwd().openIterableDir(full_src_dir, .{}) catch |err| {
+ log.err("InstallDirStep: unable to open source directory '{s}': {s}", .{
+ full_src_dir, @errorName(err),
+ });
+ return error.StepFailed;
+ };
defer src_dir.close();
var it = try src_dir.walk(self.builder.allocator);
next_entry: while (try it.next()) |entry| {
@@ -64,13 +74,8 @@ fn make(step: *Step) !void {
}
}
- const full_path = self.builder.pathJoin(&.{
- full_src_dir, entry.path,
- });
-
- const dest_path = self.builder.pathJoin(&.{
- dest_prefix, entry.path,
- });
+ const full_path = self.builder.pathJoin(&.{ full_src_dir, entry.path });
+ const dest_path = self.builder.pathJoin(&.{ dest_prefix, entry.path });
switch (entry.kind) {
.Directory => try fs.cwd().makePath(dest_path),
lib/std/build/InstallFileStep.zig
@@ -13,6 +13,9 @@ builder: *Builder,
source: FileSource,
dir: InstallDir,
dest_rel_path: []const u8,
+/// This is used by the build system when a file being installed comes from one
+/// package but is being installed by another.
+override_source_builder: ?*Builder = null,
pub fn init(
builder: *Builder,
@@ -32,7 +35,8 @@ pub fn init(
fn make(step: *Step) !void {
const self = @fieldParentPtr(InstallFileStep, "step", step);
+ const src_builder = self.override_source_builder orelse self.builder;
+ const full_src_path = self.source.getPath(src_builder);
const full_dest_path = self.builder.getInstallPath(self.dir, self.dest_rel_path);
- const full_src_path = self.source.getPath(self.builder);
try self.builder.updateFile(full_src_path, full_dest_path);
}
lib/std/build/LibExeObjStep.zig
@@ -501,6 +501,29 @@ pub fn installHeadersDirectoryOptions(
a.installed_headers.append(&install_dir.step) catch unreachable;
}
+pub fn installLibraryHeaders(a: *LibExeObjStep, l: *LibExeObjStep) void {
+ assert(l.kind == .lib);
+ const install_step = a.builder.getInstallStep();
+ // Copy each element from installed_headers, modifying the builder
+ // to be the new parent's builder.
+ for (l.installed_headers.items) |step| {
+ const step_copy = switch (step.id) {
+ inline .install_file, .install_dir => |id| blk: {
+ const T = id.Type();
+ const ptr = a.builder.allocator.create(T) catch unreachable;
+ ptr.* = step.cast(T).?.*;
+ ptr.override_source_builder = ptr.builder;
+ ptr.builder = a.builder;
+ break :blk &ptr.step;
+ },
+ else => unreachable,
+ };
+ a.installed_headers.append(step_copy) catch unreachable;
+ install_step.dependOn(step_copy);
+ }
+ a.installed_headers.appendSlice(l.installed_headers.items) catch unreachable;
+}
+
/// Creates a `RunStep` with an executable built with `addExecutable`.
/// Add command line arguments with `addArg`.
pub fn run(exe: *LibExeObjStep) *RunStep {
lib/std/build.zig
@@ -316,9 +316,20 @@ pub const Builder = struct {
// options to its dependencies. It is the programmatic way to give
// command line arguments to a build.zig script.
_ = args;
- // TODO create a hash based on the args and the package hash, use this
- // to compute the install prefix.
- const install_prefix = b.pathJoin(&.{ b.cache_root, "pkg" });
+ const Hasher = std.crypto.auth.siphash.SipHash128(1, 3);
+ // Random bytes to make unique. Refresh this with new random bytes when
+ // implementation is modified in a non-backwards-compatible way.
+ var hash = Hasher.init("ZaEsvQ5ClaA2IdH9");
+ hash.update(b.dep_prefix);
+ // TODO additionally update the hash with `args`.
+
+ var digest: [16]u8 = undefined;
+ hash.final(&digest);
+ var hash_basename: [digest.len * 2]u8 = undefined;
+ _ = std.fmt.bufPrint(&hash_basename, "{s}", .{std.fmt.fmtSliceHexLower(&digest)}) catch
+ unreachable;
+
+ const install_prefix = b.pathJoin(&.{ b.cache_root, "i", &hash_basename });
b.resolveInstallPrefix(install_prefix, .{});
}
@@ -1600,6 +1611,29 @@ pub const Step = struct {
install_raw,
options,
custom,
+
+ pub fn Type(comptime id: Id) type {
+ return switch (id) {
+ .top_level => Builder.TopLevelStep,
+ .lib_exe_obj => LibExeObjStep,
+ .install_artifact => InstallArtifactStep,
+ .install_file => InstallFileStep,
+ .install_dir => InstallDirStep,
+ .log => LogStep,
+ .remove_dir => RemoveDirStep,
+ .fmt => FmtStep,
+ .translate_c => TranslateCStep,
+ .write_file => WriteFileStep,
+ .run => RunStep,
+ .emulatable_run => EmulatableRunStep,
+ .check_file => CheckFileStep,
+ .check_object => CheckObjectStep,
+ .config_header => ConfigHeaderStep,
+ .install_raw => InstallRawStep,
+ .options => OptionsStep,
+ .custom => @compileError("no type available for custom step"),
+ };
+ }
};
pub fn init(id: Id, name: []const u8, allocator: Allocator, makeFn: MakeFn) Step {
lib/build_runner.zig
@@ -220,6 +220,11 @@ pub fn main() !void {
return usageAndErr(builder, true, stderr_stream);
},
error.UncleanExit => process.exit(1),
+ // This error is intended to indicate that the step has already
+ // logged an error message and so printing the error return trace
+ // here would be unwanted extra information, unless the user opts
+ // into it with a debug flag.
+ error.StepFailed => process.exit(1),
else => return err,
}
};