Skip to content

Commit

Permalink
Merge pull request #20688 from ziglang/incr-test
Browse files Browse the repository at this point in the history
introduce a new tool for testing incremental compilation
  • Loading branch information
andrewrk authored Jul 20, 2024
2 parents ef3a746 + 645ad1e commit b5f3d12
Show file tree
Hide file tree
Showing 14 changed files with 480 additions and 51 deletions.
15 changes: 3 additions & 12 deletions lib/std/Build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2522,7 +2522,7 @@ pub const InstallDir = union(enum) {
/// function.
pub fn makeTempPath(b: *Build) []const u8 {
const rand_int = std.crypto.random.int(u64);
const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ hex64(rand_int);
const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int);
const result_path = b.cache_root.join(b.allocator, &.{tmp_dir_sub_path}) catch @panic("OOM");
b.cache_root.handle.makePath(tmp_dir_sub_path) catch |err| {
std.debug.print("unable to make tmp path '{s}': {s}\n", .{
Expand All @@ -2532,18 +2532,9 @@ pub fn makeTempPath(b: *Build) []const u8 {
return result_path;
}

/// There are a few copies of this function in miscellaneous places. Would be nice to find
/// a home for them.
/// Deprecated; use `std.fmt.hex` instead.
pub fn hex64(x: u64) [16]u8 {
const hex_charset = "0123456789abcdef";
var result: [16]u8 = undefined;
var i: usize = 0;
while (i < 8) : (i += 1) {
const byte: u8 = @truncate(x >> @as(u6, @intCast(8 * i)));
result[i * 2 + 0] = hex_charset[byte >> 4];
result[i * 2 + 1] = hex_charset[byte & 15];
}
return result;
return std.fmt.hex(x);
}

/// A pair of target query and fully resolved target.
Expand Down
2 changes: 1 addition & 1 deletion lib/std/Build/Step/Options.zig
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void {

const rand_int = std.crypto.random.int(u64);
const tmp_sub_path = "tmp" ++ fs.path.sep_str ++
std.Build.hex64(rand_int) ++ fs.path.sep_str ++
std.fmt.hex(rand_int) ++ fs.path.sep_str ++
basename;
const tmp_sub_path_dirname = fs.path.dirname(tmp_sub_path).?;

Expand Down
2 changes: 1 addition & 1 deletion lib/std/Build/Step/Run.zig
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {

// We do not know the final output paths yet, use temp paths to run the command.
const rand_int = std.crypto.random.int(u64);
const tmp_dir_path = "tmp" ++ fs.path.sep_str ++ std.Build.hex64(rand_int);
const tmp_dir_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int);

for (output_placeholders.items) |placeholder| {
const output_components = .{ tmp_dir_path, placeholder.output.basename };
Expand Down
29 changes: 29 additions & 0 deletions lib/std/fmt.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2718,3 +2718,32 @@ test "recursive format function" {
var r = R{ .Leaf = 1 };
try expectFmt("Leaf(1)\n", "{}\n", .{&r});
}

pub const hex_charset = "0123456789abcdef";

/// Converts an unsigned integer of any multiple of u8 to an array of lowercase
/// hex bytes, little endian.
pub fn hex(x: anytype) [@sizeOf(@TypeOf(x)) * 2]u8 {
comptime assert(@typeInfo(@TypeOf(x)).Int.signedness == .unsigned);
var result: [@sizeOf(@TypeOf(x)) * 2]u8 = undefined;
var i: usize = 0;
while (i < result.len / 2) : (i += 1) {
const byte: u8 = @truncate(x >> @intCast(8 * i));
result[i * 2 + 0] = hex_charset[byte >> 4];
result[i * 2 + 1] = hex_charset[byte & 15];
}
return result;
}

test hex {
{
const x = hex(@as(u32, 0xdeadbeef));
try std.testing.expect(x.len == 8);
try std.testing.expectEqualStrings("efbeadde", &x);
}
{
const s = "[" ++ hex(@as(u64, 0x12345678_abcdef00)) ++ "]";
try std.testing.expect(s.len == 18);
try std.testing.expectEqualStrings("[00efcdab78563412]", s);
}
}
6 changes: 6 additions & 0 deletions lib/std/process.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2032,3 +2032,9 @@ pub fn createWindowsEnvBlock(allocator: mem.Allocator, env_map: *const EnvMap) !
i += 1;
return try allocator.realloc(result, i);
}

/// Logs an error and then terminates the process with exit code 1.
pub fn fatal(comptime format: []const u8, format_arguments: anytype) noreturn {
std.log.err(format, format_arguments);
exit(1);
}
6 changes: 2 additions & 4 deletions lib/std/zig.zig
Original file line number Diff line number Diff line change
Expand Up @@ -667,10 +667,8 @@ pub fn parseTargetQueryOrReportFatalError(
};
}

pub fn fatal(comptime format: []const u8, args: anytype) noreturn {
std.log.err(format, args);
std.process.exit(1);
}
/// Deprecated; see `std.process.fatal`.
pub const fatal = std.process.fatal;

/// Collects all the environment variables that Zig could possibly inspect, so
/// that we can do reflection on this and print them with `zig env`.
Expand Down
5 changes: 5 additions & 0 deletions lib/std/zig/Server.zig
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ pub fn deinit(s: *Server) void {
pub fn receiveMessage(s: *Server) !InMessage.Header {
const Header = InMessage.Header;
const fifo = &s.receive_fifo;
var last_amt_zero = false;

while (true) {
const buf = fifo.readableSlice(0);
Expand Down Expand Up @@ -136,6 +137,10 @@ pub fn receiveMessage(s: *Server) !InMessage.Header {
const write_buffer = try fifo.writableWithSize(256);
const amt = try s.in.read(write_buffer);
fifo.update(amt);
if (amt == 0) {
if (last_amt_zero) return error.BrokenPipe;
last_amt_zero = true;
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/Compilation.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2105,7 +2105,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
const tmp_artifact_directory = d: {
const s = std.fs.path.sep_str;
tmp_dir_rand_int = std.crypto.random.int(u64);
const tmp_dir_sub_path = "tmp" ++ s ++ Package.Manifest.hex64(tmp_dir_rand_int);
const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(tmp_dir_rand_int);

const path = try comp.local_cache_directory.join(gpa, &.{tmp_dir_sub_path});
errdefer gpa.free(path);
Expand Down Expand Up @@ -2297,7 +2297,7 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
} else unreachable;

const s = std.fs.path.sep_str;
const tmp_dir_sub_path = "tmp" ++ s ++ Package.Manifest.hex64(tmp_dir_rand_int);
const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(tmp_dir_rand_int);
const o_sub_path = "o" ++ s ++ digest;

// Work around windows `AccessDenied` if any files within this
Expand Down
2 changes: 1 addition & 1 deletion src/Package/Fetch.zig
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ fn runResource(
const s = fs.path.sep_str;
const cache_root = f.job_queue.global_cache;
const rand_int = std.crypto.random.int(u64);
const tmp_dir_sub_path = "tmp" ++ s ++ Manifest.hex64(rand_int);
const tmp_dir_sub_path = "tmp" ++ s ++ std.fmt.hex(rand_int);

const package_sub_path = blk: {
const tmp_directory_path = try cache_root.join(arena, &.{tmp_dir_sub_path});
Expand Down
35 changes: 9 additions & 26 deletions src/Package/Manifest.zig
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
const Manifest = @This();
const std = @import("std");
const mem = std.mem;
const Allocator = std.mem.Allocator;
const assert = std.debug.assert;
const Ast = std.zig.Ast;
const testing = std.testing;
const hex_charset = std.fmt.hex_charset;

pub const max_bytes = 10 * 1024 * 1024;
pub const basename = "build.zig.zon";
pub const Hash = std.crypto.hash.sha2.Sha256;
Expand Down Expand Up @@ -153,24 +162,6 @@ pub fn copyErrorsIntoBundle(
}
}

const hex_charset = "0123456789abcdef";

pub fn hex64(x: u64) [16]u8 {
var result: [16]u8 = undefined;
var i: usize = 0;
while (i < 8) : (i += 1) {
const byte = @as(u8, @truncate(x >> @as(u6, @intCast(8 * i))));
result[i * 2 + 0] = hex_charset[byte >> 4];
result[i * 2 + 1] = hex_charset[byte & 15];
}
return result;
}

test hex64 {
const s = "[" ++ hex64(0x12345678_abcdef00) ++ "]";
try std.testing.expectEqualStrings("[00efcdab78563412]", s);
}

pub fn hexDigest(digest: Digest) MultiHashHexDigest {
var result: MultiHashHexDigest = undefined;

Expand Down Expand Up @@ -590,14 +581,6 @@ const Parse = struct {
}
};

const Manifest = @This();
const std = @import("std");
const mem = std.mem;
const Allocator = std.mem.Allocator;
const assert = std.debug.assert;
const Ast = std.zig.Ast;
const testing = std.testing;

test "basic" {
const gpa = testing.allocator;

Expand Down
2 changes: 1 addition & 1 deletion src/link.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1031,7 +1031,7 @@ pub fn spawnLld(
error.NameTooLong => err: {
const s = fs.path.sep_str;
const rand_int = std.crypto.random.int(u64);
const rsp_path = "tmp" ++ s ++ Package.Manifest.hex64(rand_int) ++ ".rsp";
const rsp_path = "tmp" ++ s ++ std.fmt.hex(rand_int) ++ ".rsp";

const rsp_file = try comp.local_cache_directory.handle.createFileZ(rsp_path, .{});
defer comp.local_cache_directory.handle.deleteFileZ(rsp_path) catch |err|
Expand Down
5 changes: 2 additions & 3 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4746,7 +4746,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
// the strategy is to choose a temporary file name ahead of time, and then
// read this file in the parent to obtain the results, in the case the child
// exits with code 3.
const results_tmp_file_nonce = Package.Manifest.hex64(std.crypto.random.int(u64));
const results_tmp_file_nonce = std.fmt.hex(std.crypto.random.int(u64));
try child_argv.append("-Z" ++ results_tmp_file_nonce);

var color: Color = .auto;
Expand Down Expand Up @@ -7196,8 +7196,7 @@ fn createDependenciesModule(
// Atomically create the file in a directory named after the hash of its contents.
const basename = "dependencies.zig";
const rand_int = std.crypto.random.int(u64);
const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++
Package.Manifest.hex64(rand_int);
const tmp_dir_sub_path = "tmp" ++ fs.path.sep_str ++ std.fmt.hex(rand_int);
{
var tmp_dir = try local_cache_directory.handle.makeOpenPath(tmp_dir_sub_path, .{});
defer tmp_dir.close();
Expand Down
15 changes: 15 additions & 0 deletions test/incremental/hello
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#target=x86_64-linux
#update=initial version
#file=main.zig
const std = @import("std");
pub fn main() !void {
try std.io.getStdOut().writeAll("good morning\n");
}
#expect_stdout="good morning\n"
#update=change the string
#file=main.zig
const std = @import("std");
pub fn main() !void {
try std.io.getStdOut().writeAll("おはようございます\n");
}
#expect_stdout="おはようございます\n"
Loading

0 comments on commit b5f3d12

Please sign in to comment.