| ... | @@ -1,7 +1,7 @@ | ... | @@ -1,7 +1,7 @@ |
| 1 | //! Here we test our MachO linker for correctness and functionality. | 1 | //! Here we test our MachO linker for correctness and functionality. |
| 2 | //! TODO migrate standalone tests from test/link/macho/* to here. | 2 | //! TODO migrate standalone tests from test/link/macho/* to here. |
| 3 | | 3 | |
| 4 | pub fn testAll(b: *std.Build, build_opts: BuildOptions) *Step { | 4 | pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { |
| 5 | const macho_step = b.step("test-macho", "Run MachO tests"); | 5 | const macho_step = b.step("test-macho", "Run MachO tests"); |
| 6 | | 6 | |
| 7 | const default_target = b.resolveTargetQuery(.{ | 7 | const default_target = b.resolveTargetQuery(.{ |
| ... | @@ -13,15 +13,20 @@ pub fn testAll(b: *std.Build, build_opts: BuildOptions) *Step { | ... | @@ -13,15 +13,20 @@ pub fn testAll(b: *std.Build, build_opts: BuildOptions) *Step { |
| 13 | macho_step.dependOn(testSectionBoundarySymbols(b, .{ .target = default_target })); | 13 | macho_step.dependOn(testSectionBoundarySymbols(b, .{ .target = default_target })); |
| 14 | macho_step.dependOn(testSegmentBoundarySymbols(b, .{ .target = default_target })); | 14 | macho_step.dependOn(testSegmentBoundarySymbols(b, .{ .target = default_target })); |
| 15 | | 15 | |
| 16 | // Tests requiring presence of macOS SDK in system path | 16 | // Tests requiring symlinks when tested on Windows |
| 17 | if (build_opts.has_macos_sdk and build_opts.has_symlinks_windows) { | 17 | if (build_opts.has_symlinks_windows) { |
| 18 | macho_step.dependOn(testNeededFramework(b, .{ .target = b.host })); | 18 | macho_step.dependOn(testNeededLibrary(b, .{ .target = default_target })); |
| | 19 | |
| | 20 | // Tests requiring presence of macOS SDK in system path |
| | 21 | if (build_opts.has_macos_sdk) { |
| | 22 | macho_step.dependOn(testNeededFramework(b, .{ .target = b.host })); |
| | 23 | } |
| 19 | } | 24 | } |
| 20 | | 25 | |
| 21 | return macho_step; | 26 | return macho_step; |
| 22 | } | 27 | } |
| 23 | | 28 | |
| 24 | fn testDeadStrip(b: *std.Build, opts: Options) *Step { | 29 | fn testDeadStrip(b: *Build, opts: Options) *Step { |
| 25 | const test_step = addTestStep(b, "macho-dead-strip", opts); | 30 | const test_step = addTestStep(b, "macho-dead-strip", opts); |
| 26 | | 31 | |
| 27 | const obj = addObject(b, opts, .{ .name = "a", .cpp_source_bytes = | 32 | const obj = addObject(b, opts, .{ .name = "a", .cpp_source_bytes = |
| ... | @@ -102,7 +107,7 @@ fn testDeadStrip(b: *std.Build, opts: Options) *Step { | ... | @@ -102,7 +107,7 @@ fn testDeadStrip(b: *std.Build, opts: Options) *Step { |
| 102 | return test_step; | 107 | return test_step; |
| 103 | } | 108 | } |
| 104 | | 109 | |
| 105 | fn testEntryPointDylib(b: *std.Build, opts: Options) *Step { | 110 | fn testEntryPointDylib(b: *Build, opts: Options) *Step { |
| 106 | const test_step = addTestStep(b, "macho-entry-point-dylib", opts); | 111 | const test_step = addTestStep(b, "macho-entry-point-dylib", opts); |
| 107 | | 112 | |
| 108 | const dylib = addSharedLibrary(b, opts, .{ .name = "a" }); | 113 | const dylib = addSharedLibrary(b, opts, .{ .name = "a" }); |
| ... | @@ -156,11 +161,11 @@ fn testEntryPointDylib(b: *std.Build, opts: Options) *Step { | ... | @@ -156,11 +161,11 @@ fn testEntryPointDylib(b: *std.Build, opts: Options) *Step { |
| 156 | return test_step; | 161 | return test_step; |
| 157 | } | 162 | } |
| 158 | | 163 | |
| 159 | fn testNeededFramework(b: *std.Build, opts: Options) *Step { | 164 | fn testNeededFramework(b: *Build, opts: Options) *Step { |
| 160 | const test_step = addTestStep(b, "macho-needed-framework", opts); | 165 | const test_step = addTestStep(b, "macho-needed-framework", opts); |
| 161 | | 166 | |
| 162 | const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = "int main() { return 0; }" }); | 167 | const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = "int main() { return 0; }" }); |
| 163 | exe.linkFrameworkNeeded("Cocoa"); | 168 | exe.root_module.linkFramework("Cocoa", .{ .needed = true }); |
| 164 | exe.dead_strip_dylibs = true; | 169 | exe.dead_strip_dylibs = true; |
| 165 | | 170 | |
| 166 | const check = exe.checkObject(); | 171 | const check = exe.checkObject(); |
| ... | @@ -176,7 +181,31 @@ fn testNeededFramework(b: *std.Build, opts: Options) *Step { | ... | @@ -176,7 +181,31 @@ fn testNeededFramework(b: *std.Build, opts: Options) *Step { |
| 176 | return test_step; | 181 | return test_step; |
| 177 | } | 182 | } |
| 178 | | 183 | |
| 179 | fn testSectionBoundarySymbols(b: *std.Build, opts: Options) *Step { | 184 | fn testNeededLibrary(b: *Build, opts: Options) *Step { |
| | 185 | const test_step = addTestStep(b, "macho-needed-library", opts); |
| | 186 | |
| | 187 | const dylib = addSharedLibrary(b, opts, .{ .name = "a", .c_source_bytes = "int a = 42;" }); |
| | 188 | |
| | 189 | const exe = addExecutable(b, opts, .{ .name = "main", .c_source_bytes = "int main() { return 0; }" }); |
| | 190 | exe.root_module.linkSystemLibrary("a", .{ .needed = true }); |
| | 191 | exe.addLibraryPath(dylib.getEmittedBinDirectory()); |
| | 192 | exe.addRPath(dylib.getEmittedBinDirectory()); |
| | 193 | exe.dead_strip_dylibs = true; |
| | 194 | |
| | 195 | const check = exe.checkObject(); |
| | 196 | check.checkInHeaders(); |
| | 197 | check.checkExact("cmd LOAD_DYLIB"); |
| | 198 | check.checkContains("liba.dylib"); |
| | 199 | test_step.dependOn(&check.step); |
| | 200 | |
| | 201 | const run = addRunArtifact(exe); |
| | 202 | run.expectExitCode(0); |
| | 203 | test_step.dependOn(&run.step); |
| | 204 | |
| | 205 | return test_step; |
| | 206 | } |
| | 207 | |
| | 208 | fn testSectionBoundarySymbols(b: *Build, opts: Options) *Step { |
| 180 | const test_step = addTestStep(b, "macho-section-boundary-symbols", opts); | 209 | const test_step = addTestStep(b, "macho-section-boundary-symbols", opts); |
| 181 | | 210 | |
| 182 | const obj1 = addObject(b, opts, .{ | 211 | const obj1 = addObject(b, opts, .{ |
| ... | @@ -256,7 +285,7 @@ fn testSectionBoundarySymbols(b: *std.Build, opts: Options) *Step { | ... | @@ -256,7 +285,7 @@ fn testSectionBoundarySymbols(b: *std.Build, opts: Options) *Step { |
| 256 | return test_step; | 285 | return test_step; |
| 257 | } | 286 | } |
| 258 | | 287 | |
| 259 | fn testSegmentBoundarySymbols(b: *std.Build, opts: Options) *Step { | 288 | fn testSegmentBoundarySymbols(b: *Build, opts: Options) *Step { |
| 260 | const test_step = addTestStep(b, "macho-segment-boundary-symbols", opts); | 289 | const test_step = addTestStep(b, "macho-segment-boundary-symbols", opts); |
| 261 | | 290 | |
| 262 | const obj1 = addObject(b, opts, .{ .name = "a", .cpp_source_bytes = | 291 | const obj1 = addObject(b, opts, .{ .name = "a", .cpp_source_bytes = |
| ... | @@ -324,7 +353,7 @@ fn testSegmentBoundarySymbols(b: *std.Build, opts: Options) *Step { | ... | @@ -324,7 +353,7 @@ fn testSegmentBoundarySymbols(b: *std.Build, opts: Options) *Step { |
| 324 | return test_step; | 353 | return test_step; |
| 325 | } | 354 | } |
| 326 | | 355 | |
| 327 | fn addTestStep(b: *std.Build, comptime prefix: []const u8, opts: Options) *Step { | 356 | fn addTestStep(b: *Build, comptime prefix: []const u8, opts: Options) *Step { |
| 328 | return link.addTestStep(b, "macho-" ++ prefix, opts); | 357 | return link.addTestStep(b, "macho-" ++ prefix, opts); |
| 329 | } | 358 | } |
| 330 | | 359 | |
| ... | @@ -336,6 +365,8 @@ const addSharedLibrary = link.addSharedLibrary; | ... | @@ -336,6 +365,8 @@ const addSharedLibrary = link.addSharedLibrary; |
| 336 | const expectLinkErrors = link.expectLinkErrors; | 365 | const expectLinkErrors = link.expectLinkErrors; |
| 337 | const link = @import("link.zig"); | 366 | const link = @import("link.zig"); |
| 338 | const std = @import("std"); | 367 | const std = @import("std"); |
| | 368 | |
| | 369 | const Build = std.Build; |
| 339 | const BuildOptions = link.BuildOptions; | 370 | const BuildOptions = link.BuildOptions; |
| 340 | const Options = link.Options; | 371 | const Options = link.Options; |
| 341 | const Step = std.Build.Step; | 372 | const Step = Build.Step; |