test: introduce link(er) tests - builds on standalone tests

This commit is contained in:
Jakub Konka 2022-05-28 11:44:53 +02:00
parent 74ed7c1f09
commit 38edef35bf
43 changed files with 182 additions and 89 deletions

View file

@ -489,6 +489,7 @@ pub fn build(b: *Builder) !void {
toolchain_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes));
toolchain_step.dependOn(tests.addStandaloneTests(b, test_filter, modes, skip_non_native, enable_macos_sdk, target));
toolchain_step.dependOn(tests.addLinkTests(b, test_filter, modes, enable_macos_sdk));
toolchain_step.dependOn(tests.addStackTraceTests(b, test_filter, modes));
toolchain_step.dependOn(tests.addCliTests(b, test_filter, modes));
toolchain_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes));

View file

@ -149,6 +149,7 @@ fn make(step: *Step) !void {
const cwd = if (self.cwd) |cwd| self.builder.pathFromRoot(cwd) else self.builder.build_root;
var argv_list = ArrayList([]const u8).init(self.builder.allocator);
for (self.argv.items) |arg| {
switch (arg) {
.bytes => |bytes| try argv_list.append(bytes),

52
test/link.zig Normal file
View file

@ -0,0 +1,52 @@
const std = @import("std");
const builtin = @import("builtin");
const tests = @import("tests.zig");
pub fn addCases(cases: *tests.StandaloneContext) void {
cases.addBuildFile("test/link/bss/build.zig", .{
.build_modes = false, // we only guarantee zerofill for undefined in Debug
});
cases.addBuildFile("test/link/dylib/build.zig", .{
.build_modes = true,
});
cases.addBuildFile("test/link/common_symbols/build.zig", .{
.build_modes = true,
});
cases.addBuildFile("test/link/common_symbols_alignment/build.zig", .{
.build_modes = true,
});
cases.addBuildFile("test/link/interdependent_static_c_libs/build.zig", .{
.build_modes = true,
});
cases.addBuildFile("test/link/static_lib_as_system_lib/build.zig", .{
.build_modes = true,
});
cases.addBuildFile("test/link/tls/build.zig", .{
.build_modes = true,
});
if (builtin.os.tag == .macos) {
cases.addBuildFile("test/link/frameworks/build.zig", .{
.build_modes = true,
.requires_macos_sdk = true,
});
// Try to build and run an Objective-C executable.
cases.addBuildFile("test/link/objc/build.zig", .{
.build_modes = true,
.requires_macos_sdk = true,
});
// Try to build and run an Objective-C++ executable.
cases.addBuildFile("test/link/objcpp/build.zig", .{
.build_modes = true,
.requires_macos_sdk = true,
});
}
}

14
test/link/bss/build.zig Normal file
View file

@ -0,0 +1,14 @@
const Builder = @import("std").build.Builder;
pub fn build(b: *Builder) void {
const mode = b.standardReleaseOptions();
const test_step = b.step("test", "Test");
const exe = b.addExecutable("bss", "main.zig");
b.default_step.dependOn(&exe.step);
exe.setBuildMode(mode);
const run = exe.run();
run.expectStdOutEqual("0, 1, 0\n");
test_step.dependOn(&run.step);
}

13
test/link/bss/main.zig Normal file
View file

@ -0,0 +1,13 @@
const std = @import("std");
// Stress test zerofill layout
var buffer: [0x1000000]u64 = undefined;
pub fn main() anyerror!void {
buffer[0x10] = 1;
try std.io.getStdOut().writer().print("{d}, {d}, {d}\n", .{
buffer[0],
buffer[0x10],
buffer[0x1000000 - 1],
});
}

7
test/link/dylib/a.c Normal file
View file

@ -0,0 +1,7 @@
#include <stdio.h>
char world[] = "world";
char* hello() {
return "Hello";
}

29
test/link/dylib/build.zig Normal file
View file

@ -0,0 +1,29 @@
const std = @import("std");
const Builder = std.build.Builder;
pub fn build(b: *Builder) void {
const mode = b.standardReleaseOptions();
const test_step = b.step("test", "Test");
const dylib = b.addSharedLibrary("a", null, b.version(1, 0, 0));
dylib.setBuildMode(mode);
dylib.addCSourceFile("a.c", &.{});
dylib.linkLibC();
dylib.install();
const exe = b.addExecutable("main", null);
exe.setBuildMode(mode);
exe.addCSourceFile("main.c", &.{});
exe.linkSystemLibrary("a");
exe.linkLibC();
exe.addLibraryPath(b.pathFromRoot("zig-out/lib/"));
exe.addRPath(b.pathFromRoot("zig-out/lib"));
const run = exe.run();
run.cwd = b.pathFromRoot(".");
run.expectStdOutEqual("Hello world");
test_step.dependOn(b.getInstallStep());
test_step.dependOn(&run.step);
}

9
test/link/dylib/main.c Normal file
View file

@ -0,0 +1,9 @@
#include <stdio.h>
char* hello();
extern char world[];
int main() {
printf("%s %s", hello(), world);
return 0;
}

View file

@ -1,19 +1,8 @@
const std = @import("std");
const Builder = std.build.Builder;
const CrossTarget = std.zig.CrossTarget;
fn isRunnableTarget(t: CrossTarget) bool {
// TODO I think we might be able to run this on Linux via Darling.
// Add a check for that here, and return true if Darling is available.
if (t.isNative() and t.getOsTag() == .macos)
return true
else
return false;
}
pub fn build(b: *Builder) void {
const mode = b.standardReleaseOptions();
const target = b.standardTargetOptions(.{});
const test_step = b.step("test", "Test the program");
@ -21,14 +10,11 @@ pub fn build(b: *Builder) void {
b.default_step.dependOn(&exe.step);
exe.addCSourceFile("main.c", &[0][]const u8{});
exe.setBuildMode(mode);
exe.setTarget(target);
exe.linkLibC();
// TODO when we figure out how to ship framework stubs for cross-compilation,
// populate paths to the sysroot here.
exe.linkFramework("Cocoa");
if (isRunnableTarget(target)) {
const run_cmd = exe.run();
test_step.dependOn(&run_cmd.step);
}
const run_cmd = exe.run();
test_step.dependOn(&run_cmd.step);
}

View file

@ -1,19 +1,8 @@
const std = @import("std");
const Builder = std.build.Builder;
const CrossTarget = std.zig.CrossTarget;
fn isRunnableTarget(t: CrossTarget) bool {
// TODO I think we might be able to run this on Linux via Darling.
// Add a check for that here, and return true if Darling is available.
if (t.isNative() and t.getOsTag() == .macos)
return true
else
return false;
}
pub fn build(b: *Builder) void {
const mode = b.standardReleaseOptions();
const target = b.standardTargetOptions(.{});
const test_step = b.step("test", "Test the program");
@ -23,14 +12,11 @@ pub fn build(b: *Builder) void {
exe.addCSourceFile("Foo.m", &[0][]const u8{});
exe.addCSourceFile("test.m", &[0][]const u8{});
exe.setBuildMode(mode);
exe.setTarget(target);
exe.linkLibC();
// TODO when we figure out how to ship framework stubs for cross-compilation,
// populate paths to the sysroot here.
exe.linkFramework("Foundation");
if (isRunnableTarget(target)) {
const run_cmd = exe.run();
test_step.dependOn(&run_cmd.step);
}
const run_cmd = exe.run();
test_step.dependOn(&run_cmd.step);
}

View file

@ -1,19 +1,8 @@
const std = @import("std");
const Builder = std.build.Builder;
const CrossTarget = std.zig.CrossTarget;
fn isRunnableTarget(t: CrossTarget) bool {
// TODO I think we might be able to run this on Linux via Darling.
// Add a check for that here, and return true if Darling is available.
if (t.isNative() and t.getOsTag() == .macos)
return true
else
return false;
}
pub fn build(b: *Builder) void {
const mode = b.standardReleaseOptions();
const target = b.standardTargetOptions(.{});
const test_step = b.step("test", "Test the program");
@ -23,14 +12,13 @@ pub fn build(b: *Builder) void {
exe.addCSourceFile("Foo.mm", &[0][]const u8{});
exe.addCSourceFile("test.mm", &[0][]const u8{});
exe.setBuildMode(mode);
exe.setTarget(target);
exe.linkLibCpp();
// TODO when we figure out how to ship framework stubs for cross-compilation,
// populate paths to the sysroot here.
exe.linkFramework("Foundation");
if (isRunnableTarget(target)) {
const run_cmd = exe.run();
test_step.dependOn(&run_cmd.step);
}
const run_cmd = exe.run();
run_cmd.expectStdOutEqual("Hello from C++ and Zig");
test_step.dependOn(&run_cmd.step);
}

5
test/link/tls/a.c Normal file
View file

@ -0,0 +1,5 @@
_Thread_local int a;
int getA() {
return a;
}

View file

@ -6,10 +6,12 @@ pub fn build(b: *Builder) void {
const lib = b.addSharedLibrary("a", null, b.version(1, 0, 0));
lib.setBuildMode(mode);
lib.addCSourceFile("a.c", &.{});
lib.linkLibC();
const test_exe = b.addTest("main.zig");
test_exe.setBuildMode(mode);
test_exe.linkLibrary(lib);
test_exe.linkLibC();
const test_step = b.step("test", "Test it");
test_step.dependOn(&test_exe.step);

15
test/link/tls/main.zig Normal file
View file

@ -0,0 +1,15 @@
const std = @import("std");
extern threadlocal var a: i32;
extern fn getA() i32;
fn getA2() i32 {
return a;
}
test {
a = 2;
try std.testing.expect(getA() == 2);
try std.testing.expect(2 == getA2());
try std.testing.expect(getA() == getA2());
}

View file

@ -13,31 +13,12 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
cases.addBuildFile("test/standalone/main_pkg_path/build.zig", .{});
cases.addBuildFile("test/standalone/shared_library/build.zig", .{});
cases.addBuildFile("test/standalone/mix_o_files/build.zig", .{});
if (builtin.os.tag == .macos) {
// Zig's macOS linker does not yet support LTO for LLVM IR files:
// https://github.com/ziglang/zig/issues/8680
cases.addBuildFile("test/standalone/mix_c_files/build.zig", .{
.build_modes = false,
.cross_targets = true,
});
} else {
cases.addBuildFile("test/standalone/mix_c_files/build.zig", .{
.build_modes = true,
.cross_targets = true,
});
}
cases.addBuildFile("test/standalone/mix_c_files/build.zig", .{
.build_modes = true,
.cross_targets = true,
});
cases.addBuildFile("test/standalone/global_linkage/build.zig", .{});
cases.addBuildFile("test/standalone/static_c_lib/build.zig", .{});
cases.addBuildFile("test/standalone/link_interdependent_static_c_libs/build.zig", .{});
cases.addBuildFile("test/standalone/link_static_lib_as_system_lib/build.zig", .{});
cases.addBuildFile("test/standalone/link_common_symbols/build.zig", .{});
cases.addBuildFile("test/standalone/link_frameworks/build.zig", .{
.requires_macos_sdk = true,
});
cases.addBuildFile("test/standalone/link_common_symbols_alignment/build.zig", .{});
if (builtin.os.tag == .macos) {
cases.addBuildFile("test/standalone/link_import_tls_dylib/build.zig", .{});
}
cases.addBuildFile("test/standalone/issue_339/build.zig", .{});
cases.addBuildFile("test/standalone/issue_8550/build.zig", .{});
cases.addBuildFile("test/standalone/issue_794/build.zig", .{});
@ -69,16 +50,6 @@ pub fn addCases(cases: *tests.StandaloneContext) void {
if (builtin.os.tag == .linux) {
cases.addBuildFile("test/standalone/pie/build.zig", .{});
}
// Try to build and run an Objective-C executable.
cases.addBuildFile("test/standalone/objc/build.zig", .{
.build_modes = true,
.requires_macos_sdk = true,
});
// Try to build and run an Objective-C++ executable.
cases.addBuildFile("test/standalone/objcpp/build.zig", .{
.build_modes = true,
.requires_macos_sdk = true,
});
// Ensure the development tools are buildable.
cases.add("tools/gen_spirv_spec.zig");

View file

@ -1 +0,0 @@
_Thread_local int a;

View file

@ -1,7 +0,0 @@
const std = @import("std");
extern threadlocal var a: i32;
test {
try std.testing.expect(a == 0);
}

View file

@ -21,6 +21,7 @@ const assemble_and_link = @import("assemble_and_link.zig");
const translate_c = @import("translate_c.zig");
const run_translated_c = @import("run_translated_c.zig");
const gen_h = @import("gen_h.zig");
const link = @import("link.zig");
// Implementations
pub const TranslateCContext = @import("src/translate_c.zig").TranslateCContext;
@ -479,6 +480,27 @@ pub fn addStandaloneTests(
return cases.step;
}
pub fn addLinkTests(
b: *build.Builder,
test_filter: ?[]const u8,
modes: []const Mode,
enable_macos_sdk: bool,
) *build.Step {
const cases = b.allocator.create(StandaloneContext) catch unreachable;
cases.* = StandaloneContext{
.b = b,
.step = b.step("test-link", "Run the linker tests"),
.test_index = 0,
.test_filter = test_filter,
.modes = modes,
.skip_non_native = true,
.enable_macos_sdk = enable_macos_sdk,
.target = .{},
};
link.addCases(cases);
return cases.step;
}
pub fn addCliTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
_ = test_filter;
_ = modes;