aboutsummaryrefslogtreecommitdiff
path: root/lib/std/Build
diff options
context:
space:
mode:
Diffstat (limited to 'lib/std/Build')
-rw-r--r--lib/std/Build/Cache.zig57
-rw-r--r--lib/std/Build/Step/Compile.zig50
2 files changed, 83 insertions, 24 deletions
diff --git a/lib/std/Build/Cache.zig b/lib/std/Build/Cache.zig
index bd98634ba8..7f8a6d3159 100644
--- a/lib/std/Build/Cache.zig
+++ b/lib/std/Build/Cache.zig
@@ -142,6 +142,9 @@ pub const hasher_init: Hasher = Hasher.init(&[_]u8{
pub const File = struct {
prefixed_path: PrefixedPath,
max_file_size: ?usize,
+ /// Populated if the user calls `addOpenedFile`.
+ /// The handle is not owned here.
+ handle: ?fs.File,
stat: Stat,
bin_digest: BinDigest,
contents: ?[]const u8,
@@ -173,6 +176,11 @@ pub const File = struct {
const new = new_max_size orelse return;
file.max_file_size = if (file.max_file_size) |old| @max(old, new) else new;
}
+
+ pub fn updateHandle(file: *File, new_handle: ?fs.File) void {
+ const handle = new_handle orelse return;
+ file.handle = handle;
+ }
};
pub const HashHelper = struct {
@@ -363,15 +371,20 @@ pub const Manifest = struct {
/// var file_contents = cache_hash.files.keys()[file_index].contents.?;
/// ```
pub fn addFilePath(m: *Manifest, file_path: Path, max_file_size: ?usize) !usize {
+ return addOpenedFile(m, file_path, null, max_file_size);
+ }
+
+ /// Same as `addFilePath` except the file has already been opened.
+ pub fn addOpenedFile(m: *Manifest, path: Path, handle: ?fs.File, max_file_size: ?usize) !usize {
const gpa = m.cache.gpa;
try m.files.ensureUnusedCapacity(gpa, 1);
const resolved_path = try fs.path.resolve(gpa, &.{
- file_path.root_dir.path orelse ".",
- file_path.subPathOrDot(),
+ path.root_dir.path orelse ".",
+ path.subPathOrDot(),
});
errdefer gpa.free(resolved_path);
const prefixed_path = try m.cache.findPrefixResolved(resolved_path);
- return addFileInner(m, prefixed_path, max_file_size);
+ return addFileInner(m, prefixed_path, handle, max_file_size);
}
/// Deprecated; use `addFilePath`.
@@ -383,13 +396,14 @@ pub const Manifest = struct {
const prefixed_path = try self.cache.findPrefix(file_path);
errdefer gpa.free(prefixed_path.sub_path);
- return addFileInner(self, prefixed_path, max_file_size);
+ return addFileInner(self, prefixed_path, null, max_file_size);
}
- fn addFileInner(self: *Manifest, prefixed_path: PrefixedPath, max_file_size: ?usize) !usize {
+ fn addFileInner(self: *Manifest, prefixed_path: PrefixedPath, handle: ?fs.File, max_file_size: ?usize) usize {
const gop = self.files.getOrPutAssumeCapacityAdapted(prefixed_path, FilesAdapter{});
if (gop.found_existing) {
gop.key_ptr.updateMaxSize(max_file_size);
+ gop.key_ptr.updateHandle(handle);
return gop.index;
}
gop.key_ptr.* = .{
@@ -398,6 +412,7 @@ pub const Manifest = struct {
.max_file_size = max_file_size,
.stat = undefined,
.bin_digest = undefined,
+ .handle = handle,
};
self.hash.add(prefixed_path.prefix);
@@ -565,6 +580,7 @@ pub const Manifest = struct {
},
.contents = null,
.max_file_size = null,
+ .handle = null,
.stat = .{
.size = stat_size,
.inode = stat_inode,
@@ -708,12 +724,19 @@ pub const Manifest = struct {
}
fn populateFileHash(self: *Manifest, ch_file: *File) !void {
- const pp = ch_file.prefixed_path;
- const dir = self.cache.prefixes()[pp.prefix].handle;
- const file = try dir.openFile(pp.sub_path, .{});
- defer file.close();
+ if (ch_file.handle) |handle| {
+ return populateFileHashHandle(self, ch_file, handle);
+ } else {
+ const pp = ch_file.prefixed_path;
+ const dir = self.cache.prefixes()[pp.prefix].handle;
+ const handle = try dir.openFile(pp.sub_path, .{});
+ defer handle.close();
+ return populateFileHashHandle(self, ch_file, handle);
+ }
+ }
- const actual_stat = try file.stat();
+ fn populateFileHashHandle(self: *Manifest, ch_file: *File, handle: fs.File) !void {
+ const actual_stat = try handle.stat();
ch_file.stat = .{
.size = actual_stat.size,
.mtime = actual_stat.mtime,
@@ -739,8 +762,7 @@ pub const Manifest = struct {
var hasher = hasher_init;
var off: usize = 0;
while (true) {
- // give me everything you've got, captain
- const bytes_read = try file.read(contents[off..]);
+ const bytes_read = try handle.pread(contents[off..], off);
if (bytes_read == 0) break;
hasher.update(contents[off..][0..bytes_read]);
off += bytes_read;
@@ -749,7 +771,7 @@ pub const Manifest = struct {
ch_file.contents = contents;
} else {
- try hashFile(file, &ch_file.bin_digest);
+ try hashFile(handle, &ch_file.bin_digest);
}
self.hash.hasher.update(&ch_file.bin_digest);
@@ -813,6 +835,7 @@ pub const Manifest = struct {
gop.key_ptr.* = .{
.prefixed_path = prefixed_path,
.max_file_size = null,
+ .handle = null,
.stat = undefined,
.bin_digest = undefined,
.contents = null,
@@ -851,6 +874,7 @@ pub const Manifest = struct {
new_file.* = .{
.prefixed_path = prefixed_path,
.max_file_size = null,
+ .handle = null,
.stat = stat,
.bin_digest = undefined,
.contents = null,
@@ -1067,6 +1091,7 @@ pub const Manifest = struct {
gop.key_ptr.* = .{
.prefixed_path = prefixed_path,
.max_file_size = file.max_file_size,
+ .handle = file.handle,
.stat = file.stat,
.bin_digest = file.bin_digest,
.contents = null,
@@ -1103,14 +1128,14 @@ pub fn writeSmallFile(dir: fs.Dir, sub_path: []const u8, data: []const u8) !void
fn hashFile(file: fs.File, bin_digest: *[Hasher.mac_length]u8) !void {
var buf: [1024]u8 = undefined;
-
var hasher = hasher_init;
+ var off: u64 = 0;
while (true) {
- const bytes_read = try file.read(&buf);
+ const bytes_read = try file.pread(&buf, off);
if (bytes_read == 0) break;
hasher.update(buf[0..bytes_read]);
+ off += bytes_read;
}
-
hasher.final(bin_digest);
}
diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig
index 469fbdf74a..f0dad8b49a 100644
--- a/lib/std/Build/Step/Compile.zig
+++ b/lib/std/Build/Step/Compile.zig
@@ -186,6 +186,15 @@ want_lto: ?bool = null,
use_llvm: ?bool,
use_lld: ?bool,
+/// Corresponds to the `-fallow-so-scripts` / `-fno-allow-so-scripts` CLI
+/// flags, overriding the global user setting provided to the `zig build`
+/// command.
+///
+/// The compiler defaults this value to off so that users whose system shared
+/// libraries are all ELF files don't have to pay the cost of checking every
+/// file to find out if it is a text file instead.
+allow_so_scripts: ?bool = null,
+
/// This is an advanced setting that can change the intent of this Compile step.
/// If this value is non-null, it means that this Compile step exists to
/// check for compile errors and return *success* if they match, and failure
@@ -236,6 +245,7 @@ pub const ExpectedCompileErrors = union(enum) {
contains: []const u8,
exact: []const []const u8,
starts_with: []const u8,
+ stderr_contains: []const u8,
};
pub const Entry = union(enum) {
@@ -1035,6 +1045,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
if (b.reference_trace) |some| {
try zig_args.append(try std.fmt.allocPrint(arena, "-freference-trace={d}", .{some}));
}
+ try addFlag(&zig_args, "allow-so-scripts", compile.allow_so_scripts orelse b.graph.allow_so_scripts);
try addFlag(&zig_args, "llvm", compile.use_llvm);
try addFlag(&zig_args, "lld", compile.use_lld);
@@ -1945,24 +1956,24 @@ fn checkCompileErrors(compile: *Compile) !void {
const arena = compile.step.owner.allocator;
- var actual_stderr_list = std.ArrayList(u8).init(arena);
+ var actual_errors_list = std.ArrayList(u8).init(arena);
try actual_eb.renderToWriter(.{
.ttyconf = .no_color,
.include_reference_trace = false,
.include_source_line = false,
- }, actual_stderr_list.writer());
- const actual_stderr = try actual_stderr_list.toOwnedSlice();
+ }, actual_errors_list.writer());
+ const actual_errors = try actual_errors_list.toOwnedSlice();
// Render the expected lines into a string that we can compare verbatim.
var expected_generated = std.ArrayList(u8).init(arena);
const expect_errors = compile.expect_errors.?;
- var actual_line_it = mem.splitScalar(u8, actual_stderr, '\n');
+ var actual_line_it = mem.splitScalar(u8, actual_errors, '\n');
// TODO merge this with the testing.expectEqualStrings logic, and also CheckFile
switch (expect_errors) {
.starts_with => |expect_starts_with| {
- if (std.mem.startsWith(u8, actual_stderr, expect_starts_with)) return;
+ if (std.mem.startsWith(u8, actual_errors, expect_starts_with)) return;
return compile.step.fail(
\\
\\========= should start with: ============
@@ -1970,7 +1981,7 @@ fn checkCompileErrors(compile: *Compile) !void {
\\========= but not found: ================
\\{s}
\\=========================================
- , .{ expect_starts_with, actual_stderr });
+ , .{ expect_starts_with, actual_errors });
},
.contains => |expect_line| {
while (actual_line_it.next()) |actual_line| {
@@ -1985,6 +1996,29 @@ fn checkCompileErrors(compile: *Compile) !void {
\\========= but not found: ================
\\{s}
\\=========================================
+ , .{ expect_line, actual_errors });
+ },
+ .stderr_contains => |expect_line| {
+ const actual_stderr: []const u8 = if (compile.step.result_error_msgs.items.len > 0)
+ compile.step.result_error_msgs.items[0]
+ else
+ &.{};
+ compile.step.result_error_msgs.clearRetainingCapacity();
+
+ var stderr_line_it = mem.splitScalar(u8, actual_stderr, '\n');
+
+ while (stderr_line_it.next()) |actual_line| {
+ if (!matchCompileError(actual_line, expect_line)) continue;
+ return;
+ }
+
+ return compile.step.fail(
+ \\
+ \\========= should contain: ===============
+ \\{s}
+ \\========= but not found: ================
+ \\{s}
+ \\=========================================
, .{ expect_line, actual_stderr });
},
.exact => |expect_lines| {
@@ -2003,7 +2037,7 @@ fn checkCompileErrors(compile: *Compile) !void {
try expected_generated.append('\n');
}
- if (mem.eql(u8, expected_generated.items, actual_stderr)) return;
+ if (mem.eql(u8, expected_generated.items, actual_errors)) return;
return compile.step.fail(
\\
@@ -2012,7 +2046,7 @@ fn checkCompileErrors(compile: *Compile) !void {
\\========= but found: ====================
\\{s}
\\=========================================
- , .{ expected_generated.items, actual_stderr });
+ , .{ expected_generated.items, actual_errors });
},
}
}