Skip to content

Commit 8aab222

Browse files
committed
Compilation: add missing link file options to cache manifest
Also add a standalone test which covers the `-fentry` case. It does this by performing two reproducible compilations which are identical other than having different entry points, and checking whether the emitted binaries are identical (they should *not* be). Resolves: #23869
1 parent 561fdd0 commit 8aab222

File tree

5 files changed

+88
-0
lines changed

5 files changed

+88
-0
lines changed

src/Compilation.zig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3233,6 +3233,13 @@ fn addNonIncrementalStuffToCacheManifest(
32333233
man.hash.addOptional(opts.allow_shlib_undefined);
32343234
man.hash.add(opts.bind_global_refs_locally);
32353235

3236+
const EntryTag = @typeInfo(link.File.OpenOptions.Entry).@"union".tag_type.?;
3237+
man.hash.add(@as(EntryTag, opts.entry));
3238+
switch (opts.entry) {
3239+
.default, .disabled, .enabled => {},
3240+
.named => |name| man.hash.addBytes(name),
3241+
}
3242+
32363243
// ELF specific stuff
32373244
man.hash.add(opts.z_nodelete);
32383245
man.hash.add(opts.z_notext);
@@ -3254,6 +3261,9 @@ fn addNonIncrementalStuffToCacheManifest(
32543261
man.hash.addOptional(opts.max_memory);
32553262
man.hash.addOptional(opts.global_base);
32563263
man.hash.addListOfBytes(opts.export_symbol_names);
3264+
man.hash.add(opts.import_symbols);
3265+
man.hash.add(opts.import_table);
3266+
man.hash.add(opts.export_table);
32573267

32583268
// Mach-O specific stuff
32593269
try link.File.MachO.hashAddFrameworks(man, opts.frameworks);
@@ -3264,6 +3274,9 @@ fn addNonIncrementalStuffToCacheManifest(
32643274
man.hash.add(opts.dead_strip_dylibs);
32653275
man.hash.add(opts.force_load_objc);
32663276
man.hash.add(opts.discard_local_symbols);
3277+
man.hash.addOptional(opts.compatibility_version);
3278+
man.hash.addOptionalBytes(opts.install_name);
3279+
man.hash.addOptional(opts.darwin_sdk_layout);
32673280

32683281
// COFF specific stuff
32693282
man.hash.addOptional(opts.subsystem);
@@ -3272,6 +3285,8 @@ fn addNonIncrementalStuffToCacheManifest(
32723285
man.hash.add(opts.dynamicbase);
32733286
man.hash.addOptional(opts.major_subsystem_version);
32743287
man.hash.addOptional(opts.minor_subsystem_version);
3288+
man.hash.addOptionalBytes(opts.pdb_source_path);
3289+
man.hash.addOptionalBytes(opts.module_definition_file);
32753290
}
32763291

32773292
fn emitFromCObject(

test/standalone/build.zig.zon

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@
201201
.config_header = .{
202202
.path = "config_header",
203203
},
204+
.entry_point = .{
205+
.path = "entry_point",
206+
},
204207
},
205208
.paths = .{
206209
"build.zig",

test/standalone/entry_point/build.zig

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
pub fn build(b: *std.Build) !void {
2+
const mod = b.createModule(.{
3+
// Setting the entry point doesn't work properly on all targets right now. Since we're
4+
// really just trying to make sure that the compiler *frontend* respects `-fentry` and
5+
// includes it in the cache manifest, just test for a target where it works.
6+
.target = b.resolveTargetQuery(try .parse(.{
7+
.arch_os_abi = "x86_64-linux",
8+
})),
9+
.optimize = .ReleaseFast, // non-Debug build for reproducible output
10+
.root_source_file = b.path("main.zig"),
11+
});
12+
13+
const exe_foo = b.addExecutable(.{
14+
.name = "the_exe", // same name for reproducible output
15+
.root_module = mod,
16+
});
17+
exe_foo.entry = .{ .symbol_name = "foo" };
18+
const exe_bar = b.addExecutable(.{
19+
.name = "the_exe", // same name for reproducible output
20+
.root_module = mod,
21+
});
22+
exe_bar.entry = .{ .symbol_name = "bar" };
23+
24+
// Despite the output binary being reproducible, the `entry` differed, so the emitted binaries
25+
// should be different. But the two compilations are otherwise identical, so if `entry` isn't
26+
// being respected properly, we will see identical binaries.
27+
28+
const check_differ_exe = b.addExecutable(.{
29+
.name = "check_differ",
30+
.root_module = b.createModule(.{
31+
.target = b.graph.host,
32+
.optimize = .Debug,
33+
.root_source_file = b.path("check_differ.zig"),
34+
}),
35+
});
36+
37+
const diff_cmd = b.addRunArtifact(check_differ_exe);
38+
diff_cmd.addFileArg(exe_foo.getEmittedBin());
39+
diff_cmd.addFileArg(exe_bar.getEmittedBin());
40+
diff_cmd.expectExitCode(0);
41+
42+
const test_step = b.step("test", "Test it");
43+
b.default_step = test_step;
44+
test_step.dependOn(&diff_cmd.step);
45+
}
46+
const std = @import("std");
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
pub fn main() !void {
2+
var arena_state: std.heap.ArenaAllocator = .init(std.heap.page_allocator);
3+
defer arena_state.deinit();
4+
const arena = arena_state.allocator();
5+
6+
const args = try std.process.argsAlloc(arena);
7+
if (args.len != 3) return error.BadUsage; // usage: 'check_differ <path a> <path b>'
8+
9+
const contents_1 = try std.fs.cwd().readFileAlloc(arena, args[1], 1024 * 1024 * 64); // 64 MiB ought to be plenty
10+
const contents_2 = try std.fs.cwd().readFileAlloc(arena, args[2], 1024 * 1024 * 64); // 64 MiB ought to be plenty
11+
12+
if (std.mem.eql(u8, contents_1, contents_2)) {
13+
return error.FilesMatch;
14+
}
15+
// success, files differ
16+
}
17+
const std = @import("std");

test/standalone/entry_point/main.zig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
pub const _start = {};
2+
export fn foo() u32 {
3+
return 123;
4+
}
5+
export fn bar() u32 {
6+
return 456;
7+
}

0 commit comments

Comments
 (0)