mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
Merge pull request #21115 from Snektron/build-system-asm
compilation and build system fixes
This commit is contained in:
commit
dffc8c44f9
@ -201,9 +201,10 @@ fn cmdObjCopy(
|
||||
if (seen_update) fatal("zig objcopy only supports 1 update for now", .{});
|
||||
seen_update = true;
|
||||
|
||||
try server.serveEmitBinPath(output, .{
|
||||
.flags = .{ .cache_hit = false },
|
||||
});
|
||||
// The build system already knows what the output is at this point, we
|
||||
// only need to communicate that the process has finished.
|
||||
// Use the empty error bundle to indicate that the update is done.
|
||||
try server.serveErrorBundle(std.zig.ErrorBundle.empty);
|
||||
},
|
||||
else => fatal("unsupported message: {s}", .{@tagName(hdr.tag)}),
|
||||
}
|
||||
|
||||
@ -2373,7 +2373,7 @@ pub const LazyPath = union(enum) {
|
||||
// basis for not traversing up too many directories.
|
||||
|
||||
var file_path: Cache.Path = .{
|
||||
.root_dir = gen.file.step.owner.build_root,
|
||||
.root_dir = Cache.Directory.cwd(),
|
||||
.sub_path = gen.file.path orelse {
|
||||
std.debug.lockStdErr();
|
||||
const stderr = std.io.getStdErr();
|
||||
|
||||
@ -896,8 +896,8 @@ pub const Manifest = struct {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a hex encoded hash of the inputs.
|
||||
pub fn final(self: *Manifest) HexDigest {
|
||||
/// Returns a binary hash of the inputs.
|
||||
pub fn finalBin(self: *Manifest) BinDigest {
|
||||
assert(self.manifest_file != null);
|
||||
|
||||
// We don't close the manifest file yet, because we want to
|
||||
@ -908,7 +908,12 @@ pub const Manifest = struct {
|
||||
|
||||
var bin_digest: BinDigest = undefined;
|
||||
self.hash.hasher.final(&bin_digest);
|
||||
return bin_digest;
|
||||
}
|
||||
|
||||
/// Returns a hex encoded hash of the inputs.
|
||||
pub fn final(self: *Manifest) HexDigest {
|
||||
const bin_digest = self.finalBin();
|
||||
return binToHex(bin_digest);
|
||||
}
|
||||
|
||||
|
||||
@ -100,6 +100,15 @@ pub fn start(
|
||||
}
|
||||
|
||||
fn rebuildTestsWorkerRun(run: *Step.Run, ttyconf: std.io.tty.Config, parent_prog_node: std.Progress.Node) void {
|
||||
rebuildTestsWorkerRunFallible(run, ttyconf, parent_prog_node) catch |err| {
|
||||
const compile = run.producer.?;
|
||||
log.err("step '{s}': failed to rebuild in fuzz mode: {s}", .{
|
||||
compile.step.name, @errorName(err),
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
fn rebuildTestsWorkerRunFallible(run: *Step.Run, ttyconf: std.io.tty.Config, parent_prog_node: std.Progress.Node) !void {
|
||||
const gpa = run.step.owner.allocator;
|
||||
const stderr = std.io.getStdErr();
|
||||
|
||||
@ -121,14 +130,9 @@ fn rebuildTestsWorkerRun(run: *Step.Run, ttyconf: std.io.tty.Config, parent_prog
|
||||
|
||||
const rebuilt_bin_path = result catch |err| switch (err) {
|
||||
error.MakeFailed => return,
|
||||
else => {
|
||||
log.err("step '{s}': failed to rebuild in fuzz mode: {s}", .{
|
||||
compile.step.name, @errorName(err),
|
||||
});
|
||||
return;
|
||||
},
|
||||
else => |other| return other,
|
||||
};
|
||||
run.rebuilt_executable = rebuilt_bin_path;
|
||||
run.rebuilt_executable = try rebuilt_bin_path.join(gpa, compile.out_filename);
|
||||
}
|
||||
|
||||
fn fuzzWorkerRun(
|
||||
|
||||
@ -8,6 +8,8 @@ const Coverage = std.debug.Coverage;
|
||||
const abi = std.Build.Fuzz.abi;
|
||||
const log = std.log;
|
||||
const assert = std.debug.assert;
|
||||
const Cache = std.Build.Cache;
|
||||
const Path = Cache.Path;
|
||||
|
||||
const WebServer = @This();
|
||||
|
||||
@ -31,6 +33,10 @@ coverage_mutex: std.Thread.Mutex,
|
||||
/// Signaled when `coverage_files` changes.
|
||||
coverage_condition: std.Thread.Condition,
|
||||
|
||||
const fuzzer_bin_name = "fuzzer";
|
||||
const fuzzer_arch_os_abi = "wasm32-freestanding";
|
||||
const fuzzer_cpu_features = "baseline+atomics+bulk_memory+multivalue+mutable_globals+nontrapping_fptoint+reference_types+sign_ext";
|
||||
|
||||
const CoverageMap = struct {
|
||||
mapped_memory: []align(std.mem.page_size) const u8,
|
||||
coverage: Coverage,
|
||||
@ -181,9 +187,18 @@ fn serveWasm(
|
||||
|
||||
// Do the compilation every request, so that the user can edit the files
|
||||
// and see the changes without restarting the server.
|
||||
const wasm_binary_path = try buildWasmBinary(ws, arena, optimize_mode);
|
||||
const wasm_base_path = try buildWasmBinary(ws, arena, optimize_mode);
|
||||
const bin_name = try std.zig.binNameAlloc(arena, .{
|
||||
.root_name = fuzzer_bin_name,
|
||||
.target = std.zig.system.resolveTargetQuery(std.Build.parseTargetQuery(.{
|
||||
.arch_os_abi = fuzzer_arch_os_abi,
|
||||
.cpu_features = fuzzer_cpu_features,
|
||||
}) catch unreachable) catch unreachable,
|
||||
.output_mode = .Exe,
|
||||
});
|
||||
// std.http.Server does not have a sendfile API yet.
|
||||
const file_contents = try std.fs.cwd().readFileAlloc(gpa, wasm_binary_path, 10 * 1024 * 1024);
|
||||
const bin_path = try wasm_base_path.join(arena, bin_name);
|
||||
const file_contents = try bin_path.root_dir.handle.readFileAlloc(gpa, bin_path.sub_path, 10 * 1024 * 1024);
|
||||
defer gpa.free(file_contents);
|
||||
try request.respond(file_contents, .{
|
||||
.extra_headers = &.{
|
||||
@ -197,7 +212,7 @@ fn buildWasmBinary(
|
||||
ws: *WebServer,
|
||||
arena: Allocator,
|
||||
optimize_mode: std.builtin.OptimizeMode,
|
||||
) ![]const u8 {
|
||||
) !Path {
|
||||
const gpa = ws.gpa;
|
||||
|
||||
const main_src_path: Build.Cache.Path = .{
|
||||
@ -219,11 +234,11 @@ fn buildWasmBinary(
|
||||
ws.zig_exe_path, "build-exe", //
|
||||
"-fno-entry", //
|
||||
"-O", @tagName(optimize_mode), //
|
||||
"-target", "wasm32-freestanding", //
|
||||
"-mcpu", "baseline+atomics+bulk_memory+multivalue+mutable_globals+nontrapping_fptoint+reference_types+sign_ext", //
|
||||
"-target", fuzzer_arch_os_abi, //
|
||||
"-mcpu", fuzzer_cpu_features, //
|
||||
"--cache-dir", ws.global_cache_directory.path orelse ".", //
|
||||
"--global-cache-dir", ws.global_cache_directory.path orelse ".", //
|
||||
"--name", "fuzzer", //
|
||||
"--name", fuzzer_bin_name, //
|
||||
"-rdynamic", //
|
||||
"-fsingle-threaded", //
|
||||
"--dep", "Walk", //
|
||||
@ -251,7 +266,7 @@ fn buildWasmBinary(
|
||||
try sendMessage(child.stdin.?, .exit);
|
||||
|
||||
const Header = std.zig.Server.Message.Header;
|
||||
var result: ?[]const u8 = null;
|
||||
var result: ?Path = null;
|
||||
var result_error_bundle = std.zig.ErrorBundle.empty;
|
||||
|
||||
const stdout = poller.fifo(.stdout);
|
||||
@ -288,13 +303,17 @@ fn buildWasmBinary(
|
||||
.extra = extra_array,
|
||||
};
|
||||
},
|
||||
.emit_bin_path => {
|
||||
const EbpHdr = std.zig.Server.Message.EmitBinPath;
|
||||
.emit_digest => {
|
||||
const EbpHdr = std.zig.Server.Message.EmitDigest;
|
||||
const ebp_hdr = @as(*align(1) const EbpHdr, @ptrCast(body));
|
||||
if (!ebp_hdr.flags.cache_hit) {
|
||||
log.info("source changes detected; rebuilt wasm component", .{});
|
||||
}
|
||||
result = try arena.dupe(u8, body[@sizeOf(EbpHdr)..]);
|
||||
const digest = body[@sizeOf(EbpHdr)..][0..Cache.bin_digest_len];
|
||||
result = Path{
|
||||
.root_dir = ws.global_cache_directory,
|
||||
.sub_path = try arena.dupe(u8, "o" ++ std.fs.path.sep_str ++ Cache.binToHex(digest.*)),
|
||||
};
|
||||
},
|
||||
else => {}, // ignore other messages
|
||||
}
|
||||
@ -568,10 +587,7 @@ fn prepareTables(
|
||||
};
|
||||
errdefer gop.value_ptr.coverage.deinit(gpa);
|
||||
|
||||
const rebuilt_exe_path: Build.Cache.Path = .{
|
||||
.root_dir = Build.Cache.Directory.cwd(),
|
||||
.sub_path = run_step.rebuilt_executable.?,
|
||||
};
|
||||
const rebuilt_exe_path = run_step.rebuilt_executable.?;
|
||||
var debug_info = std.debug.Info.load(gpa, rebuilt_exe_path, &gop.value_ptr.coverage) catch |err| {
|
||||
log.err("step '{s}': failed to load debug information for '{}': {s}", .{
|
||||
run_step.step.name, rebuilt_exe_path, @errorName(err),
|
||||
|
||||
@ -317,6 +317,8 @@ const Build = std.Build;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const assert = std.debug.assert;
|
||||
const builtin = @import("builtin");
|
||||
const Cache = Build.Cache;
|
||||
const Path = Cache.Path;
|
||||
|
||||
pub fn evalChildProcess(s: *Step, argv: []const []const u8) ![]u8 {
|
||||
const run_result = try captureChildProcess(s, std.Progress.Node.none, argv);
|
||||
@ -373,7 +375,7 @@ pub fn evalZigProcess(
|
||||
argv: []const []const u8,
|
||||
prog_node: std.Progress.Node,
|
||||
watch: bool,
|
||||
) !?[]const u8 {
|
||||
) !?Path {
|
||||
if (s.getZigProcess()) |zp| update: {
|
||||
assert(watch);
|
||||
if (std.Progress.have_ipc) if (zp.progress_ipc_fd) |fd| prog_node.setIpcFd(fd);
|
||||
@ -477,7 +479,7 @@ pub fn evalZigProcess(
|
||||
return result;
|
||||
}
|
||||
|
||||
fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool) !?[]const u8 {
|
||||
fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool) !?Path {
|
||||
const b = s.owner;
|
||||
const arena = b.allocator;
|
||||
|
||||
@ -487,7 +489,7 @@ fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool) !?[]const u8 {
|
||||
if (!watch) try sendMessage(zp.child.stdin.?, .exit);
|
||||
|
||||
const Header = std.zig.Server.Message.Header;
|
||||
var result: ?[]const u8 = null;
|
||||
var result: ?Path = null;
|
||||
|
||||
const stdout = zp.poller.fifo(.stdout);
|
||||
|
||||
@ -531,16 +533,15 @@ fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool) !?[]const u8 {
|
||||
break;
|
||||
}
|
||||
},
|
||||
.emit_bin_path => {
|
||||
const EbpHdr = std.zig.Server.Message.EmitBinPath;
|
||||
.emit_digest => {
|
||||
const EbpHdr = std.zig.Server.Message.EmitDigest;
|
||||
const ebp_hdr = @as(*align(1) const EbpHdr, @ptrCast(body));
|
||||
s.result_cached = ebp_hdr.flags.cache_hit;
|
||||
result = try arena.dupe(u8, body[@sizeOf(EbpHdr)..]);
|
||||
if (watch) {
|
||||
// This message indicates the end of the update.
|
||||
stdout.discard(body.len);
|
||||
break;
|
||||
}
|
||||
const digest = body[@sizeOf(EbpHdr)..][0..Cache.bin_digest_len];
|
||||
result = Path{
|
||||
.root_dir = b.cache_root,
|
||||
.sub_path = try arena.dupe(u8, "o" ++ std.fs.path.sep_str ++ Cache.binToHex(digest.*)),
|
||||
};
|
||||
},
|
||||
.file_system_inputs => {
|
||||
s.clearWatchInputs();
|
||||
|
||||
@ -17,6 +17,7 @@ const Module = std.Build.Module;
|
||||
const InstallDir = std.Build.InstallDir;
|
||||
const GeneratedFile = std.Build.GeneratedFile;
|
||||
const Compile = @This();
|
||||
const Path = std.Build.Cache.Path;
|
||||
|
||||
pub const base_id: Step.Id = .compile;
|
||||
|
||||
@ -1765,7 +1766,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
||||
|
||||
const zig_args = try getZigArgs(compile, false);
|
||||
|
||||
const maybe_output_bin_path = step.evalZigProcess(
|
||||
const maybe_output_dir = step.evalZigProcess(
|
||||
zig_args,
|
||||
options.progress_node,
|
||||
(b.graph.incremental == true) and options.watch,
|
||||
@ -1779,53 +1780,51 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
||||
};
|
||||
|
||||
// Update generated files
|
||||
if (maybe_output_bin_path) |output_bin_path| {
|
||||
const output_dir = fs.path.dirname(output_bin_path).?;
|
||||
|
||||
if (maybe_output_dir) |output_dir| {
|
||||
if (compile.emit_directory) |lp| {
|
||||
lp.path = output_dir;
|
||||
lp.path = b.fmt("{}", .{output_dir});
|
||||
}
|
||||
|
||||
// -femit-bin[=path] (default) Output machine code
|
||||
if (compile.generated_bin) |bin| {
|
||||
bin.path = b.pathJoin(&.{ output_dir, compile.out_filename });
|
||||
bin.path = output_dir.joinString(b.allocator, compile.out_filename) catch @panic("OOM");
|
||||
}
|
||||
|
||||
const sep = std.fs.path.sep;
|
||||
const sep = std.fs.path.sep_str;
|
||||
|
||||
// output PDB if someone requested it
|
||||
if (compile.generated_pdb) |pdb| {
|
||||
pdb.path = b.fmt("{s}{c}{s}.pdb", .{ output_dir, sep, compile.name });
|
||||
pdb.path = b.fmt("{}" ++ sep ++ "{s}.pdb", .{ output_dir, compile.name });
|
||||
}
|
||||
|
||||
// -femit-implib[=path] (default) Produce an import .lib when building a Windows DLL
|
||||
if (compile.generated_implib) |implib| {
|
||||
implib.path = b.fmt("{s}{c}{s}.lib", .{ output_dir, sep, compile.name });
|
||||
implib.path = b.fmt("{}" ++ sep ++ "{s}.lib", .{ output_dir, compile.name });
|
||||
}
|
||||
|
||||
// -femit-h[=path] Generate a C header file (.h)
|
||||
if (compile.generated_h) |lp| {
|
||||
lp.path = b.fmt("{s}{c}{s}.h", .{ output_dir, sep, compile.name });
|
||||
lp.path = b.fmt("{}" ++ sep ++ "{s}.h", .{ output_dir, compile.name });
|
||||
}
|
||||
|
||||
// -femit-docs[=path] Create a docs/ dir with html documentation
|
||||
if (compile.generated_docs) |generated_docs| {
|
||||
generated_docs.path = b.pathJoin(&.{ output_dir, "docs" });
|
||||
generated_docs.path = output_dir.joinString(b.allocator, "docs") catch @panic("OOM");
|
||||
}
|
||||
|
||||
// -femit-asm[=path] Output .s (assembly code)
|
||||
if (compile.generated_asm) |lp| {
|
||||
lp.path = b.fmt("{s}{c}{s}.s", .{ output_dir, sep, compile.name });
|
||||
lp.path = b.fmt("{}" ++ sep ++ "{s}.s", .{ output_dir, compile.name });
|
||||
}
|
||||
|
||||
// -femit-llvm-ir[=path] Produce a .ll file with optimized LLVM IR (requires LLVM extensions)
|
||||
if (compile.generated_llvm_ir) |lp| {
|
||||
lp.path = b.fmt("{s}{c}{s}.ll", .{ output_dir, sep, compile.name });
|
||||
lp.path = b.fmt("{}" ++ sep ++ "{s}.ll", .{ output_dir, compile.name });
|
||||
}
|
||||
|
||||
// -femit-llvm-bc[=path] Produce an optimized LLVM module as a .bc file (requires LLVM extensions)
|
||||
if (compile.generated_llvm_bc) |lp| {
|
||||
lp.path = b.fmt("{s}{c}{s}.bc", .{ output_dir, sep, compile.name });
|
||||
lp.path = b.fmt("{}" ++ sep ++ "{s}.bc", .{ output_dir, compile.name });
|
||||
}
|
||||
}
|
||||
|
||||
@ -1841,7 +1840,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rebuildInFuzzMode(c: *Compile, progress_node: std.Progress.Node) ![]const u8 {
|
||||
pub fn rebuildInFuzzMode(c: *Compile, progress_node: std.Progress.Node) !Path {
|
||||
const gpa = c.step.owner.allocator;
|
||||
|
||||
c.step.result_error_msgs.clearRetainingCapacity();
|
||||
|
||||
@ -125,10 +125,10 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
||||
|
||||
if (install_artifact.dest_dir) |dest_dir| {
|
||||
const full_dest_path = b.getInstallPath(dest_dir, install_artifact.dest_sub_path);
|
||||
const full_src_path = install_artifact.emitted_bin.?.getPath2(b, step);
|
||||
const p = fs.Dir.updateFile(cwd, full_src_path, cwd, full_dest_path, .{}) catch |err| {
|
||||
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}", .{
|
||||
full_src_path, full_dest_path, @errorName(err),
|
||||
src_path.sub_path, full_dest_path, @errorName(err),
|
||||
});
|
||||
};
|
||||
all_cached = all_cached and p == .fresh;
|
||||
@ -141,22 +141,22 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
||||
}
|
||||
|
||||
if (install_artifact.implib_dir) |implib_dir| {
|
||||
const full_src_path = install_artifact.emitted_implib.?.getPath2(b, step);
|
||||
const full_implib_path = b.getInstallPath(implib_dir, fs.path.basename(full_src_path));
|
||||
const p = fs.Dir.updateFile(cwd, full_src_path, cwd, full_implib_path, .{}) catch |err| {
|
||||
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}", .{
|
||||
full_src_path, full_implib_path, @errorName(err),
|
||||
src_path.sub_path, full_implib_path, @errorName(err),
|
||||
});
|
||||
};
|
||||
all_cached = all_cached and p == .fresh;
|
||||
}
|
||||
|
||||
if (install_artifact.pdb_dir) |pdb_dir| {
|
||||
const full_src_path = install_artifact.emitted_pdb.?.getPath2(b, step);
|
||||
const full_pdb_path = b.getInstallPath(pdb_dir, fs.path.basename(full_src_path));
|
||||
const p = fs.Dir.updateFile(cwd, full_src_path, cwd, full_pdb_path, .{}) catch |err| {
|
||||
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}", .{
|
||||
full_src_path, full_pdb_path, @errorName(err),
|
||||
src_path.sub_path, full_pdb_path, @errorName(err),
|
||||
});
|
||||
};
|
||||
all_cached = all_cached and p == .fresh;
|
||||
@ -164,11 +164,11 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
||||
|
||||
if (install_artifact.h_dir) |h_dir| {
|
||||
if (install_artifact.emitted_h) |emitted_h| {
|
||||
const full_src_path = emitted_h.getPath2(b, step);
|
||||
const full_h_path = b.getInstallPath(h_dir, fs.path.basename(full_src_path));
|
||||
const p = fs.Dir.updateFile(cwd, full_src_path, cwd, full_h_path, .{}) catch |err| {
|
||||
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}", .{
|
||||
full_src_path, full_h_path, @errorName(err),
|
||||
src_path.sub_path, full_h_path, @errorName(err),
|
||||
});
|
||||
};
|
||||
all_cached = all_cached and p == .fresh;
|
||||
@ -176,22 +176,22 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
||||
|
||||
for (install_artifact.artifact.installed_headers.items) |installation| switch (installation) {
|
||||
.file => |file| {
|
||||
const full_src_path = file.source.getPath2(b, step);
|
||||
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(cwd, full_src_path, cwd, full_h_path, .{}) catch |err| {
|
||||
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}", .{
|
||||
full_src_path, full_h_path, @errorName(err),
|
||||
src_path.sub_path, full_h_path, @errorName(err),
|
||||
});
|
||||
};
|
||||
all_cached = all_cached and p == .fresh;
|
||||
},
|
||||
.directory => |dir| {
|
||||
const full_src_dir_path = dir.source.getPath2(b, step);
|
||||
const src_dir_path = dir.source.getPath3(b, step);
|
||||
const full_h_prefix = b.getInstallPath(h_dir, dir.dest_rel_path);
|
||||
|
||||
var src_dir = b.build_root.handle.openDir(full_src_dir_path, .{ .iterate = true }) catch |err| {
|
||||
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}", .{
|
||||
full_src_dir_path, @errorName(err),
|
||||
src_dir_path.sub_path, @errorName(err),
|
||||
});
|
||||
};
|
||||
defer src_dir.close();
|
||||
@ -208,14 +208,15 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
||||
continue :next_entry;
|
||||
}
|
||||
}
|
||||
const full_src_entry_path = b.pathJoin(&.{ full_src_dir_path, entry.path });
|
||||
|
||||
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(cwd, full_src_entry_path, cwd, full_dest_path, .{}) catch |err| {
|
||||
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}", .{
|
||||
full_src_entry_path, full_dest_path, @errorName(err),
|
||||
src_entry_path.sub_path, full_dest_path, @errorName(err),
|
||||
});
|
||||
};
|
||||
all_cached = all_cached and p == .fresh;
|
||||
|
||||
@ -7,6 +7,7 @@ const mem = std.mem;
|
||||
const process = std.process;
|
||||
const EnvMap = process.EnvMap;
|
||||
const assert = std.debug.assert;
|
||||
const Path = Build.Cache.Path;
|
||||
|
||||
const Run = @This();
|
||||
|
||||
@ -93,7 +94,7 @@ cached_test_metadata: ?CachedTestMetadata = null,
|
||||
|
||||
/// Populated during the fuzz phase if this run step corresponds to a unit test
|
||||
/// executable that contains fuzz tests.
|
||||
rebuilt_executable: ?[]const u8,
|
||||
rebuilt_executable: ?Path,
|
||||
|
||||
/// If this Run step was produced by a Compile step, it is tracked here.
|
||||
producer: ?*Step.Compile,
|
||||
@ -872,7 +873,7 @@ pub fn rerunInFuzzMode(
|
||||
.artifact => |pa| {
|
||||
const artifact = pa.artifact;
|
||||
const file_path = if (artifact == run.producer.?)
|
||||
run.rebuilt_executable.?
|
||||
b.fmt("{}", .{run.rebuilt_executable.?})
|
||||
else
|
||||
(artifact.installed_path orelse artifact.generated_bin.?.path.?);
|
||||
try argv_list.append(arena, b.fmt("{s}{s}", .{ pa.prefix, file_path }));
|
||||
|
||||
@ -153,12 +153,12 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
|
||||
try argv_list.append(c_macro);
|
||||
}
|
||||
|
||||
try argv_list.append(translate_c.source.getPath2(b, step));
|
||||
const c_source_path = translate_c.source.getPath2(b, step);
|
||||
try argv_list.append(c_source_path);
|
||||
|
||||
const output_path = try step.evalZigProcess(argv_list.items, prog_node, false);
|
||||
const output_dir = try step.evalZigProcess(argv_list.items, prog_node, false);
|
||||
|
||||
translate_c.out_basename = fs.path.basename(output_path.?);
|
||||
const output_dir = fs.path.dirname(output_path.?).?;
|
||||
|
||||
translate_c.output_file.path = b.pathJoin(&.{ output_dir, translate_c.out_basename });
|
||||
const basename = std.fs.path.stem(std.fs.path.basename(c_source_path));
|
||||
translate_c.out_basename = b.fmt("{s}.zig", .{basename});
|
||||
translate_c.output_file.path = output_dir.?.joinString(b.allocator, translate_c.out_basename) catch @panic("OOM");
|
||||
}
|
||||
|
||||
@ -14,8 +14,8 @@ pub const Message = struct {
|
||||
zig_version,
|
||||
/// Body is an ErrorBundle.
|
||||
error_bundle,
|
||||
/// Body is a EmitBinPath.
|
||||
emit_bin_path,
|
||||
/// Body is a EmitDigest.
|
||||
emit_digest,
|
||||
/// Body is a TestMetadata
|
||||
test_metadata,
|
||||
/// Body is a TestResults
|
||||
@ -82,8 +82,8 @@ pub const Message = struct {
|
||||
};
|
||||
|
||||
/// Trailing:
|
||||
/// * file system path where the emitted binary can be found
|
||||
pub const EmitBinPath = extern struct {
|
||||
/// * the hex digest of the cache directory within the /o/ subdirectory.
|
||||
pub const EmitDigest = extern struct {
|
||||
flags: Flags,
|
||||
|
||||
pub const Flags = packed struct(u8) {
|
||||
@ -196,17 +196,17 @@ pub fn serveU64Message(s: *Server, tag: OutMessage.Tag, int: u64) !void {
|
||||
}, &.{std.mem.asBytes(&msg_le)});
|
||||
}
|
||||
|
||||
pub fn serveEmitBinPath(
|
||||
pub fn serveEmitDigest(
|
||||
s: *Server,
|
||||
fs_path: []const u8,
|
||||
header: OutMessage.EmitBinPath,
|
||||
digest: *const [Cache.bin_digest_len]u8,
|
||||
header: OutMessage.EmitDigest,
|
||||
) !void {
|
||||
try s.serveMessage(.{
|
||||
.tag = .emit_bin_path,
|
||||
.bytes_len = @intCast(fs_path.len + @sizeOf(OutMessage.EmitBinPath)),
|
||||
.tag = .emit_digest,
|
||||
.bytes_len = @intCast(digest.len + @sizeOf(OutMessage.EmitDigest)),
|
||||
}, &.{
|
||||
std.mem.asBytes(&header),
|
||||
fs_path,
|
||||
digest,
|
||||
});
|
||||
}
|
||||
|
||||
@ -328,3 +328,4 @@ const Allocator = std.mem.Allocator;
|
||||
const assert = std.debug.assert;
|
||||
const native_endian = builtin.target.cpu.arch.endian();
|
||||
const need_bswap = native_endian != .little;
|
||||
const Cache = std.Build.Cache;
|
||||
|
||||
@ -39,6 +39,8 @@ const Air = @import("Air.zig");
|
||||
const Builtin = @import("Builtin.zig");
|
||||
const LlvmObject = @import("codegen/llvm.zig").Object;
|
||||
const dev = @import("dev.zig");
|
||||
pub const Directory = Cache.Directory;
|
||||
const Path = Cache.Path;
|
||||
|
||||
pub const Config = @import("Compilation/Config.zig");
|
||||
|
||||
@ -70,9 +72,9 @@ bin_file: ?*link.File,
|
||||
/// The root path for the dynamic linker and system libraries (as well as frameworks on Darwin)
|
||||
sysroot: ?[]const u8,
|
||||
/// This is `null` when not building a Windows DLL, or when `-fno-emit-implib` is used.
|
||||
implib_emit: ?Emit,
|
||||
implib_emit: ?Path,
|
||||
/// This is non-null when `-femit-docs` is provided.
|
||||
docs_emit: ?Emit,
|
||||
docs_emit: ?Path,
|
||||
root_name: [:0]const u8,
|
||||
include_compiler_rt: bool,
|
||||
objects: []Compilation.LinkObject,
|
||||
@ -269,27 +271,9 @@ llvm_opt_bisect_limit: c_int,
|
||||
|
||||
file_system_inputs: ?*std.ArrayListUnmanaged(u8),
|
||||
|
||||
pub const Emit = struct {
|
||||
/// Where the output will go.
|
||||
directory: Directory,
|
||||
/// Path to the output file, relative to `directory`.
|
||||
sub_path: []const u8,
|
||||
|
||||
/// Returns the full path to `basename` if it were in the same directory as the
|
||||
/// `Emit` sub_path.
|
||||
pub fn basenamePath(emit: Emit, arena: Allocator, basename: []const u8) ![:0]const u8 {
|
||||
const full_path = if (emit.directory.path) |p|
|
||||
try std.fs.path.join(arena, &[_][]const u8{ p, emit.sub_path })
|
||||
else
|
||||
emit.sub_path;
|
||||
|
||||
if (std.fs.path.dirname(full_path)) |dirname| {
|
||||
return try std.fs.path.joinZ(arena, &.{ dirname, basename });
|
||||
} else {
|
||||
return try arena.dupeZ(u8, basename);
|
||||
}
|
||||
}
|
||||
};
|
||||
/// This is the digest of the cache for the current compilation.
|
||||
/// This digest will be known after update() is called.
|
||||
digest: ?[Cache.bin_digest_len]u8 = null,
|
||||
|
||||
pub const default_stack_protector_buffer_size = target_util.default_stack_protector_buffer_size;
|
||||
pub const SemaError = Zcu.SemaError;
|
||||
@ -868,8 +852,6 @@ pub const LldError = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub const Directory = Cache.Directory;
|
||||
|
||||
pub const EmitLoc = struct {
|
||||
/// If this is `null` it means the file will be output to the cache directory.
|
||||
/// When provided, both the open file handle and the path name must outlive the `Compilation`.
|
||||
@ -1672,7 +1654,9 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
|
||||
// In the case of incremental cache mode, this `artifact_directory`
|
||||
// is computed based on a hash of non-linker inputs, and it is where all
|
||||
// build artifacts are stored (even while in-progress).
|
||||
comp.digest = hash.peekBin();
|
||||
const digest = hash.final();
|
||||
|
||||
const artifact_sub_dir = "o" ++ std.fs.path.sep_str ++ digest;
|
||||
var artifact_dir = try options.local_cache_directory.handle.makeOpenPath(artifact_sub_dir, .{});
|
||||
errdefer artifact_dir.close();
|
||||
@ -1688,8 +1672,8 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
|
||||
comp.cache_use = .{ .incremental = incremental };
|
||||
|
||||
if (options.emit_bin) |emit_bin| {
|
||||
const emit: Emit = .{
|
||||
.directory = emit_bin.directory orelse artifact_directory,
|
||||
const emit: Path = .{
|
||||
.root_dir = emit_bin.directory orelse artifact_directory,
|
||||
.sub_path = emit_bin.basename,
|
||||
};
|
||||
comp.bin_file = try link.File.open(arena, comp, emit, lf_open_opts);
|
||||
@ -1697,14 +1681,14 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
|
||||
|
||||
if (options.emit_implib) |emit_implib| {
|
||||
comp.implib_emit = .{
|
||||
.directory = emit_implib.directory orelse artifact_directory,
|
||||
.root_dir = emit_implib.directory orelse artifact_directory,
|
||||
.sub_path = emit_implib.basename,
|
||||
};
|
||||
}
|
||||
|
||||
if (options.emit_docs) |emit_docs| {
|
||||
comp.docs_emit = .{
|
||||
.directory = emit_docs.directory orelse artifact_directory,
|
||||
.root_dir = emit_docs.directory orelse artifact_directory,
|
||||
.sub_path = emit_docs.basename,
|
||||
};
|
||||
}
|
||||
@ -2121,9 +2105,11 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
|
||||
|
||||
comp.last_update_was_cache_hit = true;
|
||||
log.debug("CacheMode.whole cache hit for {s}", .{comp.root_name});
|
||||
const digest = man.final();
|
||||
const bin_digest = man.finalBin();
|
||||
const hex_digest = Cache.binToHex(bin_digest);
|
||||
|
||||
comp.wholeCacheModeSetBinFilePath(whole, &digest);
|
||||
comp.digest = bin_digest;
|
||||
comp.wholeCacheModeSetBinFilePath(whole, &hex_digest);
|
||||
|
||||
assert(whole.lock == null);
|
||||
whole.lock = man.toOwnedLock();
|
||||
@ -2155,21 +2141,21 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
|
||||
|
||||
if (whole.implib_sub_path) |sub_path| {
|
||||
comp.implib_emit = .{
|
||||
.directory = tmp_artifact_directory,
|
||||
.root_dir = tmp_artifact_directory,
|
||||
.sub_path = std.fs.path.basename(sub_path),
|
||||
};
|
||||
}
|
||||
|
||||
if (whole.docs_sub_path) |sub_path| {
|
||||
comp.docs_emit = .{
|
||||
.directory = tmp_artifact_directory,
|
||||
.root_dir = tmp_artifact_directory,
|
||||
.sub_path = std.fs.path.basename(sub_path),
|
||||
};
|
||||
}
|
||||
|
||||
if (whole.bin_sub_path) |sub_path| {
|
||||
const emit: Emit = .{
|
||||
.directory = tmp_artifact_directory,
|
||||
const emit: Path = .{
|
||||
.root_dir = tmp_artifact_directory,
|
||||
.sub_path = std.fs.path.basename(sub_path),
|
||||
};
|
||||
comp.bin_file = try link.File.createEmpty(arena, comp, emit, whole.lf_open_opts);
|
||||
@ -2329,7 +2315,8 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
|
||||
try man.populateOtherManifest(pwc.manifest, pwc.prefix_map);
|
||||
}
|
||||
|
||||
const digest = man.final();
|
||||
const bin_digest = man.finalBin();
|
||||
const hex_digest = Cache.binToHex(bin_digest);
|
||||
|
||||
// Rename the temporary directory into place.
|
||||
// Close tmp dir and link.File to avoid open handle during rename.
|
||||
@ -2341,7 +2328,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
|
||||
|
||||
const s = std.fs.path.sep_str;
|
||||
const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(tmp_dir_rand_int);
|
||||
const o_sub_path = "o" ++ s ++ digest;
|
||||
const o_sub_path = "o" ++ s ++ hex_digest;
|
||||
|
||||
// Work around windows `AccessDenied` if any files within this
|
||||
// directory are open by closing and reopening the file handles.
|
||||
@ -2376,14 +2363,15 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
|
||||
},
|
||||
);
|
||||
};
|
||||
comp.wholeCacheModeSetBinFilePath(whole, &digest);
|
||||
comp.digest = bin_digest;
|
||||
comp.wholeCacheModeSetBinFilePath(whole, &hex_digest);
|
||||
|
||||
// The linker flush functions need to know the final output path
|
||||
// for debug info purposes because executable debug info contains
|
||||
// references object file paths.
|
||||
if (comp.bin_file) |lf| {
|
||||
lf.emit = .{
|
||||
.directory = comp.local_cache_directory,
|
||||
.root_dir = comp.local_cache_directory,
|
||||
.sub_path = whole.bin_sub_path.?,
|
||||
};
|
||||
|
||||
@ -2393,9 +2381,10 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
|
||||
}
|
||||
}
|
||||
|
||||
try flush(comp, arena, .main, main_progress_node);
|
||||
|
||||
if (try comp.totalErrorCount() != 0) return;
|
||||
try flush(comp, arena, .{
|
||||
.root_dir = comp.local_cache_directory,
|
||||
.sub_path = o_sub_path,
|
||||
}, .main, main_progress_node);
|
||||
|
||||
// Failure here only means an unnecessary cache miss.
|
||||
man.writeManifest() catch |err| {
|
||||
@ -2410,8 +2399,10 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
|
||||
assert(whole.lock == null);
|
||||
whole.lock = man.toOwnedLock();
|
||||
},
|
||||
.incremental => {
|
||||
try flush(comp, arena, .main, main_progress_node);
|
||||
.incremental => |incremental| {
|
||||
try flush(comp, arena, .{
|
||||
.root_dir = incremental.artifact_directory,
|
||||
}, .main, main_progress_node);
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -2440,7 +2431,13 @@ pub fn appendFileSystemInput(
|
||||
std.debug.panic("missing prefix directory: {}, {s}", .{ root, sub_file_path });
|
||||
}
|
||||
|
||||
fn flush(comp: *Compilation, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void {
|
||||
fn flush(
|
||||
comp: *Compilation,
|
||||
arena: Allocator,
|
||||
default_artifact_directory: Path,
|
||||
tid: Zcu.PerThread.Id,
|
||||
prog_node: std.Progress.Node,
|
||||
) !void {
|
||||
if (comp.bin_file) |lf| {
|
||||
// This is needed before reading the error flags.
|
||||
lf.flush(arena, tid, prog_node) catch |err| switch (err) {
|
||||
@ -2454,17 +2451,7 @@ fn flush(comp: *Compilation, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:
|
||||
try link.File.C.flushEmitH(zcu);
|
||||
|
||||
if (zcu.llvm_object) |llvm_object| {
|
||||
const default_emit = switch (comp.cache_use) {
|
||||
.whole => |whole| .{
|
||||
.directory = whole.tmp_artifact_directory.?,
|
||||
.sub_path = "dummy",
|
||||
},
|
||||
.incremental => |incremental| .{
|
||||
.directory = incremental.artifact_directory,
|
||||
.sub_path = "dummy",
|
||||
},
|
||||
};
|
||||
try emitLlvmObject(comp, arena, default_emit, null, llvm_object, prog_node);
|
||||
try emitLlvmObject(comp, arena, default_artifact_directory, null, llvm_object, prog_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2533,7 +2520,7 @@ fn wholeCacheModeSetBinFilePath(
|
||||
@memcpy(sub_path[digest_start..][0..digest.len], digest);
|
||||
|
||||
comp.implib_emit = .{
|
||||
.directory = comp.local_cache_directory,
|
||||
.root_dir = comp.local_cache_directory,
|
||||
.sub_path = sub_path,
|
||||
};
|
||||
}
|
||||
@ -2542,7 +2529,7 @@ fn wholeCacheModeSetBinFilePath(
|
||||
@memcpy(sub_path[digest_start..][0..digest.len], digest);
|
||||
|
||||
comp.docs_emit = .{
|
||||
.directory = comp.local_cache_directory,
|
||||
.root_dir = comp.local_cache_directory,
|
||||
.sub_path = sub_path,
|
||||
};
|
||||
}
|
||||
@ -2745,7 +2732,7 @@ fn emitOthers(comp: *Compilation) void {
|
||||
pub fn emitLlvmObject(
|
||||
comp: *Compilation,
|
||||
arena: Allocator,
|
||||
default_emit: Emit,
|
||||
default_artifact_directory: Path,
|
||||
bin_emit_loc: ?EmitLoc,
|
||||
llvm_object: LlvmObject.Ptr,
|
||||
prog_node: std.Progress.Node,
|
||||
@ -2756,10 +2743,10 @@ pub fn emitLlvmObject(
|
||||
try llvm_object.emit(.{
|
||||
.pre_ir_path = comp.verbose_llvm_ir,
|
||||
.pre_bc_path = comp.verbose_llvm_bc,
|
||||
.bin_path = try resolveEmitLoc(arena, default_emit, bin_emit_loc),
|
||||
.asm_path = try resolveEmitLoc(arena, default_emit, comp.emit_asm),
|
||||
.post_ir_path = try resolveEmitLoc(arena, default_emit, comp.emit_llvm_ir),
|
||||
.post_bc_path = try resolveEmitLoc(arena, default_emit, comp.emit_llvm_bc),
|
||||
.bin_path = try resolveEmitLoc(arena, default_artifact_directory, bin_emit_loc),
|
||||
.asm_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_asm),
|
||||
.post_ir_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_llvm_ir),
|
||||
.post_bc_path = try resolveEmitLoc(arena, default_artifact_directory, comp.emit_llvm_bc),
|
||||
|
||||
.is_debug = comp.root_mod.optimize_mode == .Debug,
|
||||
.is_small = comp.root_mod.optimize_mode == .ReleaseSmall,
|
||||
@ -2772,14 +2759,14 @@ pub fn emitLlvmObject(
|
||||
|
||||
fn resolveEmitLoc(
|
||||
arena: Allocator,
|
||||
default_emit: Emit,
|
||||
default_artifact_directory: Path,
|
||||
opt_loc: ?EmitLoc,
|
||||
) Allocator.Error!?[*:0]const u8 {
|
||||
const loc = opt_loc orelse return null;
|
||||
const slice = if (loc.directory) |directory|
|
||||
try directory.joinZ(arena, &.{loc.basename})
|
||||
else
|
||||
try default_emit.basenamePath(arena, loc.basename);
|
||||
try default_artifact_directory.joinStringZ(arena, loc.basename);
|
||||
return slice.ptr;
|
||||
}
|
||||
|
||||
@ -3035,7 +3022,7 @@ pub fn saveState(comp: *Compilation) !void {
|
||||
|
||||
// Using an atomic file prevents a crash or power failure from corrupting
|
||||
// the previous incremental compilation state.
|
||||
var af = try lf.emit.directory.handle.atomicFile(basename, .{});
|
||||
var af = try lf.emit.root_dir.handle.atomicFile(basename, .{});
|
||||
defer af.deinit();
|
||||
try af.file.pwritevAll(bufs.items, 0);
|
||||
try af.finish();
|
||||
@ -4000,11 +3987,11 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
|
||||
return comp.lockAndSetMiscFailure(.docs_copy, "no Zig code to document", .{});
|
||||
|
||||
const emit = comp.docs_emit.?;
|
||||
var out_dir = emit.directory.handle.makeOpenPath(emit.sub_path, .{}) catch |err| {
|
||||
var out_dir = emit.root_dir.handle.makeOpenPath(emit.sub_path, .{}) catch |err| {
|
||||
return comp.lockAndSetMiscFailure(
|
||||
.docs_copy,
|
||||
"unable to create output directory '{}{s}': {s}",
|
||||
.{ emit.directory, emit.sub_path, @errorName(err) },
|
||||
.{ emit.root_dir, emit.sub_path, @errorName(err) },
|
||||
);
|
||||
};
|
||||
defer out_dir.close();
|
||||
@ -4024,7 +4011,7 @@ fn docsCopyFallible(comp: *Compilation) anyerror!void {
|
||||
return comp.lockAndSetMiscFailure(
|
||||
.docs_copy,
|
||||
"unable to create '{}{s}/sources.tar': {s}",
|
||||
.{ emit.directory, emit.sub_path, @errorName(err) },
|
||||
.{ emit.root_dir, emit.sub_path, @errorName(err) },
|
||||
);
|
||||
};
|
||||
defer tar_file.close();
|
||||
@ -4223,11 +4210,11 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
|
||||
try comp.updateSubCompilation(sub_compilation, .docs_wasm, prog_node);
|
||||
|
||||
const emit = comp.docs_emit.?;
|
||||
var out_dir = emit.directory.handle.makeOpenPath(emit.sub_path, .{}) catch |err| {
|
||||
var out_dir = emit.root_dir.handle.makeOpenPath(emit.sub_path, .{}) catch |err| {
|
||||
return comp.lockAndSetMiscFailure(
|
||||
.docs_copy,
|
||||
"unable to create output directory '{}{s}': {s}",
|
||||
.{ emit.directory, emit.sub_path, @errorName(err) },
|
||||
.{ emit.root_dir, emit.sub_path, @errorName(err) },
|
||||
);
|
||||
};
|
||||
defer out_dir.close();
|
||||
@ -4241,7 +4228,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
|
||||
return comp.lockAndSetMiscFailure(.docs_copy, "unable to copy '{}{s}' to '{}{s}': {s}", .{
|
||||
sub_compilation.local_cache_directory,
|
||||
sub_compilation.cache_use.whole.bin_sub_path.?,
|
||||
emit.directory,
|
||||
emit.root_dir,
|
||||
emit.sub_path,
|
||||
@errorName(err),
|
||||
});
|
||||
@ -4403,7 +4390,7 @@ pub fn obtainWin32ResourceCacheManifest(comp: *const Compilation) Cache.Manifest
|
||||
}
|
||||
|
||||
pub const CImportResult = struct {
|
||||
out_zig_path: []u8,
|
||||
digest: [Cache.bin_digest_len]u8,
|
||||
cache_hit: bool,
|
||||
errors: std.zig.ErrorBundle,
|
||||
|
||||
@ -4413,8 +4400,6 @@ pub const CImportResult = struct {
|
||||
};
|
||||
|
||||
/// Caller owns returned memory.
|
||||
/// This API is currently coupled pretty tightly to stage1's needs; it will need to be reworked
|
||||
/// a bit when we want to start using it from self-hosted.
|
||||
pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module) !CImportResult {
|
||||
dev.check(.translate_c_command);
|
||||
|
||||
@ -4503,7 +4488,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.SemanticAnalyzeFail => {
|
||||
return CImportResult{
|
||||
.out_zig_path = "",
|
||||
.digest = undefined,
|
||||
.cache_hit = actual_hit,
|
||||
.errors = errors,
|
||||
};
|
||||
@ -4528,8 +4513,9 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module
|
||||
.incremental => {},
|
||||
}
|
||||
|
||||
const digest = man.final();
|
||||
const o_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &digest });
|
||||
const bin_digest = man.finalBin();
|
||||
const hex_digest = Cache.binToHex(bin_digest);
|
||||
const o_sub_path = "o" ++ std.fs.path.sep_str ++ hex_digest;
|
||||
var o_dir = try comp.local_cache_directory.handle.makeOpenPath(o_sub_path, .{});
|
||||
defer o_dir.close();
|
||||
|
||||
@ -4541,8 +4527,8 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module
|
||||
|
||||
try out_zig_file.writeAll(formatted);
|
||||
|
||||
break :digest digest;
|
||||
} else man.final();
|
||||
break :digest bin_digest;
|
||||
} else man.finalBin();
|
||||
|
||||
if (man.have_exclusive_lock) {
|
||||
// Write the updated manifest. This is a no-op if the manifest is not dirty. Note that it is
|
||||
@ -4554,14 +4540,8 @@ pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module
|
||||
};
|
||||
}
|
||||
|
||||
const out_zig_path = try comp.local_cache_directory.join(comp.arena, &.{
|
||||
"o", &digest, cimport_zig_basename,
|
||||
});
|
||||
if (comp.verbose_cimport) {
|
||||
log.info("C import output: {s}", .{out_zig_path});
|
||||
}
|
||||
return CImportResult{
|
||||
.out_zig_path = out_zig_path,
|
||||
.digest = digest,
|
||||
.cache_hit = actual_hit,
|
||||
.errors = std.zig.ErrorBundle.empty,
|
||||
};
|
||||
@ -4800,7 +4780,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: std.Pr
|
||||
try argv.appendSlice(c_object.src.cache_exempt_flags);
|
||||
|
||||
const out_obj_path = if (comp.bin_file) |lf|
|
||||
try lf.emit.directory.join(arena, &.{lf.emit.sub_path})
|
||||
try lf.emit.root_dir.join(arena, &.{lf.emit.sub_path})
|
||||
else
|
||||
"/dev/null";
|
||||
|
||||
|
||||
11
src/Sema.zig
11
src/Sema.zig
@ -183,6 +183,7 @@ const InternPool = @import("InternPool.zig");
|
||||
const Alignment = InternPool.Alignment;
|
||||
const AnalUnit = InternPool.AnalUnit;
|
||||
const ComptimeAllocIndex = InternPool.ComptimeAllocIndex;
|
||||
const Cache = std.Build.Cache;
|
||||
|
||||
pub const default_branch_quota = 1000;
|
||||
pub const default_reference_trace_len = 2;
|
||||
@ -5871,16 +5872,18 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
|
||||
return sema.failWithOwnedErrorMsg(&child_block, msg);
|
||||
}
|
||||
const parent_mod = parent_block.ownerModule();
|
||||
const digest = Cache.binToHex(c_import_res.digest);
|
||||
const c_import_zig_path = try comp.arena.dupe(u8, "o" ++ std.fs.path.sep_str ++ digest);
|
||||
const c_import_mod = Package.Module.create(comp.arena, .{
|
||||
.global_cache_directory = comp.global_cache_directory,
|
||||
.paths = .{
|
||||
.root = .{
|
||||
.root_dir = Compilation.Directory.cwd(),
|
||||
.sub_path = std.fs.path.dirname(c_import_res.out_zig_path) orelse "",
|
||||
.root_dir = comp.local_cache_directory,
|
||||
.sub_path = c_import_zig_path,
|
||||
},
|
||||
.root_src_path = std.fs.path.basename(c_import_res.out_zig_path),
|
||||
.root_src_path = "cimport.zig",
|
||||
},
|
||||
.fully_qualified_name = c_import_res.out_zig_path,
|
||||
.fully_qualified_name = c_import_zig_path,
|
||||
.cc_argv = parent_mod.cc_argv,
|
||||
.inherited = .{},
|
||||
.global = comp.config,
|
||||
|
||||
22
src/link.zig
22
src/link.zig
@ -11,6 +11,7 @@ const wasi_libc = @import("wasi_libc.zig");
|
||||
const Air = @import("Air.zig");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const Cache = std.Build.Cache;
|
||||
const Path = Cache.Path;
|
||||
const Compilation = @import("Compilation.zig");
|
||||
const LibCInstallation = std.zig.LibCInstallation;
|
||||
const Liveness = @import("Liveness.zig");
|
||||
@ -56,7 +57,7 @@ pub const File = struct {
|
||||
|
||||
/// The owner of this output File.
|
||||
comp: *Compilation,
|
||||
emit: Compilation.Emit,
|
||||
emit: Path,
|
||||
|
||||
file: ?fs.File,
|
||||
/// When linking with LLD, this linker code will output an object file only at
|
||||
@ -189,7 +190,7 @@ pub const File = struct {
|
||||
pub fn open(
|
||||
arena: Allocator,
|
||||
comp: *Compilation,
|
||||
emit: Compilation.Emit,
|
||||
emit: Path,
|
||||
options: OpenOptions,
|
||||
) !*File {
|
||||
switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) {
|
||||
@ -204,7 +205,7 @@ pub const File = struct {
|
||||
pub fn createEmpty(
|
||||
arena: Allocator,
|
||||
comp: *Compilation,
|
||||
emit: Compilation.Emit,
|
||||
emit: Path,
|
||||
options: OpenOptions,
|
||||
) !*File {
|
||||
switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) {
|
||||
@ -243,8 +244,8 @@ pub const File = struct {
|
||||
emit.sub_path, std.crypto.random.int(u32),
|
||||
});
|
||||
defer gpa.free(tmp_sub_path);
|
||||
try emit.directory.handle.copyFile(emit.sub_path, emit.directory.handle, tmp_sub_path, .{});
|
||||
try emit.directory.handle.rename(tmp_sub_path, emit.sub_path);
|
||||
try emit.root_dir.handle.copyFile(emit.sub_path, emit.root_dir.handle, tmp_sub_path, .{});
|
||||
try emit.root_dir.handle.rename(tmp_sub_path, emit.sub_path);
|
||||
switch (builtin.os.tag) {
|
||||
.linux => std.posix.ptrace(std.os.linux.PTRACE.ATTACH, pid, 0, 0) catch |err| {
|
||||
log.warn("ptrace failure: {s}", .{@errorName(err)});
|
||||
@ -260,7 +261,7 @@ pub const File = struct {
|
||||
const use_lld = build_options.have_llvm and comp.config.use_lld;
|
||||
const output_mode = comp.config.output_mode;
|
||||
const link_mode = comp.config.link_mode;
|
||||
base.file = try emit.directory.handle.createFile(emit.sub_path, .{
|
||||
base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{
|
||||
.truncate = false,
|
||||
.read = true,
|
||||
.mode = determineMode(use_lld, output_mode, link_mode),
|
||||
@ -603,7 +604,7 @@ pub const File = struct {
|
||||
// Until then, we do `lld -r -o output.o input.o` even though the output is the same
|
||||
// as the input. For the preprocessing case (`zig cc -E -o foo`) we copy the file
|
||||
// to the final location. See also the corresponding TODO in Coff linking.
|
||||
const full_out_path = try emit.directory.join(gpa, &[_][]const u8{emit.sub_path});
|
||||
const full_out_path = try emit.root_dir.join(gpa, &[_][]const u8{emit.sub_path});
|
||||
defer gpa.free(full_out_path);
|
||||
assert(comp.c_object_table.count() == 1);
|
||||
const the_key = comp.c_object_table.keys()[0];
|
||||
@ -751,7 +752,7 @@ pub const File = struct {
|
||||
const comp = base.comp;
|
||||
const gpa = comp.gpa;
|
||||
|
||||
const directory = base.emit.directory; // Just an alias to make it shorter to type.
|
||||
const directory = base.emit.root_dir; // Just an alias to make it shorter to type.
|
||||
const full_out_path = try directory.join(arena, &[_][]const u8{base.emit.sub_path});
|
||||
const full_out_path_z = try arena.dupeZ(u8, full_out_path);
|
||||
const opt_zcu = comp.module;
|
||||
@ -1029,7 +1030,10 @@ pub const File = struct {
|
||||
llvm_object: LlvmObject.Ptr,
|
||||
prog_node: std.Progress.Node,
|
||||
) !void {
|
||||
return base.comp.emitLlvmObject(arena, base.emit, .{
|
||||
return base.comp.emitLlvmObject(arena, .{
|
||||
.root_dir = base.emit.root_dir,
|
||||
.sub_path = std.fs.path.dirname(base.emit.sub_path) orelse "",
|
||||
}, .{
|
||||
.directory = null,
|
||||
.basename = base.zcu_object_sub_path.?,
|
||||
}, llvm_object, prog_node);
|
||||
|
||||
@ -3,6 +3,7 @@ const mem = std.mem;
|
||||
const assert = std.debug.assert;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const fs = std.fs;
|
||||
const Path = std.Build.Cache.Path;
|
||||
|
||||
const C = @This();
|
||||
const build_options = @import("build_options");
|
||||
@ -104,7 +105,7 @@ pub fn addString(this: *C, s: []const u8) Allocator.Error!String {
|
||||
pub fn open(
|
||||
arena: Allocator,
|
||||
comp: *Compilation,
|
||||
emit: Compilation.Emit,
|
||||
emit: Path,
|
||||
options: link.File.OpenOptions,
|
||||
) !*C {
|
||||
return createEmpty(arena, comp, emit, options);
|
||||
@ -113,7 +114,7 @@ pub fn open(
|
||||
pub fn createEmpty(
|
||||
arena: Allocator,
|
||||
comp: *Compilation,
|
||||
emit: Compilation.Emit,
|
||||
emit: Path,
|
||||
options: link.File.OpenOptions,
|
||||
) !*C {
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
@ -127,7 +128,7 @@ pub fn createEmpty(
|
||||
assert(!use_lld);
|
||||
assert(!use_llvm);
|
||||
|
||||
const file = try emit.directory.handle.createFile(emit.sub_path, .{
|
||||
const file = try emit.root_dir.handle.createFile(emit.sub_path, .{
|
||||
// Truncation is done on `flush`.
|
||||
.truncate = false,
|
||||
});
|
||||
|
||||
@ -219,7 +219,7 @@ pub const min_text_capacity = padToIdeal(minimum_text_block_size);
|
||||
pub fn createEmpty(
|
||||
arena: Allocator,
|
||||
comp: *Compilation,
|
||||
emit: Compilation.Emit,
|
||||
emit: Path,
|
||||
options: link.File.OpenOptions,
|
||||
) !*Coff {
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
@ -315,7 +315,7 @@ pub fn createEmpty(
|
||||
// If using LLD to link, this code should produce an object file so that it
|
||||
// can be passed to LLD.
|
||||
const sub_path = if (use_lld) zcu_object_sub_path.? else emit.sub_path;
|
||||
self.base.file = try emit.directory.handle.createFile(sub_path, .{
|
||||
self.base.file = try emit.root_dir.handle.createFile(sub_path, .{
|
||||
.truncate = true,
|
||||
.read = true,
|
||||
.mode = link.File.determineMode(use_lld, output_mode, link_mode),
|
||||
@ -416,7 +416,7 @@ pub fn createEmpty(
|
||||
pub fn open(
|
||||
arena: Allocator,
|
||||
comp: *Compilation,
|
||||
emit: Compilation.Emit,
|
||||
emit: Path,
|
||||
options: link.File.OpenOptions,
|
||||
) !*Coff {
|
||||
// TODO: restore saved linker state, don't truncate the file, and
|
||||
@ -2714,6 +2714,7 @@ const math = std.math;
|
||||
const mem = std.mem;
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
const Path = std.Build.Cache.Path;
|
||||
|
||||
const codegen = @import("../codegen.zig");
|
||||
const link = @import("../link.zig");
|
||||
|
||||
@ -27,7 +27,7 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no
|
||||
const comp = self.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
|
||||
const directory = self.base.emit.directory; // Just an alias to make it shorter to type.
|
||||
const directory = self.base.emit.root_dir; // Just an alias to make it shorter to type.
|
||||
const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path});
|
||||
|
||||
// If there is no Zig code to compile, then we should skip flushing the output file because it
|
||||
@ -248,7 +248,7 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no
|
||||
try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path}));
|
||||
|
||||
if (comp.implib_emit) |emit| {
|
||||
const implib_out_path = try emit.directory.join(arena, &[_][]const u8{emit.sub_path});
|
||||
const implib_out_path = try emit.root_dir.join(arena, &[_][]const u8{emit.sub_path});
|
||||
try argv.append(try allocPrint(arena, "-IMPLIB:{s}", .{implib_out_path}));
|
||||
}
|
||||
|
||||
|
||||
@ -204,7 +204,7 @@ pub const SortSection = enum { name, alignment };
|
||||
pub fn createEmpty(
|
||||
arena: Allocator,
|
||||
comp: *Compilation,
|
||||
emit: Compilation.Emit,
|
||||
emit: Path,
|
||||
options: link.File.OpenOptions,
|
||||
) !*Elf {
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
@ -321,7 +321,7 @@ pub fn createEmpty(
|
||||
// If using LLD to link, this code should produce an object file so that it
|
||||
// can be passed to LLD.
|
||||
const sub_path = if (use_lld) zcu_object_sub_path.? else emit.sub_path;
|
||||
self.base.file = try emit.directory.handle.createFile(sub_path, .{
|
||||
self.base.file = try emit.root_dir.handle.createFile(sub_path, .{
|
||||
.truncate = true,
|
||||
.read = true,
|
||||
.mode = link.File.determineMode(use_lld, output_mode, link_mode),
|
||||
@ -401,7 +401,7 @@ pub fn createEmpty(
|
||||
pub fn open(
|
||||
arena: Allocator,
|
||||
comp: *Compilation,
|
||||
emit: Compilation.Emit,
|
||||
emit: Path,
|
||||
options: link.File.OpenOptions,
|
||||
) !*Elf {
|
||||
// TODO: restore saved linker state, don't truncate the file, and
|
||||
@ -999,7 +999,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
|
||||
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
const link_mode = comp.config.link_mode;
|
||||
const directory = self.base.emit.directory; // Just an alias to make it shorter to type.
|
||||
const directory = self.base.emit.root_dir; // Just an alias to make it shorter to type.
|
||||
const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path});
|
||||
const module_obj_path: ?[]const u8 = if (self.base.zcu_object_sub_path) |path| blk: {
|
||||
if (fs.path.dirname(full_out_path)) |dirname| {
|
||||
@ -1356,7 +1356,7 @@ fn dumpArgv(self: *Elf, comp: *Compilation) !void {
|
||||
|
||||
const target = self.base.comp.root_mod.resolved_target.result;
|
||||
const link_mode = self.base.comp.config.link_mode;
|
||||
const directory = self.base.emit.directory; // Just an alias to make it shorter to type.
|
||||
const directory = self.base.emit.root_dir; // Just an alias to make it shorter to type.
|
||||
const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path});
|
||||
const module_obj_path: ?[]const u8 = if (self.base.zcu_object_sub_path) |path| blk: {
|
||||
if (fs.path.dirname(full_out_path)) |dirname| {
|
||||
@ -2054,7 +2054,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s
|
||||
const comp = self.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
|
||||
const directory = self.base.emit.directory; // Just an alias to make it shorter to type.
|
||||
const directory = self.base.emit.root_dir; // Just an alias to make it shorter to type.
|
||||
const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path});
|
||||
|
||||
// If there is no Zig code to compile, then we should skip flushing the output file because it
|
||||
@ -6016,6 +6016,7 @@ const Allocator = std.mem.Allocator;
|
||||
const Archive = @import("Elf/Archive.zig");
|
||||
pub const Atom = @import("Elf/Atom.zig");
|
||||
const Cache = std.Build.Cache;
|
||||
const Path = Cache.Path;
|
||||
const Compilation = @import("../Compilation.zig");
|
||||
const ComdatGroupSection = synthetic_sections.ComdatGroupSection;
|
||||
const CopyRelSection = synthetic_sections.CopyRelSection;
|
||||
|
||||
@ -156,7 +156,7 @@ pub fn hashAddFrameworks(man: *Cache.Manifest, hm: []const Framework) !void {
|
||||
pub fn createEmpty(
|
||||
arena: Allocator,
|
||||
comp: *Compilation,
|
||||
emit: Compilation.Emit,
|
||||
emit: Path,
|
||||
options: link.File.OpenOptions,
|
||||
) !*MachO {
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
@ -221,7 +221,7 @@ pub fn createEmpty(
|
||||
}
|
||||
errdefer self.base.destroy();
|
||||
|
||||
self.base.file = try emit.directory.handle.createFile(emit.sub_path, .{
|
||||
self.base.file = try emit.root_dir.handle.createFile(emit.sub_path, .{
|
||||
.truncate = true,
|
||||
.read = true,
|
||||
.mode = link.File.determineMode(false, output_mode, link_mode),
|
||||
@ -260,7 +260,7 @@ pub fn createEmpty(
|
||||
pub fn open(
|
||||
arena: Allocator,
|
||||
comp: *Compilation,
|
||||
emit: Compilation.Emit,
|
||||
emit: Path,
|
||||
options: link.File.OpenOptions,
|
||||
) !*MachO {
|
||||
// TODO: restore saved linker state, don't truncate the file, and
|
||||
@ -353,7 +353,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n
|
||||
const sub_prog_node = prog_node.start("MachO Flush", 0);
|
||||
defer sub_prog_node.end();
|
||||
|
||||
const directory = self.base.emit.directory;
|
||||
const directory = self.base.emit.root_dir;
|
||||
const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path});
|
||||
const module_obj_path: ?[]const u8 = if (self.base.zcu_object_sub_path) |path| blk: {
|
||||
if (fs.path.dirname(full_out_path)) |dirname| {
|
||||
@ -586,7 +586,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n
|
||||
if (codesig) |*csig| {
|
||||
try self.writeCodeSignature(csig); // code signing always comes last
|
||||
const emit = self.base.emit;
|
||||
try invalidateKernelCache(emit.directory.handle, emit.sub_path);
|
||||
try invalidateKernelCache(emit.root_dir.handle, emit.sub_path);
|
||||
}
|
||||
}
|
||||
|
||||
@ -597,7 +597,7 @@ fn dumpArgv(self: *MachO, comp: *Compilation) !void {
|
||||
defer arena_allocator.deinit();
|
||||
const arena = arena_allocator.allocator();
|
||||
|
||||
const directory = self.base.emit.directory;
|
||||
const directory = self.base.emit.root_dir;
|
||||
const full_out_path = try directory.join(arena, &[_][]const u8{self.base.emit.sub_path});
|
||||
const module_obj_path: ?[]const u8 = if (self.base.zcu_object_sub_path) |path| blk: {
|
||||
if (fs.path.dirname(full_out_path)) |dirname| {
|
||||
@ -3199,7 +3199,7 @@ fn copyRangeAllZeroOut(self: *MachO, old_offset: u64, new_offset: u64, size: u64
|
||||
}
|
||||
|
||||
const InitMetadataOptions = struct {
|
||||
emit: Compilation.Emit,
|
||||
emit: Path,
|
||||
zo: *ZigObject,
|
||||
symbol_count_hint: u64,
|
||||
program_code_size_hint: u64,
|
||||
@ -3271,7 +3271,7 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
|
||||
);
|
||||
defer gpa.free(d_sym_path);
|
||||
|
||||
var d_sym_bundle = try options.emit.directory.handle.makeOpenPath(d_sym_path, .{});
|
||||
var d_sym_bundle = try options.emit.root_dir.handle.makeOpenPath(d_sym_path, .{});
|
||||
defer d_sym_bundle.close();
|
||||
|
||||
const d_sym_file = try d_sym_bundle.createFile(options.emit.sub_path, .{
|
||||
@ -4603,6 +4603,7 @@ pub const Atom = @import("MachO/Atom.zig");
|
||||
const AtomicBool = std.atomic.Value(bool);
|
||||
const Bind = bind.Bind;
|
||||
const Cache = std.Build.Cache;
|
||||
const Path = Cache.Path;
|
||||
const CodeSignature = @import("MachO/CodeSignature.zig");
|
||||
const Compilation = @import("../Compilation.zig");
|
||||
const DataInCode = synthetic.DataInCode;
|
||||
|
||||
@ -53,7 +53,7 @@ pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) !u32
|
||||
if (macho_file.base.isDynLib()) {
|
||||
const emit = macho_file.base.emit;
|
||||
const install_name = macho_file.install_name orelse
|
||||
try emit.directory.join(gpa, &.{emit.sub_path});
|
||||
try emit.root_dir.join(gpa, &.{emit.sub_path});
|
||||
defer if (macho_file.install_name == null) gpa.free(install_name);
|
||||
sizeofcmds += calcInstallNameLen(
|
||||
@sizeOf(macho.dylib_command),
|
||||
@ -237,7 +237,7 @@ pub fn writeDylibIdLC(macho_file: *MachO, writer: anytype) !void {
|
||||
assert(comp.config.output_mode == .Lib and comp.config.link_mode == .dynamic);
|
||||
const emit = macho_file.base.emit;
|
||||
const install_name = macho_file.install_name orelse
|
||||
try emit.directory.join(gpa, &.{emit.sub_path});
|
||||
try emit.root_dir.join(gpa, &.{emit.sub_path});
|
||||
defer if (macho_file.install_name == null) gpa.free(install_name);
|
||||
const curr = comp.version orelse std.SemanticVersion{
|
||||
.major = 1,
|
||||
|
||||
@ -11,6 +11,7 @@ const builtin = @import("builtin");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const assert = std.debug.assert;
|
||||
const log = std.log.scoped(.link);
|
||||
const Path = std.Build.Cache.Path;
|
||||
|
||||
const Zcu = @import("../Zcu.zig");
|
||||
const InternPool = @import("../InternPool.zig");
|
||||
@ -28,7 +29,7 @@ llvm_object: LlvmObject.Ptr,
|
||||
pub fn createEmpty(
|
||||
arena: Allocator,
|
||||
comp: *Compilation,
|
||||
emit: Compilation.Emit,
|
||||
emit: Path,
|
||||
options: link.File.OpenOptions,
|
||||
) !*NvPtx {
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
@ -70,7 +71,7 @@ pub fn createEmpty(
|
||||
pub fn open(
|
||||
arena: Allocator,
|
||||
comp: *Compilation,
|
||||
emit: Compilation.Emit,
|
||||
emit: Path,
|
||||
options: link.File.OpenOptions,
|
||||
) !*NvPtx {
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
|
||||
@ -23,6 +23,7 @@ const mem = std.mem;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const log = std.log.scoped(.link);
|
||||
const assert = std.debug.assert;
|
||||
const Path = std.Build.Cache.Path;
|
||||
|
||||
base: link.File,
|
||||
sixtyfour_bit: bool,
|
||||
@ -275,7 +276,7 @@ pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases {
|
||||
pub fn createEmpty(
|
||||
arena: Allocator,
|
||||
comp: *Compilation,
|
||||
emit: Compilation.Emit,
|
||||
emit: Path,
|
||||
options: link.File.OpenOptions,
|
||||
) !*Plan9 {
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
@ -1199,7 +1200,7 @@ pub fn deinit(self: *Plan9) void {
|
||||
pub fn open(
|
||||
arena: Allocator,
|
||||
comp: *Compilation,
|
||||
emit: Compilation.Emit,
|
||||
emit: Path,
|
||||
options: link.File.OpenOptions,
|
||||
) !*Plan9 {
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
@ -1213,7 +1214,7 @@ pub fn open(
|
||||
const self = try createEmpty(arena, comp, emit, options);
|
||||
errdefer self.base.destroy();
|
||||
|
||||
const file = try emit.directory.handle.createFile(emit.sub_path, .{
|
||||
const file = try emit.root_dir.handle.createFile(emit.sub_path, .{
|
||||
.read = true,
|
||||
.mode = link.File.determineMode(
|
||||
use_lld,
|
||||
|
||||
@ -26,6 +26,7 @@ const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const assert = std.debug.assert;
|
||||
const log = std.log.scoped(.link);
|
||||
const Path = std.Build.Cache.Path;
|
||||
|
||||
const Zcu = @import("../Zcu.zig");
|
||||
const InternPool = @import("../InternPool.zig");
|
||||
@ -54,7 +55,7 @@ object: codegen.Object,
|
||||
pub fn createEmpty(
|
||||
arena: Allocator,
|
||||
comp: *Compilation,
|
||||
emit: Compilation.Emit,
|
||||
emit: Path,
|
||||
options: link.File.OpenOptions,
|
||||
) !*SpirV {
|
||||
const gpa = comp.gpa;
|
||||
@ -95,7 +96,7 @@ pub fn createEmpty(
|
||||
pub fn open(
|
||||
arena: Allocator,
|
||||
comp: *Compilation,
|
||||
emit: Compilation.Emit,
|
||||
emit: Path,
|
||||
options: link.File.OpenOptions,
|
||||
) !*SpirV {
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
@ -110,7 +111,7 @@ pub fn open(
|
||||
errdefer spirv.base.destroy();
|
||||
|
||||
// TODO: read the file and keep valid parts instead of truncating
|
||||
const file = try emit.directory.handle.createFile(emit.sub_path, .{
|
||||
const file = try emit.root_dir.handle.createFile(emit.sub_path, .{
|
||||
.truncate = true,
|
||||
.read = true,
|
||||
});
|
||||
|
||||
@ -22,6 +22,7 @@ const Air = @import("../Air.zig");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const Archive = @import("Wasm/Archive.zig");
|
||||
const Cache = std.Build.Cache;
|
||||
const Path = Cache.Path;
|
||||
const CodeGen = @import("../arch/wasm/CodeGen.zig");
|
||||
const Compilation = @import("../Compilation.zig");
|
||||
const Dwarf = @import("Dwarf.zig");
|
||||
@ -346,7 +347,7 @@ pub const StringTable = struct {
|
||||
pub fn open(
|
||||
arena: Allocator,
|
||||
comp: *Compilation,
|
||||
emit: Compilation.Emit,
|
||||
emit: Path,
|
||||
options: link.File.OpenOptions,
|
||||
) !*Wasm {
|
||||
// TODO: restore saved linker state, don't truncate the file, and
|
||||
@ -357,7 +358,7 @@ pub fn open(
|
||||
pub fn createEmpty(
|
||||
arena: Allocator,
|
||||
comp: *Compilation,
|
||||
emit: Compilation.Emit,
|
||||
emit: Path,
|
||||
options: link.File.OpenOptions,
|
||||
) !*Wasm {
|
||||
const gpa = comp.gpa;
|
||||
@ -430,7 +431,7 @@ pub fn createEmpty(
|
||||
// can be passed to LLD.
|
||||
const sub_path = if (use_lld) zcu_object_sub_path.? else emit.sub_path;
|
||||
|
||||
wasm.base.file = try emit.directory.handle.createFile(sub_path, .{
|
||||
wasm.base.file = try emit.root_dir.handle.createFile(sub_path, .{
|
||||
.truncate = true,
|
||||
.read = true,
|
||||
.mode = if (fs.has_executable_bit)
|
||||
@ -2496,7 +2497,7 @@ pub fn flushModule(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_no
|
||||
const sub_prog_node = prog_node.start("Wasm Flush", 0);
|
||||
defer sub_prog_node.end();
|
||||
|
||||
const directory = wasm.base.emit.directory; // Just an alias to make it shorter to type.
|
||||
const directory = wasm.base.emit.root_dir; // Just an alias to make it shorter to type.
|
||||
const full_out_path = try directory.join(arena, &[_][]const u8{wasm.base.emit.sub_path});
|
||||
const module_obj_path: ?[]const u8 = if (wasm.base.zcu_object_sub_path) |path| blk: {
|
||||
if (fs.path.dirname(full_out_path)) |dirname| {
|
||||
@ -3346,7 +3347,7 @@ fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:
|
||||
|
||||
const gpa = comp.gpa;
|
||||
|
||||
const directory = wasm.base.emit.directory; // Just an alias to make it shorter to type.
|
||||
const directory = wasm.base.emit.root_dir; // Just an alias to make it shorter to type.
|
||||
const full_out_path = try directory.join(arena, &[_][]const u8{wasm.base.emit.sub_path});
|
||||
|
||||
// If there is no Zig code to compile, then we should skip flushing the output file because it
|
||||
|
||||
86
src/main.zig
86
src/main.zig
@ -3519,7 +3519,7 @@ fn buildOutputType(
|
||||
if (test_exec_args.items.len == 0 and target.ofmt == .c) default_exec_args: {
|
||||
// Default to using `zig run` to execute the produced .c code from `zig test`.
|
||||
const c_code_loc = emit_bin_loc orelse break :default_exec_args;
|
||||
const c_code_directory = c_code_loc.directory orelse comp.bin_file.?.emit.directory;
|
||||
const c_code_directory = c_code_loc.directory orelse comp.bin_file.?.emit.root_dir;
|
||||
const c_code_path = try fs.path.join(arena, &[_][]const u8{
|
||||
c_code_directory.path orelse ".", c_code_loc.basename,
|
||||
});
|
||||
@ -4142,7 +4142,7 @@ fn serve(
|
||||
if (output.errors.errorMessageCount() != 0) {
|
||||
try server.serveErrorBundle(output.errors);
|
||||
} else {
|
||||
try server.serveEmitBinPath(output.out_zig_path, .{
|
||||
try server.serveEmitDigest(&output.digest, .{
|
||||
.flags = .{ .cache_hit = output.cache_hit },
|
||||
});
|
||||
}
|
||||
@ -4229,62 +4229,10 @@ fn serveUpdateResults(s: *Server, comp: *Compilation) !void {
|
||||
return;
|
||||
}
|
||||
|
||||
// This logic is counter-intuitive because the protocol accounts for each
|
||||
// emitted artifact possibly being in a different location, which correctly
|
||||
// matches the behavior of the compiler, however, the build system
|
||||
// currently always passes flags that makes all build artifacts output to
|
||||
// the same local cache directory, and relies on them all being in the same
|
||||
// directory.
|
||||
//
|
||||
// So, until the build system and protocol are changed to reflect this,
|
||||
// this logic must ensure that emit_bin_path is emitted for at least one
|
||||
// thing, if there are any artifacts.
|
||||
|
||||
switch (comp.cache_use) {
|
||||
.incremental => if (comp.bin_file) |lf| {
|
||||
const full_path = try lf.emit.directory.join(gpa, &.{lf.emit.sub_path});
|
||||
defer gpa.free(full_path);
|
||||
try s.serveEmitBinPath(full_path, .{
|
||||
.flags = .{ .cache_hit = comp.last_update_was_cache_hit },
|
||||
});
|
||||
return;
|
||||
},
|
||||
.whole => |whole| if (whole.bin_sub_path) |sub_path| {
|
||||
const full_path = try comp.local_cache_directory.join(gpa, &.{sub_path});
|
||||
defer gpa.free(full_path);
|
||||
try s.serveEmitBinPath(full_path, .{
|
||||
.flags = .{ .cache_hit = comp.last_update_was_cache_hit },
|
||||
});
|
||||
return;
|
||||
},
|
||||
}
|
||||
|
||||
for ([_]?Compilation.Emit{
|
||||
comp.docs_emit,
|
||||
comp.implib_emit,
|
||||
}) |opt_emit| {
|
||||
const emit = opt_emit orelse continue;
|
||||
const full_path = try emit.directory.join(gpa, &.{emit.sub_path});
|
||||
defer gpa.free(full_path);
|
||||
try s.serveEmitBinPath(full_path, .{
|
||||
if (comp.digest) |digest| {
|
||||
try s.serveEmitDigest(&digest, .{
|
||||
.flags = .{ .cache_hit = comp.last_update_was_cache_hit },
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
for ([_]?Compilation.EmitLoc{
|
||||
comp.emit_asm,
|
||||
comp.emit_llvm_ir,
|
||||
comp.emit_llvm_bc,
|
||||
}) |opt_emit_loc| {
|
||||
const emit_loc = opt_emit_loc orelse continue;
|
||||
const directory = emit_loc.directory orelse continue;
|
||||
const full_path = try directory.join(gpa, &.{emit_loc.basename});
|
||||
defer gpa.free(full_path);
|
||||
try s.serveEmitBinPath(full_path, .{
|
||||
.flags = .{ .cache_hit = comp.last_update_was_cache_hit },
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Serve empty error bundle to indicate the update is done.
|
||||
@ -4308,7 +4256,7 @@ fn runOrTest(
|
||||
// A naive `directory.join` here will indeed get the correct path to the binary,
|
||||
// however, in the case of cwd, we actually want `./foo` so that the path can be executed.
|
||||
const exe_path = try fs.path.join(arena, &[_][]const u8{
|
||||
lf.emit.directory.path orelse ".", lf.emit.sub_path,
|
||||
lf.emit.root_dir.path orelse ".", lf.emit.sub_path,
|
||||
});
|
||||
|
||||
var argv = std.ArrayList([]const u8).init(gpa);
|
||||
@ -4420,7 +4368,7 @@ fn runOrTestHotSwap(
|
||||
// tmp zig-cache and use it to spawn the child process. This way we are free to update
|
||||
// the binary with each requested hot update.
|
||||
.windows => blk: {
|
||||
try lf.emit.directory.handle.copyFile(lf.emit.sub_path, comp.local_cache_directory.handle, lf.emit.sub_path, .{});
|
||||
try lf.emit.root_dir.handle.copyFile(lf.emit.sub_path, comp.local_cache_directory.handle, lf.emit.sub_path, .{});
|
||||
break :blk try fs.path.join(gpa, &[_][]const u8{
|
||||
comp.local_cache_directory.path orelse ".", lf.emit.sub_path,
|
||||
});
|
||||
@ -4429,7 +4377,7 @@ fn runOrTestHotSwap(
|
||||
// A naive `directory.join` here will indeed get the correct path to the binary,
|
||||
// however, in the case of cwd, we actually want `./foo` so that the path can be executed.
|
||||
else => try fs.path.join(gpa, &[_][]const u8{
|
||||
lf.emit.directory.path orelse ".", lf.emit.sub_path,
|
||||
lf.emit.root_dir.path orelse ".", lf.emit.sub_path,
|
||||
}),
|
||||
};
|
||||
defer gpa.free(exe_path);
|
||||
@ -4539,9 +4487,11 @@ fn cmdTranslateC(
|
||||
};
|
||||
|
||||
if (fancy_output) |p| p.cache_hit = true;
|
||||
const digest = if (try man.hit()) digest: {
|
||||
const bin_digest, const hex_digest = if (try man.hit()) digest: {
|
||||
if (file_system_inputs) |buf| try man.populateFileSystemInputs(buf);
|
||||
break :digest man.final();
|
||||
const bin_digest = man.finalBin();
|
||||
const hex_digest = Cache.binToHex(bin_digest);
|
||||
break :digest .{ bin_digest, hex_digest };
|
||||
} else digest: {
|
||||
if (fancy_output) |p| p.cache_hit = false;
|
||||
var argv = std.ArrayList([]const u8).init(arena);
|
||||
@ -4639,8 +4589,10 @@ fn cmdTranslateC(
|
||||
};
|
||||
}
|
||||
|
||||
const digest = man.final();
|
||||
const o_sub_path = try fs.path.join(arena, &[_][]const u8{ "o", &digest });
|
||||
const bin_digest = man.finalBin();
|
||||
const hex_digest = Cache.binToHex(bin_digest);
|
||||
|
||||
const o_sub_path = try fs.path.join(arena, &[_][]const u8{ "o", &hex_digest });
|
||||
|
||||
var o_dir = try comp.local_cache_directory.handle.makeOpenPath(o_sub_path, .{});
|
||||
defer o_dir.close();
|
||||
@ -4656,16 +4608,14 @@ fn cmdTranslateC(
|
||||
|
||||
if (file_system_inputs) |buf| try man.populateFileSystemInputs(buf);
|
||||
|
||||
break :digest digest;
|
||||
break :digest .{ bin_digest, hex_digest };
|
||||
};
|
||||
|
||||
if (fancy_output) |p| {
|
||||
p.out_zig_path = try comp.local_cache_directory.join(comp.gpa, &[_][]const u8{
|
||||
"o", &digest, translated_zig_basename,
|
||||
});
|
||||
p.digest = bin_digest;
|
||||
p.errors = std.zig.ErrorBundle.empty;
|
||||
} else {
|
||||
const out_zig_path = try fs.path.join(arena, &[_][]const u8{ "o", &digest, translated_zig_basename });
|
||||
const out_zig_path = try fs.path.join(arena, &[_][]const u8{ "o", &hex_digest, translated_zig_basename });
|
||||
const zig_file = comp.local_cache_directory.handle.openFile(out_zig_path, .{}) catch |err| {
|
||||
const path = comp.local_cache_directory.path orelse ".";
|
||||
fatal("unable to open cached translated zig file '{s}{s}{s}': {s}", .{ path, fs.path.sep_str, out_zig_path, @errorName(err) });
|
||||
|
||||
@ -51,14 +51,15 @@
|
||||
.install_raw_hex = .{
|
||||
.path = "install_raw_hex",
|
||||
},
|
||||
// https://github.com/ziglang/zig/issues/17484
|
||||
//.emit_asm_and_bin = .{
|
||||
// .path = "emit_asm_and_bin",
|
||||
//},
|
||||
// https://github.com/ziglang/zig/issues/17484
|
||||
//.issue_12588 = .{
|
||||
// .path = "issue_12588",
|
||||
//},
|
||||
.emit_asm_and_bin = .{
|
||||
.path = "emit_asm_and_bin",
|
||||
},
|
||||
.emit_llvm_no_bin = .{
|
||||
.path = "emit_llvm_no_bin",
|
||||
},
|
||||
.emit_asm_no_bin = .{
|
||||
.path = "emit_asm_no_bin",
|
||||
},
|
||||
.child_process = .{
|
||||
.path = "child_process",
|
||||
},
|
||||
|
||||
19
test/standalone/emit_asm_no_bin/build.zig
Normal file
19
test/standalone/emit_asm_no_bin/build.zig
Normal file
@ -0,0 +1,19 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const test_step = b.step("test", "Test it");
|
||||
b.default_step = test_step;
|
||||
|
||||
const optimize: std.builtin.OptimizeMode = .Debug;
|
||||
|
||||
const obj = b.addObject(.{
|
||||
.name = "main",
|
||||
.root_source_file = b.path("main.zig"),
|
||||
.optimize = optimize,
|
||||
.target = b.graph.host,
|
||||
});
|
||||
_ = obj.getEmittedAsm();
|
||||
b.default_step.dependOn(&obj.step);
|
||||
|
||||
test_step.dependOn(&obj.step);
|
||||
}
|
||||
1
test/standalone/emit_asm_no_bin/main.zig
Normal file
1
test/standalone/emit_asm_no_bin/main.zig
Normal file
@ -0,0 +1 @@
|
||||
pub fn main() void {}
|
||||
@ -1,6 +1,7 @@
|
||||
const std = @import("std");
|
||||
const fatal = std.process.fatal;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const Cache = std.Build.Cache;
|
||||
|
||||
const usage = "usage: incr-check <zig binary path> <input file> [--zig-lib-dir lib] [--debug-zcu] [--emit none|bin|c] [--zig-cc-binary /path/to/zig]";
|
||||
|
||||
@ -233,30 +234,52 @@ const Eval = struct {
|
||||
fatal("error_bundle included unexpected stderr:\n{s}", .{stderr_data});
|
||||
}
|
||||
}
|
||||
if (result_error_bundle.errorMessageCount() == 0) {
|
||||
// Empty bundle indicates successful update in a `-fno-emit-bin` build.
|
||||
try eval.checkSuccessOutcome(update, null, prog_node);
|
||||
} else {
|
||||
if (result_error_bundle.errorMessageCount() != 0) {
|
||||
try eval.checkErrorOutcome(update, result_error_bundle);
|
||||
}
|
||||
// This message indicates the end of the update.
|
||||
stdout.discard(body.len);
|
||||
return;
|
||||
},
|
||||
.emit_bin_path => {
|
||||
const EbpHdr = std.zig.Server.Message.EmitBinPath;
|
||||
.emit_digest => {
|
||||
const EbpHdr = std.zig.Server.Message.EmitDigest;
|
||||
const ebp_hdr = @as(*align(1) const EbpHdr, @ptrCast(body));
|
||||
_ = ebp_hdr;
|
||||
const result_binary = try arena.dupe(u8, body[@sizeOf(EbpHdr)..]);
|
||||
if (stderr.readableLength() > 0) {
|
||||
const stderr_data = try stderr.toOwnedSlice();
|
||||
if (eval.allow_stderr) {
|
||||
std.log.info("emit_bin_path included stderr:\n{s}", .{stderr_data});
|
||||
std.log.info("emit_digest included stderr:\n{s}", .{stderr_data});
|
||||
} else {
|
||||
fatal("emit_bin_path included unexpected stderr:\n{s}", .{stderr_data});
|
||||
fatal("emit_digest included unexpected stderr:\n{s}", .{stderr_data});
|
||||
}
|
||||
}
|
||||
try eval.checkSuccessOutcome(update, result_binary, prog_node);
|
||||
|
||||
if (eval.emit == .none) {
|
||||
try eval.checkSuccessOutcome(update, null, prog_node);
|
||||
// This message indicates the end of the update.
|
||||
stdout.discard(body.len);
|
||||
return;
|
||||
}
|
||||
|
||||
const digest = body[@sizeOf(EbpHdr)..][0..Cache.bin_digest_len];
|
||||
const result_dir = ".local-cache" ++ std.fs.path.sep_str ++ "o" ++ std.fs.path.sep_str ++ Cache.binToHex(digest.*);
|
||||
|
||||
const name = std.fs.path.stem(std.fs.path.basename(eval.case.root_source_file));
|
||||
const bin_name = try std.zig.binNameAlloc(arena, .{
|
||||
.root_name = name,
|
||||
.target = try std.zig.system.resolveTargetQuery(try std.Build.parseTargetQuery(.{
|
||||
.arch_os_abi = eval.case.target_query,
|
||||
.object_format = switch (eval.emit) {
|
||||
.none => unreachable,
|
||||
.bin => null,
|
||||
.c => "c",
|
||||
},
|
||||
})),
|
||||
.output_mode = .Exe,
|
||||
});
|
||||
const bin_path = try std.fs.path.join(arena, &.{ result_dir, bin_name });
|
||||
|
||||
try eval.checkSuccessOutcome(update, bin_path, prog_node);
|
||||
// This message indicates the end of the update.
|
||||
stdout.discard(body.len);
|
||||
return;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user