mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
A compilation build step for which the binary is not required could not be compiled previously. There were 2 issues that caused this: - The compiler communicated only the results of the emitted binary and did not properly communicate the result if the binary was not emitted. This is fixed by communicating the final hash of the artifact path (the hash of the corresponding /o/<hash> directory) and communicating this instead of the entire path. This changes the zig build --listen protocol to communicate hashes instead of paths, and emit_bin_path is accordingly renamed to emit_digest. - There was an error related to the default llvm object path when CacheUse.Whole was selected. I'm not really sure why this didn't manifest when the binary is also emitted. This was fixed by improving the path handling related to flush() and emitLlvmObject(). In general, this commit also improves some of the path handling throughout the compiler and standard library.
232 lines
9.3 KiB
Zig
232 lines
9.3 KiB
Zig
const std = @import("std");
|
|
const Step = std.Build.Step;
|
|
const InstallDir = std.Build.InstallDir;
|
|
const InstallArtifact = @This();
|
|
const fs = std.fs;
|
|
const LazyPath = std.Build.LazyPath;
|
|
|
|
step: Step,
|
|
|
|
dest_dir: ?InstallDir,
|
|
dest_sub_path: []const u8,
|
|
emitted_bin: ?LazyPath,
|
|
|
|
implib_dir: ?InstallDir,
|
|
emitted_implib: ?LazyPath,
|
|
|
|
pdb_dir: ?InstallDir,
|
|
emitted_pdb: ?LazyPath,
|
|
|
|
h_dir: ?InstallDir,
|
|
emitted_h: ?LazyPath,
|
|
|
|
dylib_symlinks: ?DylibSymlinkInfo,
|
|
|
|
artifact: *Step.Compile,
|
|
|
|
const DylibSymlinkInfo = struct {
|
|
major_only_filename: []const u8,
|
|
name_only_filename: []const u8,
|
|
};
|
|
|
|
pub const base_id: Step.Id = .install_artifact;
|
|
|
|
pub const Options = struct {
|
|
/// Which installation directory to put the main output file into.
|
|
dest_dir: Dir = .default,
|
|
pdb_dir: Dir = .default,
|
|
h_dir: Dir = .default,
|
|
implib_dir: Dir = .default,
|
|
|
|
/// Whether to install symlinks along with dynamic libraries.
|
|
dylib_symlinks: ?bool = null,
|
|
/// If non-null, adds additional path components relative to bin dir, and
|
|
/// overrides the basename of the Compile step for installation purposes.
|
|
dest_sub_path: ?[]const u8 = null,
|
|
|
|
pub const Dir = union(enum) {
|
|
disabled,
|
|
default,
|
|
override: InstallDir,
|
|
};
|
|
};
|
|
|
|
pub fn create(owner: *std.Build, artifact: *Step.Compile, options: Options) *InstallArtifact {
|
|
const install_artifact = owner.allocator.create(InstallArtifact) catch @panic("OOM");
|
|
const dest_dir: ?InstallDir = switch (options.dest_dir) {
|
|
.disabled => null,
|
|
.default => switch (artifact.kind) {
|
|
.obj => @panic("object files have no standard installation procedure"),
|
|
.exe, .@"test" => .bin,
|
|
.lib => if (artifact.isDll()) .bin else .lib,
|
|
},
|
|
.override => |o| o,
|
|
};
|
|
install_artifact.* = .{
|
|
.step = Step.init(.{
|
|
.id = base_id,
|
|
.name = owner.fmt("install {s}", .{artifact.name}),
|
|
.owner = owner,
|
|
.makeFn = make,
|
|
}),
|
|
.dest_dir = dest_dir,
|
|
.pdb_dir = switch (options.pdb_dir) {
|
|
.disabled => null,
|
|
.default => if (artifact.producesPdbFile()) dest_dir else null,
|
|
.override => |o| o,
|
|
},
|
|
.h_dir = switch (options.h_dir) {
|
|
.disabled => null,
|
|
.default => if (artifact.kind == .lib) .header else null,
|
|
.override => |o| o,
|
|
},
|
|
.implib_dir = switch (options.implib_dir) {
|
|
.disabled => null,
|
|
.default => if (artifact.producesImplib()) .lib else null,
|
|
.override => |o| o,
|
|
},
|
|
|
|
.dylib_symlinks = if (options.dylib_symlinks orelse (dest_dir != null and
|
|
artifact.isDynamicLibrary() and
|
|
artifact.version != null and
|
|
std.Build.wantSharedLibSymLinks(artifact.rootModuleTarget()))) .{
|
|
.major_only_filename = artifact.major_only_filename.?,
|
|
.name_only_filename = artifact.name_only_filename.?,
|
|
} else null,
|
|
|
|
.dest_sub_path = options.dest_sub_path orelse artifact.out_filename,
|
|
|
|
.emitted_bin = null,
|
|
.emitted_pdb = null,
|
|
.emitted_h = null,
|
|
.emitted_implib = null,
|
|
|
|
.artifact = artifact,
|
|
};
|
|
|
|
install_artifact.step.dependOn(&artifact.step);
|
|
|
|
if (install_artifact.dest_dir != null) install_artifact.emitted_bin = artifact.getEmittedBin();
|
|
if (install_artifact.pdb_dir != null) install_artifact.emitted_pdb = artifact.getEmittedPdb();
|
|
// https://github.com/ziglang/zig/issues/9698
|
|
//if (install_artifact.h_dir != null) install_artifact.emitted_h = artifact.getEmittedH();
|
|
if (install_artifact.implib_dir != null) install_artifact.emitted_implib = artifact.getEmittedImplib();
|
|
|
|
return install_artifact;
|
|
}
|
|
|
|
fn make(step: *Step, options: Step.MakeOptions) !void {
|
|
_ = options;
|
|
const install_artifact: *InstallArtifact = @fieldParentPtr("step", step);
|
|
const b = step.owner;
|
|
const cwd = fs.cwd();
|
|
|
|
var all_cached = true;
|
|
|
|
if (install_artifact.dest_dir) |dest_dir| {
|
|
const full_dest_path = b.getInstallPath(dest_dir, install_artifact.dest_sub_path);
|
|
const src_path = install_artifact.emitted_bin.?.getPath3(b, step);
|
|
const p = fs.Dir.updateFile(src_path.root_dir.handle, src_path.sub_path, cwd, full_dest_path, .{}) catch |err| {
|
|
return step.fail("unable to update file from '{s}' to '{s}': {s}", .{
|
|
src_path.sub_path, full_dest_path, @errorName(err),
|
|
});
|
|
};
|
|
all_cached = all_cached and p == .fresh;
|
|
|
|
if (install_artifact.dylib_symlinks) |dls| {
|
|
try Step.Compile.doAtomicSymLinks(step, full_dest_path, dls.major_only_filename, dls.name_only_filename);
|
|
}
|
|
|
|
install_artifact.artifact.installed_path = full_dest_path;
|
|
}
|
|
|
|
if (install_artifact.implib_dir) |implib_dir| {
|
|
const src_path = install_artifact.emitted_implib.?.getPath3(b, step);
|
|
const full_implib_path = b.getInstallPath(implib_dir, fs.path.basename(src_path.sub_path));
|
|
const p = fs.Dir.updateFile(src_path.root_dir.handle, src_path.sub_path, cwd, full_implib_path, .{}) catch |err| {
|
|
return step.fail("unable to update file from '{s}' to '{s}': {s}", .{
|
|
src_path.sub_path, full_implib_path, @errorName(err),
|
|
});
|
|
};
|
|
all_cached = all_cached and p == .fresh;
|
|
}
|
|
|
|
if (install_artifact.pdb_dir) |pdb_dir| {
|
|
const src_path = install_artifact.emitted_pdb.?.getPath3(b, step);
|
|
const full_pdb_path = b.getInstallPath(pdb_dir, fs.path.basename(src_path.sub_path));
|
|
const p = fs.Dir.updateFile(src_path.root_dir.handle, src_path.sub_path, cwd, full_pdb_path, .{}) catch |err| {
|
|
return step.fail("unable to update file from '{s}' to '{s}': {s}", .{
|
|
src_path.sub_path, full_pdb_path, @errorName(err),
|
|
});
|
|
};
|
|
all_cached = all_cached and p == .fresh;
|
|
}
|
|
|
|
if (install_artifact.h_dir) |h_dir| {
|
|
if (install_artifact.emitted_h) |emitted_h| {
|
|
const src_path = emitted_h.getPath3(b, step);
|
|
const full_h_path = b.getInstallPath(h_dir, fs.path.basename(src_path.sub_path));
|
|
const p = fs.Dir.updateFile(src_path.root_dir.handle, src_path.sub_path, cwd, full_h_path, .{}) catch |err| {
|
|
return step.fail("unable to update file from '{s}' to '{s}': {s}", .{
|
|
src_path.sub_path, full_h_path, @errorName(err),
|
|
});
|
|
};
|
|
all_cached = all_cached and p == .fresh;
|
|
}
|
|
|
|
for (install_artifact.artifact.installed_headers.items) |installation| switch (installation) {
|
|
.file => |file| {
|
|
const src_path = file.source.getPath3(b, step);
|
|
const full_h_path = b.getInstallPath(h_dir, file.dest_rel_path);
|
|
const p = fs.Dir.updateFile(src_path.root_dir.handle, src_path.sub_path, cwd, full_h_path, .{}) catch |err| {
|
|
return step.fail("unable to update file from '{s}' to '{s}': {s}", .{
|
|
src_path.sub_path, full_h_path, @errorName(err),
|
|
});
|
|
};
|
|
all_cached = all_cached and p == .fresh;
|
|
},
|
|
.directory => |dir| {
|
|
const src_dir_path = dir.source.getPath3(b, step);
|
|
const full_h_prefix = b.getInstallPath(h_dir, dir.dest_rel_path);
|
|
|
|
var src_dir = src_dir_path.root_dir.handle.openDir(src_dir_path.sub_path, .{ .iterate = true }) catch |err| {
|
|
return step.fail("unable to open source directory '{s}': {s}", .{
|
|
src_dir_path.sub_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 src_entry_path = src_dir_path.join(b.allocator, entry.path) catch @panic("OOM");
|
|
const full_dest_path = b.pathJoin(&.{ full_h_prefix, entry.path });
|
|
switch (entry.kind) {
|
|
.directory => try cwd.makePath(full_dest_path),
|
|
.file => {
|
|
const p = fs.Dir.updateFile(src_entry_path.root_dir.handle, src_entry_path.sub_path, cwd, full_dest_path, .{}) catch |err| {
|
|
return step.fail("unable to update file from '{s}' to '{s}': {s}", .{
|
|
src_entry_path.sub_path, full_dest_path, @errorName(err),
|
|
});
|
|
};
|
|
all_cached = all_cached and p == .fresh;
|
|
},
|
|
else => continue,
|
|
}
|
|
}
|
|
},
|
|
};
|
|
}
|
|
|
|
step.result_cached = all_cached;
|
|
}
|