Commit 16d78bc0c0
Changed files (11)
lib/std/Build/Step/Compile.zig
@@ -668,6 +668,7 @@ pub fn producesPdbFile(compile: *Compile) bool {
else => return false,
}
if (target.ofmt == .c) return false;
+ if (compile.use_llvm == false) return false;
if (compile.root_module.strip == true or
(compile.root_module.strip == null and compile.root_module.optimize == .ReleaseSmall))
{
lib/std/Build/Step/InstallArtifact.zig
@@ -119,18 +119,12 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
_ = options;
const install_artifact: *InstallArtifact = @fieldParentPtr("step", step);
const b = step.owner;
- const cwd = fs.cwd();
var all_cached = true;
if (install_artifact.dest_dir) |dest_dir| {
const full_dest_path = b.getInstallPath(dest_dir, install_artifact.dest_sub_path);
- const src_path = install_artifact.emitted_bin.?.getPath3(b, step);
- const p = fs.Dir.updateFile(src_path.root_dir.handle, src_path.sub_path, cwd, full_dest_path, .{}) catch |err| {
- return step.fail("unable to update file from '{s}' to '{s}': {s}", .{
- src_path.sub_path, full_dest_path, @errorName(err),
- });
- };
+ const p = try step.installFile(install_artifact.emitted_bin.?, full_dest_path);
all_cached = all_cached and p == .fresh;
if (install_artifact.dylib_symlinks) |dls| {
@@ -141,48 +135,28 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
}
if (install_artifact.implib_dir) |implib_dir| {
- const src_path = install_artifact.emitted_implib.?.getPath3(b, step);
- const full_implib_path = b.getInstallPath(implib_dir, fs.path.basename(src_path.sub_path));
- const p = fs.Dir.updateFile(src_path.root_dir.handle, src_path.sub_path, cwd, full_implib_path, .{}) catch |err| {
- return step.fail("unable to update file from '{s}' to '{s}': {s}", .{
- src_path.sub_path, full_implib_path, @errorName(err),
- });
- };
+ const full_implib_path = b.getInstallPath(implib_dir, install_artifact.emitted_implib.?.basename(b, step));
+ const p = try step.installFile(install_artifact.emitted_implib.?, full_implib_path);
all_cached = all_cached and p == .fresh;
}
if (install_artifact.pdb_dir) |pdb_dir| {
- const src_path = install_artifact.emitted_pdb.?.getPath3(b, step);
- const full_pdb_path = b.getInstallPath(pdb_dir, fs.path.basename(src_path.sub_path));
- const p = fs.Dir.updateFile(src_path.root_dir.handle, src_path.sub_path, cwd, full_pdb_path, .{}) catch |err| {
- return step.fail("unable to update file from '{s}' to '{s}': {s}", .{
- src_path.sub_path, full_pdb_path, @errorName(err),
- });
- };
+ const full_pdb_path = b.getInstallPath(pdb_dir, install_artifact.emitted_pdb.?.basename(b, step));
+ const p = try step.installFile(install_artifact.emitted_pdb.?, full_pdb_path);
all_cached = all_cached and p == .fresh;
}
if (install_artifact.h_dir) |h_dir| {
if (install_artifact.emitted_h) |emitted_h| {
- const src_path = emitted_h.getPath3(b, step);
- const full_h_path = b.getInstallPath(h_dir, fs.path.basename(src_path.sub_path));
- const p = fs.Dir.updateFile(src_path.root_dir.handle, src_path.sub_path, cwd, full_h_path, .{}) catch |err| {
- return step.fail("unable to update file from '{s}' to '{s}': {s}", .{
- src_path.sub_path, full_h_path, @errorName(err),
- });
- };
+ const full_h_path = b.getInstallPath(h_dir, emitted_h.basename(b, step));
+ const p = try step.installFile(emitted_h, full_h_path);
all_cached = all_cached and p == .fresh;
}
for (install_artifact.artifact.installed_headers.items) |installation| switch (installation) {
.file => |file| {
- const src_path = file.source.getPath3(b, step);
const full_h_path = b.getInstallPath(h_dir, file.dest_rel_path);
- const p = fs.Dir.updateFile(src_path.root_dir.handle, src_path.sub_path, cwd, full_h_path, .{}) catch |err| {
- return step.fail("unable to update file from '{s}' to '{s}': {s}", .{
- src_path.sub_path, full_h_path, @errorName(err),
- });
- };
+ const p = try step.installFile(file.source, full_h_path);
all_cached = all_cached and p == .fresh;
},
.directory => |dir| {
@@ -209,16 +183,15 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
}
}
- 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),
+ .directory => {
+ try Step.handleVerbose(b, null, &.{ "install", "-d", full_dest_path });
+ const p = try step.installDir(full_dest_path);
+ all_cached = all_cached and p == .existed;
+ },
.file => {
- const p = fs.Dir.updateFile(src_entry_path.root_dir.handle, src_entry_path.sub_path, cwd, full_dest_path, .{}) catch |err| {
- return step.fail("unable to update file from '{s}' to '{s}': {s}", .{
- src_entry_path.sub_path, full_dest_path, @errorName(err),
- });
- };
+ const p = try step.installFile(try dir.source.join(b.allocator, entry.path), full_dest_path);
all_cached = all_cached and p == .fresh;
},
else => continue,
lib/std/Build/Step/InstallDir.zig
@@ -74,31 +74,23 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
var all_cached = true;
next_entry: while (try it.next()) |entry| {
for (install_dir.options.exclude_extensions) |ext| {
- if (mem.endsWith(u8, entry.path, ext)) {
- continue :next_entry;
- }
+ if (mem.endsWith(u8, entry.path, ext)) continue :next_entry;
}
if (install_dir.options.include_extensions) |incs| {
- var found = false;
for (incs) |inc| {
- if (mem.endsWith(u8, entry.path, inc)) {
- found = true;
- break;
- }
+ if (mem.endsWith(u8, entry.path, inc)) break;
+ } else {
+ continue :next_entry;
}
- if (!found) continue :next_entry;
}
- // relative to src build root
- const src_sub_path = try src_dir_path.join(arena, entry.path);
+ const src_path = try install_dir.options.source_dir.join(b.allocator, entry.path);
const dest_path = b.pathJoin(&.{ dest_prefix, entry.path });
- const cwd = fs.cwd();
-
switch (entry.kind) {
.directory => {
- if (need_derived_inputs) try step.addDirectoryWatchInputFromPath(src_sub_path);
- try cwd.makePath(dest_path);
- // TODO: set result_cached=false if the directory did not already exist.
+ if (need_derived_inputs) _ = try step.addDirectoryWatchInput(src_path);
+ const p = try step.installDir(dest_path);
+ all_cached = all_cached and p == .existed;
},
.file => {
for (install_dir.options.blank_extensions) |ext| {
@@ -108,18 +100,8 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
}
}
- const prev_status = fs.Dir.updateFile(
- src_sub_path.root_dir.handle,
- src_sub_path.sub_path,
- cwd,
- dest_path,
- .{},
- ) catch |err| {
- return step.fail("unable to update file from '{}' to '{s}': {s}", .{
- src_sub_path, dest_path, @errorName(err),
- });
- };
- all_cached = all_cached and prev_status == .fresh;
+ const p = try step.installFile(src_path, dest_path);
+ all_cached = all_cached and p == .fresh;
},
else => continue,
}
lib/std/Build/Step/InstallFile.zig
@@ -41,13 +41,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
const install_file: *InstallFile = @fieldParentPtr("step", step);
try step.singleUnchangingWatchInput(install_file.source);
- const full_src_path = install_file.source.getPath2(b, step);
const full_dest_path = b.getInstallPath(install_file.dir, install_file.dest_rel_path);
- const cwd = std.fs.cwd();
- const prev = std.fs.Dir.updateFile(cwd, full_src_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),
- });
- };
- step.result_cached = prev == .fresh;
+ const p = try step.installFile(install_file.source, full_dest_path);
+ step.result_cached = p == .fresh;
}
lib/std/Build/Step/ObjCopy.zig
@@ -209,7 +209,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
}
if (objcopy.add_section) |section| {
try argv.append("--add-section");
- try argv.appendSlice(&.{b.fmt("{s}={s}", .{ section.section_name, section.file_path.getPath(b) })});
+ try argv.appendSlice(&.{b.fmt("{s}={s}", .{ section.section_name, section.file_path.getPath2(b, step) })});
}
if (objcopy.set_section_alignment) |set_align| {
try argv.append("--set-section-alignment");
lib/std/Build/Step/Run.zig
@@ -456,11 +456,28 @@ pub fn addPathDir(run: *Run, search_path: []const u8) void {
const b = run.step.owner;
const env_map = getEnvMapInternal(run);
- const key = "PATH";
+ const use_wine = b.enable_wine and b.graph.host.result.os.tag != .windows and use_wine: switch (run.argv.items[0]) {
+ .artifact => |p| p.artifact.rootModuleTarget().os.tag == .windows,
+ .lazy_path => |p| {
+ switch (p.lazy_path) {
+ .generated => |g| if (g.file.step.cast(Step.Compile)) |cs| break :use_wine cs.rootModuleTarget().os.tag == .windows,
+ else => {},
+ }
+ break :use_wine std.mem.endsWith(u8, p.lazy_path.basename(b, &run.step), ".exe");
+ },
+ .decorated_directory => false,
+ .bytes => |bytes| std.mem.endsWith(u8, bytes, ".exe"),
+ .output_file, .output_directory => false,
+ };
+ const key = if (use_wine) "WINEPATH" else "PATH";
const prev_path = env_map.get(key);
if (prev_path) |pp| {
- const new_path = b.fmt("{s}" ++ [1]u8{fs.path.delimiter} ++ "{s}", .{ pp, search_path });
+ const new_path = b.fmt("{s}{c}{s}", .{
+ pp,
+ if (use_wine) fs.path.delimiter_windows else fs.path.delimiter,
+ search_path,
+ });
env_map.put(key, new_path) catch @panic("OOM");
} else {
env_map.put(key, b.dupePath(search_path)) catch @panic("OOM");
@@ -866,7 +883,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
try runCommand(run, argv_list.items, has_side_effects, tmp_dir_path, prog_node, null);
const dep_file_dir = std.fs.cwd();
- const dep_file_basename = dep_output_file.generated_file.getPath();
+ const dep_file_basename = dep_output_file.generated_file.getPath2(b, step);
if (has_side_effects)
try man.addDepFile(dep_file_dir, dep_file_basename)
else
lib/std/Build/Step.zig
@@ -478,6 +478,29 @@ pub fn evalZigProcess(
return result;
}
+/// Wrapper around `std.fs.Dir.updateFile` that handles verbose and error output.
+pub fn installFile(s: *Step, src_lazy_path: Build.LazyPath, dest_path: []const u8) !std.fs.Dir.PrevStatus {
+ const b = s.owner;
+ const src_path = src_lazy_path.getPath3(b, s);
+ try handleVerbose(b, null, &.{ "install", "-C", b.fmt("{}", .{src_path}), dest_path });
+ return src_path.root_dir.handle.updateFile(src_path.sub_path, std.fs.cwd(), dest_path, .{}) catch |err| {
+ return s.fail("unable to update file from '{}' to '{s}': {s}", .{
+ src_path, dest_path, @errorName(err),
+ });
+ };
+}
+
+/// Wrapper around `std.fs.Dir.makePathStatus` that handles verbose and error output.
+pub fn installDir(s: *Step, dest_path: []const u8) !std.fs.Dir.MakePathStatus {
+ const b = s.owner;
+ try handleVerbose(b, null, &.{ "install", "-d", dest_path });
+ return std.fs.cwd().makePathStatus(dest_path) catch |err| {
+ return s.fail("unable to create dir '{s}': {s}", .{
+ dest_path, @errorName(err),
+ });
+ };
+}
+
fn zigProcessUpdate(s: *Step, zp: *ZigProcess, watch: bool) !?Path {
const b = s.owner;
const arena = b.allocator;
@@ -714,8 +737,44 @@ pub fn allocPrintCmd2(
opt_env: ?*const std.process.EnvMap,
argv: []const []const u8,
) Allocator.Error![]u8 {
+ const shell = struct {
+ fn escape(writer: anytype, string: []const u8, is_argv0: bool) !void {
+ for (string) |c| {
+ if (switch (c) {
+ else => true,
+ '%', '+'...':', '@'...'Z', '_', 'a'...'z' => false,
+ '=' => is_argv0,
+ }) break;
+ } else return writer.writeAll(string);
+
+ try writer.writeByte('"');
+ for (string) |c| {
+ if (switch (c) {
+ std.ascii.control_code.nul => break,
+ '!', '"', '$', '\\', '`' => true,
+ else => !std.ascii.isPrint(c),
+ }) try writer.writeByte('\\');
+ switch (c) {
+ std.ascii.control_code.nul => unreachable,
+ std.ascii.control_code.bel => try writer.writeByte('a'),
+ std.ascii.control_code.bs => try writer.writeByte('b'),
+ std.ascii.control_code.ht => try writer.writeByte('t'),
+ std.ascii.control_code.lf => try writer.writeByte('n'),
+ std.ascii.control_code.vt => try writer.writeByte('v'),
+ std.ascii.control_code.ff => try writer.writeByte('f'),
+ std.ascii.control_code.cr => try writer.writeByte('r'),
+ std.ascii.control_code.esc => try writer.writeByte('E'),
+ ' '...'~' => try writer.writeByte(c),
+ else => try writer.print("{o:0>3}", .{c}),
+ }
+ }
+ try writer.writeByte('"');
+ }
+ };
+
var buf: std.ArrayListUnmanaged(u8) = .empty;
- if (opt_cwd) |cwd| try buf.writer(arena).print("cd {s} && ", .{cwd});
+ const writer = buf.writer(arena);
+ if (opt_cwd) |cwd| try writer.print("cd {s} && ", .{cwd});
if (opt_env) |env| {
const process_env_map = std.process.getEnvMap(arena) catch std.process.EnvMap.init(arena);
var it = env.iterator();
@@ -725,11 +784,15 @@ pub fn allocPrintCmd2(
if (process_env_map.get(key)) |process_value| {
if (std.mem.eql(u8, value, process_value)) continue;
}
- try buf.writer(arena).print("{s}={s} ", .{ key, value });
+ try writer.print("{s}=", .{key});
+ try shell.escape(writer, value, false);
+ try writer.writeByte(' ');
}
}
- for (argv) |arg| {
- try buf.writer(arena).print("{s} ", .{arg});
+ try shell.escape(writer, argv[0], true);
+ for (argv[1..]) |arg| {
+ try writer.writeByte(' ');
+ try shell.escape(writer, arg, false);
}
return buf.toOwnedSlice(arena);
}
lib/std/fs/Dir.zig
@@ -1146,6 +1146,7 @@ pub fn makeDirW(self: Dir, sub_path: [*:0]const u16) MakeError!void {
/// On Windows, `sub_path` should be encoded as [WTF-8](https://simonsapin.github.io/wtf-8/).
/// On WASI, `sub_path` should be encoded as valid UTF-8.
/// On other platforms, `sub_path` is an opaque sequence of bytes with no particular encoding.
+/// Fails on an empty path with `error.BadPathName` as that is not a path that can be created.
///
/// Paths containing `..` components are handled differently depending on the platform:
/// - On Windows, `..` are resolved before the path is passed to NtCreateFile, meaning
@@ -1155,10 +1156,19 @@ pub fn makeDirW(self: Dir, sub_path: [*:0]const u16) MakeError!void {
/// meaning a `sub_path` like "first/../second" will create both a `./first`
/// and a `./second` directory.
pub fn makePath(self: Dir, sub_path: []const u8) (MakeError || StatFileError)!void {
+ _ = try self.makePathStatus(sub_path);
+}
+
+pub const MakePathStatus = enum { existed, created };
+/// Same as `makePath` except returns whether the path already existed or was successfully created.
+pub fn makePathStatus(self: Dir, sub_path: []const u8) (MakeError || StatFileError)!MakePathStatus {
var it = try fs.path.componentIterator(sub_path);
- var component = it.last() orelse return;
+ var status: MakePathStatus = .existed;
+ var component = it.last() orelse return error.BadPathName;
while (true) {
- self.makeDir(component.path) catch |err| switch (err) {
+ if (self.makeDir(component.path)) |_| {
+ status = .created;
+ } else |err| switch (err) {
error.PathAlreadyExists => {
// stat the file and return an error if it's not a directory
// this is important because otherwise a dangling symlink
@@ -1177,8 +1187,8 @@ pub fn makePath(self: Dir, sub_path: []const u8) (MakeError || StatFileError)!vo
continue;
},
else => |e| return e,
- };
- component = it.next() orelse return;
+ }
+ component = it.next() orelse return status;
}
}
lib/std/fs/path.zig
@@ -27,8 +27,8 @@ const fs = std.fs;
const process = std.process;
const native_os = builtin.target.os.tag;
-pub const sep_windows = '\\';
-pub const sep_posix = '/';
+pub const sep_windows: u8 = '\\';
+pub const sep_posix: u8 = '/';
pub const sep = switch (native_os) {
.windows, .uefi => sep_windows,
else => sep_posix,
@@ -41,8 +41,8 @@ pub const sep_str = switch (native_os) {
else => sep_str_posix,
};
-pub const delimiter_windows = ';';
-pub const delimiter_posix = ':';
+pub const delimiter_windows: u8 = ';';
+pub const delimiter_posix: u8 = ':';
pub const delimiter = if (native_os == .windows) delimiter_windows else delimiter_posix;
/// Returns if the given byte is a valid path separator
lib/std/Build.zig
@@ -2456,12 +2456,23 @@ pub const GeneratedFile = struct {
/// This value must be set in the `fn make()` of the `step` and must not be `null` afterwards.
path: ?[]const u8 = null,
+ /// Deprecated, see `getPath2`.
pub fn getPath(gen: GeneratedFile) []const u8 {
return gen.step.owner.pathFromCwd(gen.path orelse std.debug.panic(
"getPath() was called on a GeneratedFile that wasn't built yet. Is there a missing Step dependency on step '{s}'?",
.{gen.step.name},
));
}
+
+ pub fn getPath2(gen: GeneratedFile, src_builder: *Build, asking_step: ?*Step) []const u8 {
+ return gen.path orelse {
+ std.debug.lockStdErr();
+ const stderr = std.io.getStdErr();
+ dumpBadGetPathHelp(gen.step, stderr, src_builder, asking_step) catch {};
+ std.debug.unlockStdErr();
+ @panic("misconfigured build script");
+ };
+ }
};
// dirnameAllowEmpty is a variant of fs.path.dirname
@@ -2712,6 +2723,18 @@ pub const LazyPath = union(enum) {
}
}
+ pub fn basename(lazy_path: LazyPath, src_builder: *Build, asking_step: ?*Step) []const u8 {
+ return fs.path.basename(switch (lazy_path) {
+ .src_path => |sp| sp.sub_path,
+ .cwd_relative => |sub_path| sub_path,
+ .generated => |gen| if (gen.sub_path.len > 0)
+ gen.sub_path
+ else
+ gen.file.getPath2(src_builder, asking_step),
+ .dependency => |dep| dep.sub_path,
+ });
+ }
+
/// Copies the internal strings.
///
/// The `b` parameter is only used for its allocator. All *Build instances
build.zig
@@ -203,6 +203,10 @@ pub fn build(b: *std.Build) !void {
exe.pie = pie;
exe.entitlements = entitlements;
+ const use_llvm = b.option(bool, "use-llvm", "Use the llvm backend");
+ exe.use_llvm = use_llvm;
+ exe.use_lld = use_llvm;
+
if (no_bin) {
b.getInstallStep().dependOn(&exe.step);
} else {
@@ -214,10 +218,6 @@ pub fn build(b: *std.Build) !void {
test_step.dependOn(&exe.step);
- const use_llvm = b.option(bool, "use-llvm", "Use the llvm backend");
- exe.use_llvm = use_llvm;
- exe.use_lld = use_llvm;
-
const exe_options = b.addOptions();
exe.root_module.addOptions("build_options", exe_options);