| ... | @@ -23,6 +23,8 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { | ... | @@ -23,6 +23,8 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { |
| 23 | macho_step.dependOn(testHelloZig(b, .{ .target = default_target })); | 23 | macho_step.dependOn(testHelloZig(b, .{ .target = default_target })); |
| 24 | macho_step.dependOn(testLargeBss(b, .{ .target = default_target })); | 24 | macho_step.dependOn(testLargeBss(b, .{ .target = default_target })); |
| 25 | macho_step.dependOn(testMhExecuteHeader(b, .{ .target = default_target })); | 25 | macho_step.dependOn(testMhExecuteHeader(b, .{ .target = default_target })); |
| | 26 | macho_step.dependOn(testRelocatable(b, .{ .target = default_target })); |
| | 27 | macho_step.dependOn(testRelocatableZig(b, .{ .target = default_target })); |
| 26 | macho_step.dependOn(testSectionBoundarySymbols(b, .{ .target = default_target })); | 28 | macho_step.dependOn(testSectionBoundarySymbols(b, .{ .target = default_target })); |
| 27 | macho_step.dependOn(testSegmentBoundarySymbols(b, .{ .target = default_target })); | 29 | macho_step.dependOn(testSegmentBoundarySymbols(b, .{ .target = default_target })); |
| 28 | macho_step.dependOn(testTentative(b, .{ .target = default_target })); | 30 | macho_step.dependOn(testTentative(b, .{ .target = default_target })); |
| ... | @@ -498,6 +500,125 @@ fn testNeededLibrary(b: *Build, opts: Options) *Step { | ... | @@ -498,6 +500,125 @@ fn testNeededLibrary(b: *Build, opts: Options) *Step { |
| 498 | return test_step; | 500 | return test_step; |
| 499 | } | 501 | } |
| 500 | | 502 | |
| | 503 | fn testRelocatable(b: *Build, opts: Options) *Step { |
| | 504 | const test_step = addTestStep(b, "macho-relocatable", opts); |
| | 505 | |
| | 506 | const a_o = addObject(b, opts, .{ .name = "a", .cpp_source_bytes = |
| | 507 | \\#include <stdexcept> |
| | 508 | \\int try_me() { |
| | 509 | \\ throw std::runtime_error("Oh no!"); |
| | 510 | \\} |
| | 511 | }); |
| | 512 | a_o.linkLibCpp(); |
| | 513 | |
| | 514 | const b_o = addObject(b, opts, .{ .name = "b", .cpp_source_bytes = |
| | 515 | \\extern int try_me(); |
| | 516 | \\int try_again() { |
| | 517 | \\ return try_me(); |
| | 518 | \\} |
| | 519 | }); |
| | 520 | |
| | 521 | const main_o = addObject(b, opts, .{ .name = "main", .cpp_source_bytes = |
| | 522 | \\#include <iostream> |
| | 523 | \\#include <stdexcept> |
| | 524 | \\extern int try_again(); |
| | 525 | \\int main() { |
| | 526 | \\ try { |
| | 527 | \\ try_again(); |
| | 528 | \\ } catch (const std::exception &e) { |
| | 529 | \\ std::cout << "exception=" << e.what(); |
| | 530 | \\ } |
| | 531 | \\ return 0; |
| | 532 | \\} |
| | 533 | }); |
| | 534 | main_o.linkLibCpp(); |
| | 535 | |
| | 536 | const exp_stdout = "exception=Oh no!"; |
| | 537 | |
| | 538 | { |
| | 539 | const c_o = addObject(b, opts, .{ .name = "c" }); |
| | 540 | c_o.addObject(a_o); |
| | 541 | c_o.addObject(b_o); |
| | 542 | |
| | 543 | const exe = addExecutable(b, opts, .{ .name = "main1" }); |
| | 544 | exe.addObject(main_o); |
| | 545 | exe.addObject(c_o); |
| | 546 | exe.linkLibCpp(); |
| | 547 | |
| | 548 | const run = addRunArtifact(exe); |
| | 549 | run.expectStdOutEqual(exp_stdout); |
| | 550 | test_step.dependOn(&run.step); |
| | 551 | } |
| | 552 | |
| | 553 | { |
| | 554 | const d_o = addObject(b, opts, .{ .name = "d" }); |
| | 555 | d_o.addObject(a_o); |
| | 556 | d_o.addObject(b_o); |
| | 557 | d_o.addObject(main_o); |
| | 558 | |
| | 559 | const exe = addExecutable(b, opts, .{ .name = "main2" }); |
| | 560 | exe.addObject(d_o); |
| | 561 | exe.linkLibCpp(); |
| | 562 | |
| | 563 | const run = addRunArtifact(exe); |
| | 564 | run.expectStdOutEqual(exp_stdout); |
| | 565 | test_step.dependOn(&run.step); |
| | 566 | } |
| | 567 | |
| | 568 | return test_step; |
| | 569 | } |
| | 570 | |
| | 571 | fn testRelocatableZig(b: *Build, opts: Options) *Step { |
| | 572 | const test_step = addTestStep(b, "macho-relocatable-zig", opts); |
| | 573 | |
| | 574 | const a_o = addObject(b, opts, .{ .name = "a", .zig_source_bytes = |
| | 575 | \\const std = @import("std"); |
| | 576 | \\export var foo: i32 = 0; |
| | 577 | \\export fn incrFoo() void { |
| | 578 | \\ foo += 1; |
| | 579 | \\ std.debug.print("incrFoo={d}\n", .{foo}); |
| | 580 | \\} |
| | 581 | }); |
| | 582 | |
| | 583 | const b_o = addObject(b, opts, .{ .name = "b", .zig_source_bytes = |
| | 584 | \\const std = @import("std"); |
| | 585 | \\extern var foo: i32; |
| | 586 | \\export fn decrFoo() void { |
| | 587 | \\ foo -= 1; |
| | 588 | \\ std.debug.print("decrFoo={d}\n", .{foo}); |
| | 589 | \\} |
| | 590 | }); |
| | 591 | |
| | 592 | const main_o = addObject(b, opts, .{ .name = "main", .zig_source_bytes = |
| | 593 | \\const std = @import("std"); |
| | 594 | \\extern var foo: i32; |
| | 595 | \\extern fn incrFoo() void; |
| | 596 | \\extern fn decrFoo() void; |
| | 597 | \\pub fn main() void { |
| | 598 | \\ const init = foo; |
| | 599 | \\ incrFoo(); |
| | 600 | \\ decrFoo(); |
| | 601 | \\ if (init == foo) @panic("Oh no!"); |
| | 602 | \\} |
| | 603 | }); |
| | 604 | |
| | 605 | const c_o = addObject(b, opts, .{ .name = "c" }); |
| | 606 | c_o.addObject(a_o); |
| | 607 | c_o.addObject(b_o); |
| | 608 | c_o.addObject(main_o); |
| | 609 | |
| | 610 | const exe = addExecutable(b, opts, .{ .name = "main" }); |
| | 611 | exe.addObject(c_o); |
| | 612 | |
| | 613 | const run = addRunArtifact(exe); |
| | 614 | run.addCheck(.{ .expect_stderr_match = b.dupe("incrFoo=1") }); |
| | 615 | run.addCheck(.{ .expect_stderr_match = b.dupe("decrFoo=1") }); |
| | 616 | run.addCheck(.{ .expect_stderr_match = b.dupe("panic: Oh no!") }); |
| | 617 | test_step.dependOn(&run.step); |
| | 618 | |
| | 619 | return test_step; |
| | 620 | } |
| | 621 | |
| 501 | fn testSectionBoundarySymbols(b: *Build, opts: Options) *Step { | 622 | fn testSectionBoundarySymbols(b: *Build, opts: Options) *Step { |
| 502 | const test_step = addTestStep(b, "macho-section-boundary-symbols", opts); | 623 | const test_step = addTestStep(b, "macho-section-boundary-symbols", opts); |
| 503 | | 624 | |