| ... | @@ -83,6 +83,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { | ... | @@ -83,6 +83,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { |
| 83 | macho_step.dependOn(testDeadStripDylibs(b, .{ .target = b.host })); | 83 | macho_step.dependOn(testDeadStripDylibs(b, .{ .target = b.host })); |
| 84 | macho_step.dependOn(testHeaderpad(b, .{ .target = b.host })); | 84 | macho_step.dependOn(testHeaderpad(b, .{ .target = b.host })); |
| 85 | macho_step.dependOn(testLinkDirectlyCppTbd(b, .{ .target = b.host })); | 85 | macho_step.dependOn(testLinkDirectlyCppTbd(b, .{ .target = b.host })); |
| | 86 | macho_step.dependOn(testMergeLiteralsObjc(b, .{ .target = b.host })); |
| 86 | macho_step.dependOn(testNeededFramework(b, .{ .target = b.host })); | 87 | macho_step.dependOn(testNeededFramework(b, .{ .target = b.host })); |
| 87 | macho_step.dependOn(testObjc(b, .{ .target = b.host })); | 88 | macho_step.dependOn(testObjc(b, .{ .target = b.host })); |
| 88 | macho_step.dependOn(testObjcpp(b, .{ .target = b.host })); | 89 | macho_step.dependOn(testObjcpp(b, .{ .target = b.host })); |
| ... | @@ -1125,6 +1126,96 @@ fn testMergeLiterals2(b: *Build, opts: Options) *Step { | ... | @@ -1125,6 +1126,96 @@ fn testMergeLiterals2(b: *Build, opts: Options) *Step { |
| 1125 | return test_step; | 1126 | return test_step; |
| 1126 | } | 1127 | } |
| 1127 | | 1128 | |
| | 1129 | fn testMergeLiteralsObjc(b: *Build, opts: Options) *Step { |
| | 1130 | const test_step = addTestStep(b, "merge-literals-objc", opts); |
| | 1131 | |
| | 1132 | const main_o = addObject(b, opts, .{ .name = "main", .objc_source_bytes = |
| | 1133 | \\#import <Foundation/Foundation.h>; |
| | 1134 | \\ |
| | 1135 | \\extern void foo(); |
| | 1136 | \\ |
| | 1137 | \\int main() { |
| | 1138 | \\ NSString *thing = @"aaa"; |
| | 1139 | \\ |
| | 1140 | \\ SEL sel = @selector(lowercaseString); |
| | 1141 | \\ NSString *lower = (([thing respondsToSelector:sel]) ? @"YES" : @"NO"); |
| | 1142 | \\ NSLog (@"Responds to lowercaseString: %@", lower); |
| | 1143 | \\ if ([thing respondsToSelector:sel]) //(lower == @"YES") |
| | 1144 | \\ NSLog(@"lowercaseString is: %@", [thing lowercaseString]); |
| | 1145 | \\ |
| | 1146 | \\ foo(); |
| | 1147 | \\} |
| | 1148 | }); |
| | 1149 | |
| | 1150 | const a_o = addObject(b, opts, .{ .name = "a", .objc_source_bytes = |
| | 1151 | \\#import <Foundation/Foundation.h>; |
| | 1152 | \\ |
| | 1153 | \\void foo() { |
| | 1154 | \\ NSString *thing = @"aaa"; |
| | 1155 | \\ SEL sel = @selector(lowercaseString); |
| | 1156 | \\ NSString *lower = (([thing respondsToSelector:sel]) ? @"YES" : @"NO"); |
| | 1157 | \\ NSLog (@"Responds to lowercaseString in foo(): %@", lower); |
| | 1158 | \\ if ([thing respondsToSelector:sel]) //(lower == @"YES") |
| | 1159 | \\ NSLog(@"lowercaseString in foo() is: %@", [thing lowercaseString]); |
| | 1160 | \\ SEL sel2 = @selector(uppercaseString); |
| | 1161 | \\ NSString *upper = (([thing respondsToSelector:sel2]) ? @"YES" : @"NO"); |
| | 1162 | \\ NSLog (@"Responds to uppercaseString in foo(): %@", upper); |
| | 1163 | \\ if ([thing respondsToSelector:sel2]) //(upper == @"YES") |
| | 1164 | \\ NSLog(@"uppercaseString in foo() is: %@", [thing uppercaseString]); |
| | 1165 | \\} |
| | 1166 | }); |
| | 1167 | |
| | 1168 | const runWithChecks = struct { |
| | 1169 | fn runWithChecks(step: *Step, exe: *Compile) void { |
| | 1170 | const builder = step.owner; |
| | 1171 | const run = addRunArtifact(exe); |
| | 1172 | run.addCheck(.{ .expect_stderr_match = builder.dupe("Responds to lowercaseString: YES") }); |
| | 1173 | run.addCheck(.{ .expect_stderr_match = builder.dupe("lowercaseString is: aaa") }); |
| | 1174 | run.addCheck(.{ .expect_stderr_match = builder.dupe("Responds to lowercaseString in foo(): YES") }); |
| | 1175 | run.addCheck(.{ .expect_stderr_match = builder.dupe("lowercaseString in foo() is: aaa") }); |
| | 1176 | run.addCheck(.{ .expect_stderr_match = builder.dupe("Responds to uppercaseString in foo(): YES") }); |
| | 1177 | run.addCheck(.{ .expect_stderr_match = builder.dupe("uppercaseString in foo() is: AAA") }); |
| | 1178 | step.dependOn(&run.step); |
| | 1179 | |
| | 1180 | const check = exe.checkObject(); |
| | 1181 | check.dumpSection("__TEXT,__objc_methname"); |
| | 1182 | check.checkContains("lowercaseString\x00"); |
| | 1183 | check.dumpSection("__TEXT,__objc_methname"); |
| | 1184 | check.checkContains("uppercaseString\x00"); |
| | 1185 | step.dependOn(&check.step); |
| | 1186 | } |
| | 1187 | }.runWithChecks; |
| | 1188 | |
| | 1189 | { |
| | 1190 | const exe = addExecutable(b, opts, .{ .name = "main1" }); |
| | 1191 | exe.addObject(main_o); |
| | 1192 | exe.addObject(a_o); |
| | 1193 | exe.root_module.linkFramework("Foundation", .{}); |
| | 1194 | runWithChecks(test_step, exe); |
| | 1195 | } |
| | 1196 | |
| | 1197 | { |
| | 1198 | const exe = addExecutable(b, opts, .{ .name = "main2" }); |
| | 1199 | exe.addObject(a_o); |
| | 1200 | exe.addObject(main_o); |
| | 1201 | exe.root_module.linkFramework("Foundation", .{}); |
| | 1202 | runWithChecks(test_step, exe); |
| | 1203 | } |
| | 1204 | |
| | 1205 | { |
| | 1206 | const b_o = addObject(b, opts, .{ .name = "b" }); |
| | 1207 | b_o.addObject(a_o); |
| | 1208 | b_o.addObject(main_o); |
| | 1209 | |
| | 1210 | const exe = addExecutable(b, opts, .{ .name = "main3" }); |
| | 1211 | exe.addObject(b_o); |
| | 1212 | exe.root_module.linkFramework("Foundation", .{}); |
| | 1213 | runWithChecks(test_step, exe); |
| | 1214 | } |
| | 1215 | |
| | 1216 | return test_step; |
| | 1217 | } |
| | 1218 | |
| 1128 | fn testMhExecuteHeader(b: *Build, opts: Options) *Step { | 1219 | fn testMhExecuteHeader(b: *Build, opts: Options) *Step { |
| 1129 | const test_step = addTestStep(b, "mh-execute-header", opts); | 1220 | const test_step = addTestStep(b, "mh-execute-header", opts); |
| 1130 | | 1221 | |