Skip to content

Commit f599a04

Browse files
committed
Merge remote-tracking branch 'origin/main' into fix-issue-9005
2 parents 5159da0 + 2b02497 commit f599a04

80 files changed

Lines changed: 17760 additions & 1756 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

build.zig

Lines changed: 75 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1824,13 +1824,59 @@ const FixArchivePaddingStep = struct {
18241824
defer file.close();
18251825

18261826
const stat = try file.stat();
1827-
const file_size = stat.size;
1827+
var file_size = stat.size;
18281828

18291829
// AR format requires archives to end on an even byte boundary.
18301830
// If file size is odd, append a newline padding byte.
1831+
// This fixes Zig bug https://codeberg.org/ziglang/zig/issues/30572
1832+
// where Zig's archiver doesn't add required padding after odd-sized members.
18311833
if (file_size % 2 == 1) {
18321834
try file.seekTo(file_size);
18331835
try file.writeAll("\n");
1836+
file_size += 1;
1837+
}
1838+
1839+
// Parse the archive to verify member offsets are valid.
1840+
// This catches cases where lld would fail with "truncated or malformed archive".
1841+
try file.seekTo(0);
1842+
var header_buf: [8]u8 = undefined;
1843+
_ = try file.read(&header_buf);
1844+
if (!std.mem.eql(u8, &header_buf, "!<arch>\n")) {
1845+
std.debug.print("Warning: Invalid archive magic in {s}\n", .{self.archive_path});
1846+
return;
1847+
}
1848+
1849+
var offset: u64 = 8; // After magic
1850+
while (offset + 60 <= file_size) {
1851+
try file.seekTo(offset + 48); // Seek to size field (offset 48 within 60-byte header)
1852+
var size_buf: [10]u8 = undefined;
1853+
_ = try file.read(&size_buf);
1854+
1855+
// Parse size (ASCII decimal, space-padded)
1856+
var size: u64 = 0;
1857+
for (size_buf) |c| {
1858+
if (c >= '0' and c <= '9') {
1859+
size = size * 10 + (c - '0');
1860+
} else break;
1861+
}
1862+
1863+
// Move to next member (header + content + padding if odd)
1864+
offset += 60 + size;
1865+
if (size % 2 == 1) {
1866+
offset += 1; // Padding byte expected
1867+
}
1868+
1869+
// If we're exactly at EOF, archive is valid
1870+
if (offset == file_size) break;
1871+
1872+
// If next offset would be past EOF, we have a problem - add missing padding
1873+
if (offset > file_size) {
1874+
const missing = offset - file_size;
1875+
try file.seekTo(file_size);
1876+
const padding = "\n\n"; // At most 1 byte needed, but be safe
1877+
try file.writeAll(padding[0..@min(missing, 2)]);
1878+
break;
1879+
}
18341880
}
18351881
}
18361882
};
@@ -2859,17 +2905,39 @@ pub fn build(b: *std.Build) void {
28592905
// Copy the fx test platform host library to the source directory
28602906
const copy_test_fx_host = b.addUpdateSourceFiles();
28612907
const test_fx_host_filename = if (target.result.os.tag == .windows) "host.lib" else "libhost.a";
2862-
copy_test_fx_host.addCopyFileToSource(test_platform_fx_host_lib.getEmittedBin(), b.pathJoin(&.{ "test/fx/platform", test_fx_host_filename }));
2863-
b.getInstallStep().dependOn(&copy_test_fx_host.step);
2908+
const fx_host_main_path = b.pathJoin(&.{ "test/fx/platform", test_fx_host_filename });
2909+
copy_test_fx_host.addCopyFileToSource(test_platform_fx_host_lib.getEmittedBin(), fx_host_main_path);
28642910

28652911
// Also copy to the target-specific directory so findHostLibrary finds it
2866-
if (fx_host_target_dir) |target_dir| {
2912+
const fx_host_target_path = if (fx_host_target_dir) |target_dir|
2913+
b.pathJoin(&.{ "test/fx/platform/targets", target_dir, test_fx_host_filename })
2914+
else
2915+
null;
2916+
if (fx_host_target_path) |target_path| {
28672917
copy_test_fx_host.addCopyFileToSource(
28682918
test_platform_fx_host_lib.getEmittedBin(),
2869-
b.pathJoin(&.{ "test/fx/platform/targets", target_dir, test_fx_host_filename }),
2919+
target_path,
28702920
);
28712921
}
28722922

2923+
// Apply archive padding fix for non-Windows targets (Zig bug workaround)
2924+
// The final_fx_host_step is what tests should depend on to ensure the archive is ready
2925+
const final_fx_host_step: *Step = if (target.result.os.tag != .windows) blk: {
2926+
const fix_main = FixArchivePaddingStep.create(b, fx_host_main_path);
2927+
fix_main.step.dependOn(&copy_test_fx_host.step);
2928+
2929+
if (fx_host_target_path) |target_path| {
2930+
const fix_target = FixArchivePaddingStep.create(b, target_path);
2931+
fix_target.step.dependOn(&copy_test_fx_host.step);
2932+
// Make fix_target depend on fix_main so both complete
2933+
fix_target.step.dependOn(&fix_main.step);
2934+
break :blk &fix_target.step;
2935+
}
2936+
break :blk &fix_main.step;
2937+
} else &copy_test_fx_host.step;
2938+
2939+
b.getInstallStep().dependOn(final_fx_host_step);
2940+
28732941
const fx_platform_test = b.addTest(.{
28742942
.name = "fx_platform_test",
28752943
.root_module = b.createModule(.{
@@ -2884,8 +2952,8 @@ pub fn build(b: *std.Build) void {
28842952
if (run_args.len != 0) {
28852953
run_fx_platform_test.addArgs(run_args);
28862954
}
2887-
// Ensure host library is copied before running the test
2888-
run_fx_platform_test.step.dependOn(&copy_test_fx_host.step);
2955+
// Ensure host library is copied AND fixed before running the test
2956+
run_fx_platform_test.step.dependOn(final_fx_host_step);
28892957
// Ensure roc binary is built before running the test (tests invoke roc CLI)
28902958
run_fx_platform_test.step.dependOn(roc_step);
28912959
tests_summary.addRun(&run_fx_platform_test.step);

0 commit comments

Comments
 (0)