Skip to content

Commit 16d78bc

Browse files
committed
Build: add install commands to --verbose output
1 parent df4068c commit 16d78bc

File tree

11 files changed

+160
-97
lines changed

11 files changed

+160
-97
lines changed

build.zig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,10 @@ pub fn build(b: *std.Build) !void {
203203
exe.pie = pie;
204204
exe.entitlements = entitlements;
205205

206+
const use_llvm = b.option(bool, "use-llvm", "Use the llvm backend");
207+
exe.use_llvm = use_llvm;
208+
exe.use_lld = use_llvm;
209+
206210
if (no_bin) {
207211
b.getInstallStep().dependOn(&exe.step);
208212
} else {
@@ -214,10 +218,6 @@ pub fn build(b: *std.Build) !void {
214218

215219
test_step.dependOn(&exe.step);
216220

217-
const use_llvm = b.option(bool, "use-llvm", "Use the llvm backend");
218-
exe.use_llvm = use_llvm;
219-
exe.use_lld = use_llvm;
220-
221221
const exe_options = b.addOptions();
222222
exe.root_module.addOptions("build_options", exe_options);
223223

lib/std/Build.zig

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2456,12 +2456,23 @@ pub const GeneratedFile = struct {
24562456
/// This value must be set in the `fn make()` of the `step` and must not be `null` afterwards.
24572457
path: ?[]const u8 = null,
24582458

2459+
/// Deprecated, see `getPath2`.
24592460
pub fn getPath(gen: GeneratedFile) []const u8 {
24602461
return gen.step.owner.pathFromCwd(gen.path orelse std.debug.panic(
24612462
"getPath() was called on a GeneratedFile that wasn't built yet. Is there a missing Step dependency on step '{s}'?",
24622463
.{gen.step.name},
24632464
));
24642465
}
2466+
2467+
pub fn getPath2(gen: GeneratedFile, src_builder: *Build, asking_step: ?*Step) []const u8 {
2468+
return gen.path orelse {
2469+
std.debug.lockStdErr();
2470+
const stderr = std.io.getStdErr();
2471+
dumpBadGetPathHelp(gen.step, stderr, src_builder, asking_step) catch {};
2472+
std.debug.unlockStdErr();
2473+
@panic("misconfigured build script");
2474+
};
2475+
}
24652476
};
24662477

24672478
// dirnameAllowEmpty is a variant of fs.path.dirname
@@ -2712,6 +2723,18 @@ pub const LazyPath = union(enum) {
27122723
}
27132724
}
27142725

2726+
pub fn basename(lazy_path: LazyPath, src_builder: *Build, asking_step: ?*Step) []const u8 {
2727+
return fs.path.basename(switch (lazy_path) {
2728+
.src_path => |sp| sp.sub_path,
2729+
.cwd_relative => |sub_path| sub_path,
2730+
.generated => |gen| if (gen.sub_path.len > 0)
2731+
gen.sub_path
2732+
else
2733+
gen.file.getPath2(src_builder, asking_step),
2734+
.dependency => |dep| dep.sub_path,
2735+
});
2736+
}
2737+
27152738
/// Copies the internal strings.
27162739
///
27172740
/// The `b` parameter is only used for its allocator. All *Build instances

lib/std/Build/Step.zig

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,29 @@ pub fn evalZigProcess(
478478
return result;
479479
}
480480

481+
/// Wrapper around `std.fs.Dir.updateFile` that handles verbose and error output.
482+
pub fn installFile(s: *Step, src_lazy_path: Build.LazyPath, dest_path: []const u8) !std.fs.Dir.PrevStatus {
483+
const b = s.owner;
484+
const src_path = src_lazy_path.getPath3(b, s);
485+
try handleVerbose(b, null, &.{ "install", "-C", b.fmt("{}", .{src_path}), dest_path });
486+
return src_path.root_dir.handle.updateFile(src_path.sub_path, std.fs.cwd(), dest_path, .{}) catch |err| {
487+
return s.fail("unable to update file from '{}' to '{s}': {s}", .{
488+
src_path, dest_path, @errorName(err),
489+
});
490+
};
491+
}
492+
493+
/// Wrapper around `std.fs.Dir.makePathStatus` that handles verbose and error output.
494+
pub fn installDir(s: *Step, dest_path: []const u8) !std.fs.Dir.MakePathStatus {
495+
const b = s.owner;
496+
try handleVerbose(b, null, &.{ "install", "-d", dest_path });
497+
return std.fs.cwd().makePathStatus(dest_path) catch |err| {
498+
return s.fail("unable to create dir '{s}': {s}", .{
499+
dest_path, @errorName(err),
500+
});
501+
};
502+
}
503+
481504
fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool) !?Path {
482505
const b = s.owner;
483506
const arena = b.allocator;
@@ -714,8 +737,44 @@ pub fn allocPrintCmd2(
714737
opt_env: ?*const std.process.EnvMap,
715738
argv: []const []const u8,
716739
) Allocator.Error![]u8 {
740+
const shell = struct {
741+
fn escape(writer: anytype, string: []const u8, is_argv0: bool) !void {
742+
for (string) |c| {
743+
if (switch (c) {
744+
else => true,
745+
'%', '+'...':', '@'...'Z', '_', 'a'...'z' => false,
746+
'=' => is_argv0,
747+
}) break;
748+
} else return writer.writeAll(string);
749+
750+
try writer.writeByte('"');
751+
for (string) |c| {
752+
if (switch (c) {
753+
std.ascii.control_code.nul => break,
754+
'!', '"', '$', '\\', '`' => true,
755+
else => !std.ascii.isPrint(c),
756+
}) try writer.writeByte('\\');
757+
switch (c) {
758+
std.ascii.control_code.nul => unreachable,
759+
std.ascii.control_code.bel => try writer.writeByte('a'),
760+
std.ascii.control_code.bs => try writer.writeByte('b'),
761+
std.ascii.control_code.ht => try writer.writeByte('t'),
762+
std.ascii.control_code.lf => try writer.writeByte('n'),
763+
std.ascii.control_code.vt => try writer.writeByte('v'),
764+
std.ascii.control_code.ff => try writer.writeByte('f'),
765+
std.ascii.control_code.cr => try writer.writeByte('r'),
766+
std.ascii.control_code.esc => try writer.writeByte('E'),
767+
' '...'~' => try writer.writeByte(c),
768+
else => try writer.print("{o:0>3}", .{c}),
769+
}
770+
}
771+
try writer.writeByte('"');
772+
}
773+
};
774+
717775
var buf: std.ArrayListUnmanaged(u8) = .empty;
718-
if (opt_cwd) |cwd| try buf.writer(arena).print("cd {s} && ", .{cwd});
776+
const writer = buf.writer(arena);
777+
if (opt_cwd) |cwd| try writer.print("cd {s} && ", .{cwd});
719778
if (opt_env) |env| {
720779
const process_env_map = std.process.getEnvMap(arena) catch std.process.EnvMap.init(arena);
721780
var it = env.iterator();
@@ -725,11 +784,15 @@ pub fn allocPrintCmd2(
725784
if (process_env_map.get(key)) |process_value| {
726785
if (std.mem.eql(u8, value, process_value)) continue;
727786
}
728-
try buf.writer(arena).print("{s}={s} ", .{ key, value });
787+
try writer.print("{s}=", .{key});
788+
try shell.escape(writer, value, false);
789+
try writer.writeByte(' ');
729790
}
730791
}
731-
for (argv) |arg| {
732-
try buf.writer(arena).print("{s} ", .{arg});
792+
try shell.escape(writer, argv[0], true);
793+
for (argv[1..]) |arg| {
794+
try writer.writeByte(' ');
795+
try shell.escape(writer, arg, false);
733796
}
734797
return buf.toOwnedSlice(arena);
735798
}

lib/std/Build/Step/Compile.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,7 @@ pub fn producesPdbFile(compile: *Compile) bool {
668668
else => return false,
669669
}
670670
if (target.ofmt == .c) return false;
671+
if (compile.use_llvm == false) return false;
671672
if (compile.root_module.strip == true or
672673
(compile.root_module.strip == null and compile.root_module.optimize == .ReleaseSmall))
673674
{

lib/std/Build/Step/InstallArtifact.zig

Lines changed: 14 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -119,18 +119,12 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
119119
_ = options;
120120
const install_artifact: *InstallArtifact = @fieldParentPtr("step", step);
121121
const b = step.owner;
122-
const cwd = fs.cwd();
123122

124123
var all_cached = true;
125124

126125
if (install_artifact.dest_dir) |dest_dir| {
127126
const full_dest_path = b.getInstallPath(dest_dir, install_artifact.dest_sub_path);
128-
const src_path = install_artifact.emitted_bin.?.getPath3(b, step);
129-
const p = fs.Dir.updateFile(src_path.root_dir.handle, src_path.sub_path, cwd, full_dest_path, .{}) catch |err| {
130-
return step.fail("unable to update file from '{s}' to '{s}': {s}", .{
131-
src_path.sub_path, full_dest_path, @errorName(err),
132-
});
133-
};
127+
const p = try step.installFile(install_artifact.emitted_bin.?, full_dest_path);
134128
all_cached = all_cached and p == .fresh;
135129

136130
if (install_artifact.dylib_symlinks) |dls| {
@@ -141,48 +135,28 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
141135
}
142136

143137
if (install_artifact.implib_dir) |implib_dir| {
144-
const src_path = install_artifact.emitted_implib.?.getPath3(b, step);
145-
const full_implib_path = b.getInstallPath(implib_dir, fs.path.basename(src_path.sub_path));
146-
const p = fs.Dir.updateFile(src_path.root_dir.handle, src_path.sub_path, cwd, full_implib_path, .{}) catch |err| {
147-
return step.fail("unable to update file from '{s}' to '{s}': {s}", .{
148-
src_path.sub_path, full_implib_path, @errorName(err),
149-
});
150-
};
138+
const full_implib_path = b.getInstallPath(implib_dir, install_artifact.emitted_implib.?.basename(b, step));
139+
const p = try step.installFile(install_artifact.emitted_implib.?, full_implib_path);
151140
all_cached = all_cached and p == .fresh;
152141
}
153142

154143
if (install_artifact.pdb_dir) |pdb_dir| {
155-
const src_path = install_artifact.emitted_pdb.?.getPath3(b, step);
156-
const full_pdb_path = b.getInstallPath(pdb_dir, fs.path.basename(src_path.sub_path));
157-
const p = fs.Dir.updateFile(src_path.root_dir.handle, src_path.sub_path, cwd, full_pdb_path, .{}) catch |err| {
158-
return step.fail("unable to update file from '{s}' to '{s}': {s}", .{
159-
src_path.sub_path, full_pdb_path, @errorName(err),
160-
});
161-
};
144+
const full_pdb_path = b.getInstallPath(pdb_dir, install_artifact.emitted_pdb.?.basename(b, step));
145+
const p = try step.installFile(install_artifact.emitted_pdb.?, full_pdb_path);
162146
all_cached = all_cached and p == .fresh;
163147
}
164148

165149
if (install_artifact.h_dir) |h_dir| {
166150
if (install_artifact.emitted_h) |emitted_h| {
167-
const src_path = emitted_h.getPath3(b, step);
168-
const full_h_path = b.getInstallPath(h_dir, fs.path.basename(src_path.sub_path));
169-
const p = fs.Dir.updateFile(src_path.root_dir.handle, src_path.sub_path, cwd, full_h_path, .{}) catch |err| {
170-
return step.fail("unable to update file from '{s}' to '{s}': {s}", .{
171-
src_path.sub_path, full_h_path, @errorName(err),
172-
});
173-
};
151+
const full_h_path = b.getInstallPath(h_dir, emitted_h.basename(b, step));
152+
const p = try step.installFile(emitted_h, full_h_path);
174153
all_cached = all_cached and p == .fresh;
175154
}
176155

177156
for (install_artifact.artifact.installed_headers.items) |installation| switch (installation) {
178157
.file => |file| {
179-
const src_path = file.source.getPath3(b, step);
180158
const full_h_path = b.getInstallPath(h_dir, file.dest_rel_path);
181-
const p = fs.Dir.updateFile(src_path.root_dir.handle, src_path.sub_path, cwd, full_h_path, .{}) catch |err| {
182-
return step.fail("unable to update file from '{s}' to '{s}': {s}", .{
183-
src_path.sub_path, full_h_path, @errorName(err),
184-
});
185-
};
159+
const p = try step.installFile(file.source, full_h_path);
186160
all_cached = all_cached and p == .fresh;
187161
},
188162
.directory => |dir| {
@@ -209,16 +183,15 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
209183
}
210184
}
211185

212-
const src_entry_path = src_dir_path.join(b.allocator, entry.path) catch @panic("OOM");
213186
const full_dest_path = b.pathJoin(&.{ full_h_prefix, entry.path });
214187
switch (entry.kind) {
215-
.directory => try cwd.makePath(full_dest_path),
188+
.directory => {
189+
try Step.handleVerbose(b, null, &.{ "install", "-d", full_dest_path });
190+
const p = try step.installDir(full_dest_path);
191+
all_cached = all_cached and p == .existed;
192+
},
216193
.file => {
217-
const p = fs.Dir.updateFile(src_entry_path.root_dir.handle, src_entry_path.sub_path, cwd, full_dest_path, .{}) catch |err| {
218-
return step.fail("unable to update file from '{s}' to '{s}': {s}", .{
219-
src_entry_path.sub_path, full_dest_path, @errorName(err),
220-
});
221-
};
194+
const p = try step.installFile(try dir.source.join(b.allocator, entry.path), full_dest_path);
222195
all_cached = all_cached and p == .fresh;
223196
},
224197
else => continue,

lib/std/Build/Step/InstallDir.zig

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -74,31 +74,23 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
7474
var all_cached = true;
7575
next_entry: while (try it.next()) |entry| {
7676
for (install_dir.options.exclude_extensions) |ext| {
77-
if (mem.endsWith(u8, entry.path, ext)) {
78-
continue :next_entry;
79-
}
77+
if (mem.endsWith(u8, entry.path, ext)) continue :next_entry;
8078
}
8179
if (install_dir.options.include_extensions) |incs| {
82-
var found = false;
8380
for (incs) |inc| {
84-
if (mem.endsWith(u8, entry.path, inc)) {
85-
found = true;
86-
break;
87-
}
81+
if (mem.endsWith(u8, entry.path, inc)) break;
82+
} else {
83+
continue :next_entry;
8884
}
89-
if (!found) continue :next_entry;
9085
}
9186

92-
// relative to src build root
93-
const src_sub_path = try src_dir_path.join(arena, entry.path);
87+
const src_path = try install_dir.options.source_dir.join(b.allocator, entry.path);
9488
const dest_path = b.pathJoin(&.{ dest_prefix, entry.path });
95-
const cwd = fs.cwd();
96-
9789
switch (entry.kind) {
9890
.directory => {
99-
if (need_derived_inputs) try step.addDirectoryWatchInputFromPath(src_sub_path);
100-
try cwd.makePath(dest_path);
101-
// TODO: set result_cached=false if the directory did not already exist.
91+
if (need_derived_inputs) _ = try step.addDirectoryWatchInput(src_path);
92+
const p = try step.installDir(dest_path);
93+
all_cached = all_cached and p == .existed;
10294
},
10395
.file => {
10496
for (install_dir.options.blank_extensions) |ext| {
@@ -108,18 +100,8 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
108100
}
109101
}
110102

111-
const prev_status = fs.Dir.updateFile(
112-
src_sub_path.root_dir.handle,
113-
src_sub_path.sub_path,
114-
cwd,
115-
dest_path,
116-
.{},
117-
) catch |err| {
118-
return step.fail("unable to update file from '{}' to '{s}': {s}", .{
119-
src_sub_path, dest_path, @errorName(err),
120-
});
121-
};
122-
all_cached = all_cached and prev_status == .fresh;
103+
const p = try step.installFile(src_path, dest_path);
104+
all_cached = all_cached and p == .fresh;
123105
},
124106
else => continue,
125107
}

lib/std/Build/Step/InstallFile.zig

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
4141
const install_file: *InstallFile = @fieldParentPtr("step", step);
4242
try step.singleUnchangingWatchInput(install_file.source);
4343

44-
const full_src_path = install_file.source.getPath2(b, step);
4544
const full_dest_path = b.getInstallPath(install_file.dir, install_file.dest_rel_path);
46-
const cwd = std.fs.cwd();
47-
const prev = std.fs.Dir.updateFile(cwd, full_src_path, cwd, full_dest_path, .{}) catch |err| {
48-
return step.fail("unable to update file from '{s}' to '{s}': {s}", .{
49-
full_src_path, full_dest_path, @errorName(err),
50-
});
51-
};
52-
step.result_cached = prev == .fresh;
45+
const p = try step.installFile(install_file.source, full_dest_path);
46+
step.result_cached = p == .fresh;
5347
}

lib/std/Build/Step/ObjCopy.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
209209
}
210210
if (objcopy.add_section) |section| {
211211
try argv.append("--add-section");
212-
try argv.appendSlice(&.{b.fmt("{s}={s}", .{ section.section_name, section.file_path.getPath(b) })});
212+
try argv.appendSlice(&.{b.fmt("{s}={s}", .{ section.section_name, section.file_path.getPath2(b, step) })});
213213
}
214214
if (objcopy.set_section_alignment) |set_align| {
215215
try argv.append("--set-section-alignment");

lib/std/Build/Step/Run.zig

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -456,11 +456,28 @@ pub fn addPathDir(run: *Run, search_path: []const u8) void {
456456
const b = run.step.owner;
457457
const env_map = getEnvMapInternal(run);
458458

459-
const key = "PATH";
459+
const use_wine = b.enable_wine and b.graph.host.result.os.tag != .windows and use_wine: switch (run.argv.items[0]) {
460+
.artifact => |p| p.artifact.rootModuleTarget().os.tag == .windows,
461+
.lazy_path => |p| {
462+
switch (p.lazy_path) {
463+
.generated => |g| if (g.file.step.cast(Step.Compile)) |cs| break :use_wine cs.rootModuleTarget().os.tag == .windows,
464+
else => {},
465+
}
466+
break :use_wine std.mem.endsWith(u8, p.lazy_path.basename(b, &run.step), ".exe");
467+
},
468+
.decorated_directory => false,
469+
.bytes => |bytes| std.mem.endsWith(u8, bytes, ".exe"),
470+
.output_file, .output_directory => false,
471+
};
472+
const key = if (use_wine) "WINEPATH" else "PATH";
460473
const prev_path = env_map.get(key);
461474

462475
if (prev_path) |pp| {
463-
const new_path = b.fmt("{s}" ++ [1]u8{fs.path.delimiter} ++ "{s}", .{ pp, search_path });
476+
const new_path = b.fmt("{s}{c}{s}", .{
477+
pp,
478+
if (use_wine) fs.path.delimiter_windows else fs.path.delimiter,
479+
search_path,
480+
});
464481
env_map.put(key, new_path) catch @panic("OOM");
465482
} else {
466483
env_map.put(key, b.dupePath(search_path)) catch @panic("OOM");
@@ -866,7 +883,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
866883
try runCommand(run, argv_list.items, has_side_effects, tmp_dir_path, prog_node, null);
867884

868885
const dep_file_dir = std.fs.cwd();
869-
const dep_file_basename = dep_output_file.generated_file.getPath();
886+
const dep_file_basename = dep_output_file.generated_file.getPath2(b, step);
870887
if (has_side_effects)
871888
try man.addDepFile(dep_file_dir, dep_file_basename)
872889
else

0 commit comments

Comments
 (0)