authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-26 21:03:38-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-26 21:03:38-07:00
logb6556c944b88726c2bdb34ce72358ade88c5a984
tree426cf861f39fb6e250e581588c33496366a1e68c
parentfe4c348f578903d53c490673b1b1dcf5513ae049

fix another round of regressions in this branch

* std.log: still print error messages in ReleaseSmall builds. - when start code gets an error code from main, it uses std.log.err to report the error. this resulted in a test failure because ReleaseSmall wasn't printing `error: TheErrorCode` when an error was returned from main. But that seems like it should keep working. So I changed the std.log defaults. I plan to follow this up with a proposal to change the names of and reduce the quantity of the log levels. * warning emitted when using -femit-h when using stage1 backend; fatal log message when using -femit-h with self-hosted backend (because the feature is not yet available) * fix double `test-cli` build steps in zig's build.zig * update docgen to use new CLI * translate-c uses `-x c` and generates a temporary basename with a `.h` extension. Otherwise clang reports an error. * --show-builtin implies -fno-emit-bin * restore the compile error for using an extern "c" function without putting -lc on the build line. we have to know about the libc dependency up front. * Fix ReleaseFast and ReleaseSmall getting swapped when passing the value to the stage1 backend. * correct the zig0 CLI usage text. * update test harness code to the new CLI.

13 files changed, 213 insertions(+), 273 deletions(-)

BRANCH_TODO+4-6
...@@ -1,18 +1,15 @@...@@ -1,18 +1,15 @@
1 * restore the legacy -femit-h feature using the stage1 backend1 * MachO LLD linking
2 * tests passing with -Dskip-non-native
3 * `-ftime-report`
4 * -fstack-report print stack size diagnostics\n"
5 * subsystem2 * subsystem
6 * mingw-w643 * mingw-w64
7 * MachO LLD linking
8 * COFF LLD linking4 * COFF LLD linking
9 * WASM LLD linking5 * WASM LLD linking
10 * audit the CLI options for stage26 * audit the CLI options for stage2
11 * audit the base cache hash7 * audit the base cache hash
12 * On operating systems that support it, do an execve for `zig test` and `zig run` rather than child process.8 * On operating systems that support it, do an execve for `zig test` and `zig run` rather than child process.
13 * restore error messages for stage2_add_link_lib
14 * windows CUSTOMBUILD : error : unable to build compiler_rt: FileNotFound [D:\a\1\s\build\zig_install_lib_files.vcxproj]9 * windows CUSTOMBUILD : error : unable to build compiler_rt: FileNotFound [D:\a\1\s\build\zig_install_lib_files.vcxproj]
15 * try building some software with zig cc to make sure it didn't regress10 * try building some software with zig cc to make sure it didn't regress
11 * `-ftime-report`
12 * -fstack-report print stack size diagnostics\n"
1613
17 * implement proper parsing of clang stderr/stdout and exposing compile errors with the Compilation API14 * implement proper parsing of clang stderr/stdout and exposing compile errors with the Compilation API
18 * implement proper parsing of LLD stderr/stdout and exposing compile errors with the Compilation API15 * implement proper parsing of LLD stderr/stdout and exposing compile errors with the Compilation API
...@@ -51,3 +48,4 @@...@@ -51,3 +48,4 @@
51 * update musl.zig static data to use native path separator in static data rather than replacing '/' at runtime48 * update musl.zig static data to use native path separator in static data rather than replacing '/' at runtime
52 * linking hello world with LLD, lld is silently calling exit(1) instead of reporting ok=false. when run standalone the error message is: ld.lld: error: section [index 3] has a sh_offset (0x57000) + sh_size (0x68) that is greater than the file size (0x57060)49 * linking hello world with LLD, lld is silently calling exit(1) instead of reporting ok=false. when run standalone the error message is: ld.lld: error: section [index 3] has a sh_offset (0x57000) + sh_size (0x68) that is greater than the file size (0x57060)
53 * submit PR to godbolt and update the CLI options (see changes to test/cli.zig)50 * submit PR to godbolt and update the CLI options (see changes to test/cli.zig)
51 * make proposal about log levels
build.zig+1-4
...@@ -211,10 +211,7 @@ pub fn build(b: *Builder) !void {...@@ -211,10 +211,7 @@ pub fn build(b: *Builder) !void {
211 test_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes));211 test_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes));
212 test_step.dependOn(tests.addStandaloneTests(b, test_filter, modes));212 test_step.dependOn(tests.addStandaloneTests(b, test_filter, modes));
213 test_step.dependOn(tests.addStackTraceTests(b, test_filter, modes));213 test_step.dependOn(tests.addStackTraceTests(b, test_filter, modes));
214 const test_cli = tests.addCliTests(b, test_filter, modes);214 test_step.dependOn(tests.addCliTests(b, test_filter, modes));
215 const test_cli_step = b.step("test-cli", "Run zig cli tests");
216 test_cli_step.dependOn(test_cli);
217 test_step.dependOn(test_cli);
218 test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes));215 test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes));
219 test_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes));216 test_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes));
220 test_step.dependOn(tests.addTranslateCTests(b, test_filter));217 test_step.dependOn(tests.addTranslateCTests(b, test_filter));
doc/docgen.zig+85-162
...@@ -4,7 +4,7 @@ const io = std.io;...@@ -4,7 +4,7 @@ const io = std.io;
4const fs = std.fs;4const fs = std.fs;
5const process = std.process;5const process = std.process;
6const ChildProcess = std.ChildProcess;6const ChildProcess = std.ChildProcess;
7const warn = std.debug.warn;7const print = std.debug.print;
8const mem = std.mem;8const mem = std.mem;
9const testing = std.testing;9const testing = std.testing;
1010
...@@ -215,23 +215,23 @@ const Tokenizer = struct {...@@ -215,23 +215,23 @@ const Tokenizer = struct {
215fn parseError(tokenizer: *Tokenizer, token: Token, comptime fmt: []const u8, args: anytype) anyerror {215fn parseError(tokenizer: *Tokenizer, token: Token, comptime fmt: []const u8, args: anytype) anyerror {
216 const loc = tokenizer.getTokenLocation(token);216 const loc = tokenizer.getTokenLocation(token);
217 const args_prefix = .{ tokenizer.source_file_name, loc.line + 1, loc.column + 1 };217 const args_prefix = .{ tokenizer.source_file_name, loc.line + 1, loc.column + 1 };
218 warn("{}:{}:{}: error: " ++ fmt ++ "\n", args_prefix ++ args);218 print("{}:{}:{}: error: " ++ fmt ++ "\n", args_prefix ++ args);
219 if (loc.line_start <= loc.line_end) {219 if (loc.line_start <= loc.line_end) {
220 warn("{}\n", .{tokenizer.buffer[loc.line_start..loc.line_end]});220 print("{}\n", .{tokenizer.buffer[loc.line_start..loc.line_end]});
221 {221 {
222 var i: usize = 0;222 var i: usize = 0;
223 while (i < loc.column) : (i += 1) {223 while (i < loc.column) : (i += 1) {
224 warn(" ", .{});224 print(" ", .{});
225 }225 }
226 }226 }
227 {227 {
228 const caret_count = token.end - token.start;228 const caret_count = token.end - token.start;
229 var i: usize = 0;229 var i: usize = 0;
230 while (i < caret_count) : (i += 1) {230 while (i < caret_count) : (i += 1) {
231 warn("~", .{});231 print("~", .{});
232 }232 }
233 }233 }
234 warn("\n", .{});234 print("\n", .{});
235 }235 }
236 return error.ParseError;236 return error.ParseError;
237}237}
...@@ -274,6 +274,7 @@ const Code = struct {...@@ -274,6 +274,7 @@ const Code = struct {
274 link_objects: []const []const u8,274 link_objects: []const []const u8,
275 target_str: ?[]const u8,275 target_str: ?[]const u8,
276 link_libc: bool,276 link_libc: bool,
277 disable_cache: bool,
277278
278 const Id = union(enum) {279 const Id = union(enum) {
279 Test,280 Test,
...@@ -522,6 +523,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {...@@ -522,6 +523,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
522 defer link_objects.deinit();523 defer link_objects.deinit();
523 var target_str: ?[]const u8 = null;524 var target_str: ?[]const u8 = null;
524 var link_libc = false;525 var link_libc = false;
526 var disable_cache = false;
525527
526 const source_token = while (true) {528 const source_token = while (true) {
527 const content_tok = try eatToken(tokenizer, Token.Id.Content);529 const content_tok = try eatToken(tokenizer, Token.Id.Content);
...@@ -532,6 +534,8 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {...@@ -532,6 +534,8 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
532 mode = .ReleaseFast;534 mode = .ReleaseFast;
533 } else if (mem.eql(u8, end_tag_name, "code_release_safe")) {535 } else if (mem.eql(u8, end_tag_name, "code_release_safe")) {
534 mode = .ReleaseSafe;536 mode = .ReleaseSafe;
537 } else if (mem.eql(u8, end_tag_name, "code_disable_cache")) {
538 disable_cache = true;
535 } else if (mem.eql(u8, end_tag_name, "code_link_object")) {539 } else if (mem.eql(u8, end_tag_name, "code_link_object")) {
536 _ = try eatToken(tokenizer, Token.Id.Separator);540 _ = try eatToken(tokenizer, Token.Id.Separator);
537 const obj_tok = try eatToken(tokenizer, Token.Id.TagContent);541 const obj_tok = try eatToken(tokenizer, Token.Id.TagContent);
...@@ -572,6 +576,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {...@@ -572,6 +576,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
572 .link_objects = link_objects.toOwnedSlice(),576 .link_objects = link_objects.toOwnedSlice(),
573 .target_str = target_str,577 .target_str = target_str,
574 .link_libc = link_libc,578 .link_libc = link_libc,
579 .disable_cache = disable_cache,
575 },580 },
576 });581 });
577 tokenizer.code_node_count += 1;582 tokenizer.code_node_count += 1;
...@@ -1032,7 +1037,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any...@@ -1032,7 +1037,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
1032 },1037 },
1033 .Code => |code| {1038 .Code => |code| {
1034 code_progress_index += 1;1039 code_progress_index += 1;
1035 warn("docgen example code {}/{}...", .{ code_progress_index, tokenizer.code_node_count });1040 print("docgen example code {}/{}...", .{ code_progress_index, tokenizer.code_node_count });
10361041
1037 const raw_source = tokenizer.buffer[code.source_token.start..code.source_token.end];1042 const raw_source = tokenizer.buffer[code.source_token.start..code.source_token.end];
1038 const trimmed_raw_source = mem.trim(u8, raw_source, " \n");1043 const trimmed_raw_source = mem.trim(u8, raw_source, " \n");
...@@ -1055,30 +1060,17 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any...@@ -1055,30 +1060,17 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
1055 var build_args = std.ArrayList([]const u8).init(allocator);1060 var build_args = std.ArrayList([]const u8).init(allocator);
1056 defer build_args.deinit();1061 defer build_args.deinit();
1057 try build_args.appendSlice(&[_][]const u8{1062 try build_args.appendSlice(&[_][]const u8{
1058 zig_exe,1063 zig_exe, "build-exe",
1059 "build-exe",1064 "--name", code.name,
1060 tmp_source_file_name,1065 "--color", "on",
1061 "--name",1066 "--enable-cache", tmp_source_file_name,
1062 code.name,
1063 "--color",
1064 "on",
1065 "--cache",
1066 "on",
1067 });1067 });
1068 try out.print("<pre><code class=\"shell\">$ zig build-exe {}.zig", .{code.name});1068 try out.print("<pre><code class=\"shell\">$ zig build-exe {}.zig", .{code.name});
1069 switch (code.mode) {1069 switch (code.mode) {
1070 .Debug => {},1070 .Debug => {},
1071 .ReleaseSafe => {1071 else => {
1072 try build_args.append("--release-safe");1072 try build_args.appendSlice(&[_][]const u8{ "-O", @tagName(code.mode) });
1073 try out.print(" --release-safe", .{});1073 try out.print(" -O {s}", .{@tagName(code.mode)});
1074 },
1075 .ReleaseFast => {
1076 try build_args.append("--release-fast");
1077 try out.print(" --release-fast", .{});
1078 },
1079 .ReleaseSmall => {
1080 try build_args.append("--release-small");
1081 try out.print(" --release-small", .{});
1082 },1074 },
1083 }1075 }
1084 for (code.link_objects) |link_object| {1076 for (code.link_objects) |link_object| {
...@@ -1087,9 +1079,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any...@@ -1087,9 +1079,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
1087 allocator,1079 allocator,
1088 &[_][]const u8{ tmp_dir_name, name_with_ext },1080 &[_][]const u8{ tmp_dir_name, name_with_ext },
1089 );1081 );
1090 try build_args.append("--object");
1091 try build_args.append(full_path_object);1082 try build_args.append(full_path_object);
1092 try out.print(" --object {}", .{name_with_ext});1083 try out.print(" {s}", .{name_with_ext});
1093 }1084 }
1094 if (code.link_libc) {1085 if (code.link_libc) {
1095 try build_args.append("-lc");1086 try build_args.append("-lc");
...@@ -1114,20 +1105,14 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any...@@ -1114,20 +1105,14 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
1114 switch (result.term) {1105 switch (result.term) {
1115 .Exited => |exit_code| {1106 .Exited => |exit_code| {
1116 if (exit_code == 0) {1107 if (exit_code == 0) {
1117 warn("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});1108 print("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});
1118 for (build_args.items) |arg|1109 dumpArgs(build_args.items);
1119 warn("{} ", .{arg})
1120 else
1121 warn("\n", .{});
1122 return parseError(tokenizer, code.source_token, "example incorrectly compiled", .{});1110 return parseError(tokenizer, code.source_token, "example incorrectly compiled", .{});
1123 }1111 }
1124 },1112 },
1125 else => {1113 else => {
1126 warn("{}\nThe following command crashed:\n", .{result.stderr});1114 print("{}\nThe following command crashed:\n", .{result.stderr});
1127 for (build_args.items) |arg|1115 dumpArgs(build_args.items);
1128 warn("{} ", .{arg})
1129 else
1130 warn("\n", .{});
1131 return parseError(tokenizer, code.source_token, "example compile crashed", .{});1116 return parseError(tokenizer, code.source_token, "example compile crashed", .{});
1132 },1117 },
1133 }1118 }
...@@ -1174,11 +1159,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any...@@ -1174,11 +1159,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
1174 switch (result.term) {1159 switch (result.term) {
1175 .Exited => |exit_code| {1160 .Exited => |exit_code| {
1176 if (exit_code == 0) {1161 if (exit_code == 0) {
1177 warn("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});1162 print("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});
1178 for (run_args) |arg|1163 dumpArgs(run_args);
1179 warn("{} ", .{arg})
1180 else
1181 warn("\n", .{});
1182 return parseError(tokenizer, code.source_token, "example incorrectly compiled", .{});1164 return parseError(tokenizer, code.source_token, "example incorrectly compiled", .{});
1183 }1165 }
1184 },1166 },
...@@ -1206,27 +1188,13 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any...@@ -1206,27 +1188,13 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
1206 var test_args = std.ArrayList([]const u8).init(allocator);1188 var test_args = std.ArrayList([]const u8).init(allocator);
1207 defer test_args.deinit();1189 defer test_args.deinit();
12081190
1209 try test_args.appendSlice(&[_][]const u8{1191 try test_args.appendSlice(&[_][]const u8{ zig_exe, "test", tmp_source_file_name });
1210 zig_exe,
1211 "test",
1212 tmp_source_file_name,
1213 "--cache",
1214 "on",
1215 });
1216 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", .{code.name});1192 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", .{code.name});
1217 switch (code.mode) {1193 switch (code.mode) {
1218 .Debug => {},1194 .Debug => {},
1219 .ReleaseSafe => {1195 else => {
1220 try test_args.append("--release-safe");1196 try test_args.appendSlice(&[_][]const u8{ "-O", @tagName(code.mode) });
1221 try out.print(" --release-safe", .{});1197 try out.print(" -O {s}", .{@tagName(code.mode)});
1222 },
1223 .ReleaseFast => {
1224 try test_args.append("--release-fast");
1225 try out.print(" --release-fast", .{});
1226 },
1227 .ReleaseSmall => {
1228 try test_args.append("--release-small");
1229 try out.print(" --release-small", .{});
1230 },1198 },
1231 }1199 }
1232 if (code.link_libc) {1200 if (code.link_libc) {
...@@ -1252,23 +1220,13 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any...@@ -1252,23 +1220,13 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
1252 "--color",1220 "--color",
1253 "on",1221 "on",
1254 tmp_source_file_name,1222 tmp_source_file_name,
1255 "--output-dir",
1256 tmp_dir_name,
1257 });1223 });
1258 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", .{code.name});1224 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", .{code.name});
1259 switch (code.mode) {1225 switch (code.mode) {
1260 .Debug => {},1226 .Debug => {},
1261 .ReleaseSafe => {1227 else => {
1262 try test_args.append("--release-safe");1228 try test_args.appendSlice(&[_][]const u8{ "-O", @tagName(code.mode) });
1263 try out.print(" --release-safe", .{});1229 try out.print(" -O {s}", .{@tagName(code.mode)});
1264 },
1265 .ReleaseFast => {
1266 try test_args.append("--release-fast");
1267 try out.print(" --release-fast", .{});
1268 },
1269 .ReleaseSmall => {
1270 try test_args.append("--release-small");
1271 try out.print(" --release-small", .{});
1272 },1230 },
1273 }1231 }
1274 const result = try ChildProcess.exec(.{1232 const result = try ChildProcess.exec(.{
...@@ -1280,25 +1238,19 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any...@@ -1280,25 +1238,19 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
1280 switch (result.term) {1238 switch (result.term) {
1281 .Exited => |exit_code| {1239 .Exited => |exit_code| {
1282 if (exit_code == 0) {1240 if (exit_code == 0) {
1283 warn("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});1241 print("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});
1284 for (test_args.items) |arg|1242 dumpArgs(test_args.items);
1285 warn("{} ", .{arg})
1286 else
1287 warn("\n", .{});
1288 return parseError(tokenizer, code.source_token, "example incorrectly compiled", .{});1243 return parseError(tokenizer, code.source_token, "example incorrectly compiled", .{});
1289 }1244 }
1290 },1245 },
1291 else => {1246 else => {
1292 warn("{}\nThe following command crashed:\n", .{result.stderr});1247 print("{}\nThe following command crashed:\n", .{result.stderr});
1293 for (test_args.items) |arg|1248 dumpArgs(test_args.items);
1294 warn("{} ", .{arg})
1295 else
1296 warn("\n", .{});
1297 return parseError(tokenizer, code.source_token, "example compile crashed", .{});1249 return parseError(tokenizer, code.source_token, "example compile crashed", .{});
1298 },1250 },
1299 }1251 }
1300 if (mem.indexOf(u8, result.stderr, error_match) == null) {1252 if (mem.indexOf(u8, result.stderr, error_match) == null) {
1301 warn("{}\nExpected to find '{}' in stderr", .{ result.stderr, error_match });1253 print("{}\nExpected to find '{}' in stderr", .{ result.stderr, error_match });
1302 return parseError(tokenizer, code.source_token, "example did not have expected compile error", .{});1254 return parseError(tokenizer, code.source_token, "example did not have expected compile error", .{});
1303 }1255 }
1304 const escaped_stderr = try escapeHtml(allocator, result.stderr);1256 const escaped_stderr = try escapeHtml(allocator, result.stderr);
...@@ -1314,23 +1266,21 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any...@@ -1314,23 +1266,21 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
1314 zig_exe,1266 zig_exe,
1315 "test",1267 "test",
1316 tmp_source_file_name,1268 tmp_source_file_name,
1317 "--output-dir",
1318 tmp_dir_name,
1319 });1269 });
1320 var mode_arg: []const u8 = "";1270 var mode_arg: []const u8 = "";
1321 switch (code.mode) {1271 switch (code.mode) {
1322 .Debug => {},1272 .Debug => {},
1323 .ReleaseSafe => {1273 .ReleaseSafe => {
1324 try test_args.append("--release-safe");1274 try test_args.append("-OReleaseSafe");
1325 mode_arg = " --release-safe";1275 mode_arg = "-OReleaseSafe";
1326 },1276 },
1327 .ReleaseFast => {1277 .ReleaseFast => {
1328 try test_args.append("--release-fast");1278 try test_args.append("-OReleaseFast");
1329 mode_arg = " --release-fast";1279 mode_arg = "-OReleaseFast";
1330 },1280 },
1331 .ReleaseSmall => {1281 .ReleaseSmall => {
1332 try test_args.append("--release-small");1282 try test_args.append("-OReleaseSmall");
1333 mode_arg = " --release-small";1283 mode_arg = "-OReleaseSmall";
1334 },1284 },
1335 }1285 }
13361286
...@@ -1343,25 +1293,19 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any...@@ -1343,25 +1293,19 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
1343 switch (result.term) {1293 switch (result.term) {
1344 .Exited => |exit_code| {1294 .Exited => |exit_code| {
1345 if (exit_code == 0) {1295 if (exit_code == 0) {
1346 warn("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});1296 print("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});
1347 for (test_args.items) |arg|1297 dumpArgs(test_args.items);
1348 warn("{} ", .{arg})
1349 else
1350 warn("\n", .{});
1351 return parseError(tokenizer, code.source_token, "example test incorrectly succeeded", .{});1298 return parseError(tokenizer, code.source_token, "example test incorrectly succeeded", .{});
1352 }1299 }
1353 },1300 },
1354 else => {1301 else => {
1355 warn("{}\nThe following command crashed:\n", .{result.stderr});1302 print("{}\nThe following command crashed:\n", .{result.stderr});
1356 for (test_args.items) |arg|1303 dumpArgs(test_args.items);
1357 warn("{} ", .{arg})
1358 else
1359 warn("\n", .{});
1360 return parseError(tokenizer, code.source_token, "example compile crashed", .{});1304 return parseError(tokenizer, code.source_token, "example compile crashed", .{});
1361 },1305 },
1362 }1306 }
1363 if (mem.indexOf(u8, result.stderr, error_match) == null) {1307 if (mem.indexOf(u8, result.stderr, error_match) == null) {
1364 warn("{}\nExpected to find '{}' in stderr", .{ result.stderr, error_match });1308 print("{}\nExpected to find '{}' in stderr", .{ result.stderr, error_match });
1365 return parseError(tokenizer, code.source_token, "example did not have expected runtime safety error message", .{});1309 return parseError(tokenizer, code.source_token, "example did not have expected runtime safety error message", .{});
1366 }1310 }
1367 const escaped_stderr = try escapeHtml(allocator, result.stderr);1311 const escaped_stderr = try escapeHtml(allocator, result.stderr);
...@@ -1395,32 +1339,20 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any...@@ -1395,32 +1339,20 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
1395 "on",1339 "on",
1396 "--name",1340 "--name",
1397 code.name,1341 code.name,
1398 "--output-dir",1342 try std.fmt.allocPrint(allocator, "-femit-bin={s}{c}{s}", .{
1399 tmp_dir_name,1343 tmp_dir_name, fs.path.sep, name_plus_obj_ext,
1344 }),
1400 });1345 });
1401
1402 if (!code.is_inline) {1346 if (!code.is_inline) {
1403 try out.print("<pre><code class=\"shell\">$ zig build-obj {}.zig", .{code.name});1347 try out.print("<pre><code class=\"shell\">$ zig build-obj {}.zig", .{code.name});
1404 }1348 }
14051349
1406 switch (code.mode) {1350 switch (code.mode) {
1407 .Debug => {},1351 .Debug => {},
1408 .ReleaseSafe => {1352 else => {
1409 try build_args.append("--release-safe");1353 try build_args.appendSlice(&[_][]const u8{ "-O", @tagName(code.mode) });
1410 if (!code.is_inline) {
1411 try out.print(" --release-safe", .{});
1412 }
1413 },
1414 .ReleaseFast => {
1415 try build_args.append("--release-fast");
1416 if (!code.is_inline) {
1417 try out.print(" --release-fast", .{});
1418 }
1419 },
1420 .ReleaseSmall => {
1421 try build_args.append("--release-small");
1422 if (!code.is_inline) {1354 if (!code.is_inline) {
1423 try out.print(" --release-small", .{});1355 try out.print(" -O {s}", .{@tagName(code.mode)});
1424 }1356 }
1425 },1357 },
1426 }1358 }
...@@ -1440,25 +1372,19 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any...@@ -1440,25 +1372,19 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
1440 switch (result.term) {1372 switch (result.term) {
1441 .Exited => |exit_code| {1373 .Exited => |exit_code| {
1442 if (exit_code == 0) {1374 if (exit_code == 0) {
1443 warn("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});1375 print("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});
1444 for (build_args.items) |arg|1376 dumpArgs(build_args.items);
1445 warn("{} ", .{arg})
1446 else
1447 warn("\n", .{});
1448 return parseError(tokenizer, code.source_token, "example build incorrectly succeeded", .{});1377 return parseError(tokenizer, code.source_token, "example build incorrectly succeeded", .{});
1449 }1378 }
1450 },1379 },
1451 else => {1380 else => {
1452 warn("{}\nThe following command crashed:\n", .{result.stderr});1381 print("{}\nThe following command crashed:\n", .{result.stderr});
1453 for (build_args.items) |arg|1382 dumpArgs(build_args.items);
1454 warn("{} ", .{arg})
1455 else
1456 warn("\n", .{});
1457 return parseError(tokenizer, code.source_token, "example compile crashed", .{});1383 return parseError(tokenizer, code.source_token, "example compile crashed", .{});
1458 },1384 },
1459 }1385 }
1460 if (mem.indexOf(u8, result.stderr, error_match) == null) {1386 if (mem.indexOf(u8, result.stderr, error_match) == null) {
1461 warn("{}\nExpected to find '{}' in stderr", .{ result.stderr, error_match });1387 print("{}\nExpected to find '{}' in stderr", .{ result.stderr, error_match });
1462 return parseError(tokenizer, code.source_token, "example did not have expected compile error message", .{});1388 return parseError(tokenizer, code.source_token, "example did not have expected compile error message", .{});
1463 }1389 }
1464 const escaped_stderr = try escapeHtml(allocator, result.stderr);1390 const escaped_stderr = try escapeHtml(allocator, result.stderr);
...@@ -1472,6 +1398,12 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any...@@ -1472,6 +1398,12 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
1472 }1398 }
1473 },1399 },
1474 Code.Id.Lib => {1400 Code.Id.Lib => {
1401 const bin_basename = try std.zig.binNameAlloc(allocator, .{
1402 .root_name = code.name,
1403 .target = std.Target.current,
1404 .output_mode = .Lib,
1405 });
1406
1475 var test_args = std.ArrayList([]const u8).init(allocator);1407 var test_args = std.ArrayList([]const u8).init(allocator);
1476 defer test_args.deinit();1408 defer test_args.deinit();
14771409
...@@ -1479,23 +1411,16 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any...@@ -1479,23 +1411,16 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
1479 zig_exe,1411 zig_exe,
1480 "build-lib",1412 "build-lib",
1481 tmp_source_file_name,1413 tmp_source_file_name,
1482 "--output-dir",1414 try std.fmt.allocPrint(allocator, "-femit-bin={s}{s}{s}", .{
1483 tmp_dir_name,1415 tmp_dir_name, fs.path.sep_str, bin_basename,
1416 }),
1484 });1417 });
1485 try out.print("<pre><code class=\"shell\">$ zig build-lib {}.zig", .{code.name});1418 try out.print("<pre><code class=\"shell\">$ zig build-lib {}.zig", .{code.name});
1486 switch (code.mode) {1419 switch (code.mode) {
1487 .Debug => {},1420 .Debug => {},
1488 .ReleaseSafe => {1421 else => {
1489 try test_args.append("--release-safe");1422 try test_args.appendSlice(&[_][]const u8{ "-O", @tagName(code.mode) });
1490 try out.print(" --release-safe", .{});1423 try out.print(" -O {s}", .{@tagName(code.mode)});
1491 },
1492 .ReleaseFast => {
1493 try test_args.append("--release-fast");
1494 try out.print(" --release-fast", .{});
1495 },
1496 .ReleaseSmall => {
1497 try test_args.append("--release-small");
1498 try out.print(" --release-small", .{});
1499 },1424 },
1500 }1425 }
1501 if (code.target_str) |triple| {1426 if (code.target_str) |triple| {
...@@ -1508,7 +1433,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any...@@ -1508,7 +1433,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
1508 try out.print("\n{}{}</code></pre>\n", .{ escaped_stderr, escaped_stdout });1433 try out.print("\n{}{}</code></pre>\n", .{ escaped_stderr, escaped_stdout });
1509 },1434 },
1510 }1435 }
1511 warn("OK\n", .{});1436 print("OK\n", .{});
1512 },1437 },
1513 }1438 }
1514 }1439 }
...@@ -1524,20 +1449,14 @@ fn exec(allocator: *mem.Allocator, env_map: *std.BufMap, args: []const []const u...@@ -1524,20 +1449,14 @@ fn exec(allocator: *mem.Allocator, env_map: *std.BufMap, args: []const []const u
1524 switch (result.term) {1449 switch (result.term) {
1525 .Exited => |exit_code| {1450 .Exited => |exit_code| {
1526 if (exit_code != 0) {1451 if (exit_code != 0) {
1527 warn("{}\nThe following command exited with code {}:\n", .{ result.stderr, exit_code });1452 print("{}\nThe following command exited with code {}:\n", .{ result.stderr, exit_code });
1528 for (args) |arg|1453 dumpArgs(args);
1529 warn("{} ", .{arg})
1530 else
1531 warn("\n", .{});
1532 return error.ChildExitError;1454 return error.ChildExitError;
1533 }1455 }
1534 },1456 },
1535 else => {1457 else => {
1536 warn("{}\nThe following command crashed:\n", .{result.stderr});1458 print("{}\nThe following command crashed:\n", .{result.stderr});
1537 for (args) |arg|1459 dumpArgs(args);
1538 warn("{} ", .{arg})
1539 else
1540 warn("\n", .{});
1541 return error.ChildCrashed;1460 return error.ChildCrashed;
1542 },1461 },
1543 }1462 }
...@@ -1545,9 +1464,13 @@ fn exec(allocator: *mem.Allocator, env_map: *std.BufMap, args: []const []const u...@@ -1545,9 +1464,13 @@ fn exec(allocator: *mem.Allocator, env_map: *std.BufMap, args: []const []const u
1545}1464}
15461465
1547fn getBuiltinCode(allocator: *mem.Allocator, env_map: *std.BufMap, zig_exe: []const u8) ![]const u8 {1466fn getBuiltinCode(allocator: *mem.Allocator, env_map: *std.BufMap, zig_exe: []const u8) ![]const u8 {
1548 const result = try exec(allocator, env_map, &[_][]const u8{1467 const result = try exec(allocator, env_map, &[_][]const u8{ zig_exe, "build-obj", "--show-builtin" });
1549 zig_exe,
1550 "builtin",
1551 });
1552 return result.stdout;1468 return result.stdout;
1553}1469}
1470
1471fn dumpArgs(args: []const []const u8) void {
1472 for (args) |arg|
1473 print("{} ", .{arg})
1474 else
1475 print("\n", .{});
1476}
doc/langref.html.in+1
...@@ -1078,6 +1078,7 @@ const nan = std.math.nan(f128);...@@ -1078,6 +1078,7 @@ const nan = std.math.nan(f128);
1078 but you can switch to {#syntax#}Optimized{#endsyntax#} mode on a per-block basis:</p>1078 but you can switch to {#syntax#}Optimized{#endsyntax#} mode on a per-block basis:</p>
1079 {#code_begin|obj|foo#}1079 {#code_begin|obj|foo#}
1080 {#code_release_fast#}1080 {#code_release_fast#}
1081 {#code_disable_cache#}
1081const std = @import("std");1082const std = @import("std");
1082const builtin = std.builtin;1083const builtin = std.builtin;
1083const big = @as(f64, 1 << 40);1084const big = @as(f64, 1 << 40);
lib/std/log.zig+3-5
...@@ -101,14 +101,12 @@ pub const Level = enum {...@@ -101,14 +101,12 @@ pub const Level = enum {
101 debug,101 debug,
102};102};
103103
104/// The default log level is based on build mode. Note that in ReleaseSmall104/// The default log level is based on build mode.
105/// builds the default level is emerg but no messages will be stored/logged
106/// by the default logger to save space.
107pub const default_level: Level = switch (builtin.mode) {105pub const default_level: Level = switch (builtin.mode) {
108 .Debug => .debug,106 .Debug => .debug,
109 .ReleaseSafe => .notice,107 .ReleaseSafe => .notice,
110 .ReleaseFast => .err,108 .ReleaseFast => .err,
111 .ReleaseSmall => .emerg,109 .ReleaseSmall => .err,
112};110};
113111
114/// The current log level. This is set to root.log_level if present, otherwise112/// The current log level. This is set to root.log_level if present, otherwise
...@@ -131,7 +129,7 @@ fn log(...@@ -131,7 +129,7 @@ fn log(
131 // On freestanding one must provide a log function; we do not have129 // On freestanding one must provide a log function; we do not have
132 // any I/O configured.130 // any I/O configured.
133 return;131 return;
134 } else if (builtin.mode != .ReleaseSmall) {132 } else {
135 const level_txt = switch (message_level) {133 const level_txt = switch (message_level) {
136 .emerg => "emergency",134 .emerg => "emergency",
137 .alert => "alert",135 .alert => "alert",
src/Compilation.zig+10-3
...@@ -714,6 +714,10 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -714,6 +714,10 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
714 };714 };
715 };715 };
716716
717 if (!use_llvm and options.emit_h != null) {
718 fatal("TODO implement support for -femit-h in the self-hosted backend", .{});
719 }
720
717 const bin_file = try link.File.openPath(gpa, .{721 const bin_file = try link.File.openPath(gpa, .{
718 .emit = bin_file_emit,722 .emit = bin_file_emit,
719 .root_name = root_name,723 .root_name = root_name,
...@@ -1313,13 +1317,13 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {...@@ -1313,13 +1317,13 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
1313 const tmp_dir_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &tmp_digest });1317 const tmp_dir_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &tmp_digest });
1314 var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath(tmp_dir_sub_path, .{});1318 var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath(tmp_dir_sub_path, .{});
1315 defer zig_cache_tmp_dir.close();1319 defer zig_cache_tmp_dir.close();
1316 const cimport_c_basename = "cimport.c";1320 const cimport_basename = "cimport.h";
1317 const out_h_path = try comp.local_cache_directory.join(arena, &[_][]const u8{1321 const out_h_path = try comp.local_cache_directory.join(arena, &[_][]const u8{
1318 tmp_dir_sub_path, cimport_c_basename,1322 tmp_dir_sub_path, cimport_basename,
1319 });1323 });
1320 const out_dep_path = try std.fmt.allocPrint(arena, "{}.d", .{out_h_path});1324 const out_dep_path = try std.fmt.allocPrint(arena, "{}.d", .{out_h_path});
13211325
1322 try zig_cache_tmp_dir.writeFile(cimport_c_basename, c_src);1326 try zig_cache_tmp_dir.writeFile(cimport_basename, c_src);
1323 if (comp.verbose_cimport) {1327 if (comp.verbose_cimport) {
1324 log.info("C import source: {}", .{out_h_path});1328 log.info("C import source: {}", .{out_h_path});
1325 }1329 }
...@@ -2542,6 +2546,9 @@ fn updateStage1Module(comp: *Compilation) !void {...@@ -2542,6 +2546,9 @@ fn updateStage1Module(comp: *Compilation) !void {
2542 });2546 });
2543 break :blk try directory.join(arena, &[_][]const u8{bin_basename});2547 break :blk try directory.join(arena, &[_][]const u8{bin_basename});
2544 } else "";2548 } else "";
2549 if (comp.emit_h != null) {
2550 log.warn("-femit-h is not available in the stage1 backend; no .h file will be produced", .{});
2551 }
2545 const emit_h_path = try stage1LocPath(arena, comp.emit_h, directory);2552 const emit_h_path = try stage1LocPath(arena, comp.emit_h, directory);
2546 const emit_asm_path = try stage1LocPath(arena, comp.emit_asm, directory);2553 const emit_asm_path = try stage1LocPath(arena, comp.emit_asm, directory);
2547 const emit_llvm_ir_path = try stage1LocPath(arena, comp.emit_llvm_ir, directory);2554 const emit_llvm_ir_path = try stage1LocPath(arena, comp.emit_llvm_ir, directory);
src/main.zig+6-59
...@@ -7,16 +7,18 @@ const process = std.process;...@@ -7,16 +7,18 @@ const process = std.process;
7const Allocator = mem.Allocator;7const Allocator = mem.Allocator;
8const ArrayList = std.ArrayList;8const ArrayList = std.ArrayList;
9const ast = std.zig.ast;9const ast = std.zig.ast;
10const warn = std.log.warn;
11
10const Compilation = @import("Compilation.zig");12const Compilation = @import("Compilation.zig");
11const link = @import("link.zig");13const link = @import("link.zig");
12const Package = @import("Package.zig");14const Package = @import("Package.zig");
13const zir = @import("zir.zig");15const zir = @import("zir.zig");
14const build_options = @import("build_options");16const build_options = @import("build_options");
15const warn = std.log.warn;
16const introspect = @import("introspect.zig");17const introspect = @import("introspect.zig");
17const LibCInstallation = @import("libc_installation.zig").LibCInstallation;18const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
18const translate_c = @import("translate_c.zig");19const translate_c = @import("translate_c.zig");
19const Cache = @import("Cache.zig");20const Cache = @import("Cache.zig");
21const target_util = @import("target.zig");
2022
21pub fn fatal(comptime format: []const u8, args: anytype) noreturn {23pub fn fatal(comptime format: []const u8, args: anytype) noreturn {
22 std.log.emerg(format, args);24 std.log.emerg(format, args);
...@@ -773,6 +775,7 @@ fn buildOutputType(...@@ -773,6 +775,7 @@ fn buildOutputType(
773 dll_export_fns = false;775 dll_export_fns = false;
774 } else if (mem.eql(u8, arg, "--show-builtin")) {776 } else if (mem.eql(u8, arg, "--show-builtin")) {
775 show_builtin = true;777 show_builtin = true;
778 emit_bin = .no;
776 } else if (mem.eql(u8, arg, "--strip")) {779 } else if (mem.eql(u8, arg, "--strip")) {
777 strip = true;780 strip = true;
778 } else if (mem.eql(u8, arg, "--single-threaded")) {781 } else if (mem.eql(u8, arg, "--single-threaded")) {
...@@ -1219,12 +1222,12 @@ fn buildOutputType(...@@ -1219,12 +1222,12 @@ fn buildOutputType(
1219 var i: usize = 0;1222 var i: usize = 0;
1220 while (i < system_libs.items.len) {1223 while (i < system_libs.items.len) {
1221 const lib_name = system_libs.items[i];1224 const lib_name = system_libs.items[i];
1222 if (is_libc_lib_name(target_info.target, lib_name)) {1225 if (target_util.is_libc_lib_name(target_info.target, lib_name)) {
1223 link_libc = true;1226 link_libc = true;
1224 _ = system_libs.orderedRemove(i);1227 _ = system_libs.orderedRemove(i);
1225 continue;1228 continue;
1226 }1229 }
1227 if (is_libcpp_lib_name(target_info.target, lib_name)) {1230 if (target_util.is_libcpp_lib_name(target_info.target, lib_name)) {
1228 link_libcpp = true;1231 link_libcpp = true;
1229 _ = system_libs.orderedRemove(i);1232 _ = system_libs.orderedRemove(i);
1230 continue;1233 continue;
...@@ -2809,62 +2812,6 @@ pub const ClangArgIterator = struct {...@@ -2809,62 +2812,6 @@ pub const ClangArgIterator = struct {
2809 }2812 }
2810};2813};
28112814
2812fn eqlIgnoreCase(ignore_case: bool, a: []const u8, b: []const u8) bool {
2813 if (ignore_case) {
2814 return std.ascii.eqlIgnoreCase(a, b);
2815 } else {
2816 return mem.eql(u8, a, b);
2817 }
2818}
2819
2820fn is_libc_lib_name(target: std.Target, name: []const u8) bool {
2821 const ignore_case = target.os.tag.isDarwin() or target.os.tag == .windows;
2822
2823 if (eqlIgnoreCase(ignore_case, name, "c"))
2824 return true;
2825
2826 if (target.isMinGW()) {
2827 if (eqlIgnoreCase(ignore_case, name, "m"))
2828 return true;
2829
2830 return false;
2831 }
2832
2833 if (target.abi.isGnu() or target.abi.isMusl() or target.os.tag.isDarwin()) {
2834 if (eqlIgnoreCase(ignore_case, name, "m"))
2835 return true;
2836 if (eqlIgnoreCase(ignore_case, name, "rt"))
2837 return true;
2838 if (eqlIgnoreCase(ignore_case, name, "pthread"))
2839 return true;
2840 if (eqlIgnoreCase(ignore_case, name, "crypt"))
2841 return true;
2842 if (eqlIgnoreCase(ignore_case, name, "util"))
2843 return true;
2844 if (eqlIgnoreCase(ignore_case, name, "xnet"))
2845 return true;
2846 if (eqlIgnoreCase(ignore_case, name, "resolv"))
2847 return true;
2848 if (eqlIgnoreCase(ignore_case, name, "dl"))
2849 return true;
2850 if (eqlIgnoreCase(ignore_case, name, "util"))
2851 return true;
2852 }
2853
2854 if (target.os.tag.isDarwin() and eqlIgnoreCase(ignore_case, name, "System"))
2855 return true;
2856
2857 return false;
2858}
2859
2860fn is_libcpp_lib_name(target: std.Target, name: []const u8) bool {
2861 const ignore_case = target.os.tag.isDarwin() or target.os.tag == .windows;
2862
2863 return eqlIgnoreCase(ignore_case, name, "c++") or
2864 eqlIgnoreCase(ignore_case, name, "stdc++") or
2865 eqlIgnoreCase(ignore_case, name, "c++abi");
2866}
2867
2868fn parseCodeModel(arg: []const u8) std.builtin.CodeModel {2815fn parseCodeModel(arg: []const u8) std.builtin.CodeModel {
2869 return std.meta.stringToEnum(std.builtin.CodeModel, arg) orelse2816 return std.meta.stringToEnum(std.builtin.CodeModel, arg) orelse
2870 fatal("unsupported machine code model: '{}'", .{arg});2817 fatal("unsupported machine code model: '{}'", .{arg});
src/stage1.zig+23-3
...@@ -5,13 +5,15 @@...@@ -5,13 +5,15 @@
5const std = @import("std");5const std = @import("std");
6const assert = std.debug.assert;6const assert = std.debug.assert;
7const mem = std.mem;7const mem = std.mem;
8const CrossTarget = std.zig.CrossTarget;
9const Target = std.Target;
10
8const build_options = @import("build_options");11const build_options = @import("build_options");
9const stage2 = @import("main.zig");12const stage2 = @import("main.zig");
10const fatal = stage2.fatal;13const fatal = stage2.fatal;
11const CrossTarget = std.zig.CrossTarget;
12const Target = std.Target;
13const Compilation = @import("Compilation.zig");14const Compilation = @import("Compilation.zig");
14const translate_c = @import("translate_c.zig");15const translate_c = @import("translate_c.zig");
16const target_util = @import("target.zig");
1517
16comptime {18comptime {
17 assert(std.builtin.link_libc);19 assert(std.builtin.link_libc);
...@@ -370,7 +372,25 @@ export fn stage2_add_link_lib(...@@ -370,7 +372,25 @@ export fn stage2_add_link_lib(
370 symbol_name_ptr: [*c]const u8,372 symbol_name_ptr: [*c]const u8,
371 symbol_name_len: usize,373 symbol_name_len: usize,
372) ?[*:0]const u8 {374) ?[*:0]const u8 {
373 return null; // no error375 const comp = @intToPtr(*Compilation, stage1.userdata);
376 const lib_name = lib_name_ptr[0..lib_name_len];
377 const symbol_name = symbol_name_ptr[0..symbol_name_len];
378 const target = comp.getTarget();
379 const is_libc = target_util.is_libc_lib_name(target, lib_name);
380 if (is_libc and !comp.bin_file.options.link_libc) {
381 return "dependency on libc must be explicitly specified in the build command";
382 }
383
384 if (!is_libc and !target.isWasm() and !comp.bin_file.options.pic) {
385 const msg = std.fmt.allocPrint0(
386 comp.gpa,
387 "dependency on dynamic library '{s}' requires enabling Position Independent Code. Fixed by `-l{s}` or `-fPIC`.",
388 .{ lib_name, lib_name },
389 ) catch return "out of memory";
390 return msg.ptr;
391 }
392
393 return null;
374}394}
375395
376export fn stage2_fetch_file(396export fn stage2_fetch_file(
src/stage1/stage1.h+1-1
...@@ -117,8 +117,8 @@ struct Stage2ProgressNode;...@@ -117,8 +117,8 @@ struct Stage2ProgressNode;
117117
118enum BuildMode {118enum BuildMode {
119 BuildModeDebug,119 BuildModeDebug,
120 BuildModeFastRelease,
121 BuildModeSafeRelease,120 BuildModeSafeRelease,
121 BuildModeFastRelease,
122 BuildModeSmallRelease,122 BuildModeSmallRelease,
123};123};
124124
src/stage1/zig0.cpp+1-1
...@@ -33,7 +33,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {...@@ -33,7 +33,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
33 "Options:\n"33 "Options:\n"
34 " --color [auto|off|on] enable or disable colored error messages\n"34 " --color [auto|off|on] enable or disable colored error messages\n"
35 " --name [name] override output name\n"35 " --name [name] override output name\n"
36 " --output-dir [dir] override output directory (defaults to cwd)\n"36 " -femit-bin=[path] Output machine code\n"
37 " --pkg-begin [name] [path] make pkg available to import and push current pkg\n"37 " --pkg-begin [name] [path] make pkg available to import and push current pkg\n"
38 " --pkg-end pop current pkg\n"38 " --pkg-end pop current pkg\n"
39 " -ODebug build with optimizations on and safety off\n"39 " -ODebug build with optimizations on and safety off\n"
src/target.zig+56
...@@ -223,3 +223,59 @@ pub fn osToLLVM(os_tag: std.Target.Os.Tag) llvm.OSType {...@@ -223,3 +223,59 @@ pub fn osToLLVM(os_tag: std.Target.Os.Tag) llvm.OSType {
223 .emscripten => .Emscripten,223 .emscripten => .Emscripten,
224 };224 };
225}225}
226
227fn eqlIgnoreCase(ignore_case: bool, a: []const u8, b: []const u8) bool {
228 if (ignore_case) {
229 return std.ascii.eqlIgnoreCase(a, b);
230 } else {
231 return std.mem.eql(u8, a, b);
232 }
233}
234
235pub fn is_libc_lib_name(target: std.Target, name: []const u8) bool {
236 const ignore_case = target.os.tag.isDarwin() or target.os.tag == .windows;
237
238 if (eqlIgnoreCase(ignore_case, name, "c"))
239 return true;
240
241 if (target.isMinGW()) {
242 if (eqlIgnoreCase(ignore_case, name, "m"))
243 return true;
244
245 return false;
246 }
247
248 if (target.abi.isGnu() or target.abi.isMusl() or target.os.tag.isDarwin()) {
249 if (eqlIgnoreCase(ignore_case, name, "m"))
250 return true;
251 if (eqlIgnoreCase(ignore_case, name, "rt"))
252 return true;
253 if (eqlIgnoreCase(ignore_case, name, "pthread"))
254 return true;
255 if (eqlIgnoreCase(ignore_case, name, "crypt"))
256 return true;
257 if (eqlIgnoreCase(ignore_case, name, "util"))
258 return true;
259 if (eqlIgnoreCase(ignore_case, name, "xnet"))
260 return true;
261 if (eqlIgnoreCase(ignore_case, name, "resolv"))
262 return true;
263 if (eqlIgnoreCase(ignore_case, name, "dl"))
264 return true;
265 if (eqlIgnoreCase(ignore_case, name, "util"))
266 return true;
267 }
268
269 if (target.os.tag.isDarwin() and eqlIgnoreCase(ignore_case, name, "System"))
270 return true;
271
272 return false;
273}
274
275pub fn is_libcpp_lib_name(target: std.Target, name: []const u8) bool {
276 const ignore_case = target.os.tag.isDarwin() or target.os.tag == .windows;
277
278 return eqlIgnoreCase(ignore_case, name, "c++") or
279 eqlIgnoreCase(ignore_case, name, "stdc++") or
280 eqlIgnoreCase(ignore_case, name, "c++abi");
281}
test/compile_errors.zig+1-1
...@@ -2347,7 +2347,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2347,7 +2347,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2347 \\ exit(0);2347 \\ exit(0);
2348 \\}2348 \\}
2349 , &[_][]const u8{2349 , &[_][]const u8{
2350 "tmp.zig:3:5: error: dependency on library c must be explicitly specified in the build command",2350 "tmp.zig:3:5: error: dependency on libc must be explicitly specified in the build command",
2351 });2351 });
23522352
2353 cases.addTest("libc headers note",2353 cases.addTest("libc headers note",
test/tests.zig+21-28
...@@ -634,7 +634,7 @@ pub const StackTracesContext = struct {...@@ -634,7 +634,7 @@ pub const StackTracesContext = struct {
634634
635 warn("Test {}/{} {}...", .{ self.test_index + 1, self.context.test_index, self.name });635 warn("Test {}/{} {}...", .{ self.test_index + 1, self.context.test_index, self.name });
636636
637 const child = std.ChildProcess.init(args.span(), b.allocator) catch unreachable;637 const child = std.ChildProcess.init(args.items, b.allocator) catch unreachable;
638 defer child.deinit();638 defer child.deinit();
639639
640 child.stdin_behavior = .Ignore;640 child.stdin_behavior = .Ignore;
...@@ -643,7 +643,7 @@ pub const StackTracesContext = struct {...@@ -643,7 +643,7 @@ pub const StackTracesContext = struct {
643 child.env_map = b.env_map;643 child.env_map = b.env_map;
644644
645 if (b.verbose) {645 if (b.verbose) {
646 printInvocation(args.span());646 printInvocation(args.items);
647 }647 }
648 child.spawn() catch |err| debug.panic("Unable to spawn {}: {}\n", .{ full_exe_path, @errorName(err) });648 child.spawn() catch |err| debug.panic("Unable to spawn {}: {}\n", .{ full_exe_path, @errorName(err) });
649649
...@@ -666,23 +666,23 @@ pub const StackTracesContext = struct {...@@ -666,23 +666,23 @@ pub const StackTracesContext = struct {
666 code,666 code,
667 expect_code,667 expect_code,
668 });668 });
669 printInvocation(args.span());669 printInvocation(args.items);
670 return error.TestFailed;670 return error.TestFailed;
671 }671 }
672 },672 },
673 .Signal => |signum| {673 .Signal => |signum| {
674 warn("Process {} terminated on signal {}\n", .{ full_exe_path, signum });674 warn("Process {} terminated on signal {}\n", .{ full_exe_path, signum });
675 printInvocation(args.span());675 printInvocation(args.items);
676 return error.TestFailed;676 return error.TestFailed;
677 },677 },
678 .Stopped => |signum| {678 .Stopped => |signum| {
679 warn("Process {} stopped on signal {}\n", .{ full_exe_path, signum });679 warn("Process {} stopped on signal {}\n", .{ full_exe_path, signum });
680 printInvocation(args.span());680 printInvocation(args.items);
681 return error.TestFailed;681 return error.TestFailed;
682 },682 },
683 .Unknown => |code| {683 .Unknown => |code| {
684 warn("Process {} terminated unexpectedly with error code {}\n", .{ full_exe_path, code });684 warn("Process {} terminated unexpectedly with error code {}\n", .{ full_exe_path, code });
685 printInvocation(args.span());685 printInvocation(args.items);
686 return error.TestFailed;686 return error.TestFailed;
687 },687 },
688 }688 }
...@@ -837,34 +837,27 @@ pub const CompileErrorContext = struct {...@@ -837,34 +837,27 @@ pub const CompileErrorContext = struct {
837 } else {837 } else {
838 try zig_args.append("build-obj");838 try zig_args.append("build-obj");
839 }839 }
840 const root_src_basename = self.case.sources.span()[0].filename;840 const root_src_basename = self.case.sources.items[0].filename;
841 try zig_args.append(self.write_src.getOutputPath(root_src_basename));841 try zig_args.append(self.write_src.getOutputPath(root_src_basename));
842842
843 zig_args.append("--name") catch unreachable;843 zig_args.append("--name") catch unreachable;
844 zig_args.append("test") catch unreachable;844 zig_args.append("test") catch unreachable;
845845
846 zig_args.append("--output-dir") catch unreachable;
847 zig_args.append(b.pathFromRoot(b.cache_root)) catch unreachable;
848
849 if (!self.case.target.isNative()) {846 if (!self.case.target.isNative()) {
850 try zig_args.append("-target");847 try zig_args.append("-target");
851 try zig_args.append(try self.case.target.zigTriple(b.allocator));848 try zig_args.append(try self.case.target.zigTriple(b.allocator));
852 }849 }
853850
854 switch (self.build_mode) {851 zig_args.append("-O") catch unreachable;
855 Mode.Debug => {},852 zig_args.append(@tagName(self.build_mode)) catch unreachable;
856 Mode.ReleaseSafe => zig_args.append("--release-safe") catch unreachable,
857 Mode.ReleaseFast => zig_args.append("--release-fast") catch unreachable,
858 Mode.ReleaseSmall => zig_args.append("--release-small") catch unreachable,
859 }
860853
861 warn("Test {}/{} {}...", .{ self.test_index + 1, self.context.test_index, self.name });854 warn("Test {}/{} {}...", .{ self.test_index + 1, self.context.test_index, self.name });
862855
863 if (b.verbose) {856 if (b.verbose) {
864 printInvocation(zig_args.span());857 printInvocation(zig_args.items);
865 }858 }
866859
867 const child = std.ChildProcess.init(zig_args.span(), b.allocator) catch unreachable;860 const child = std.ChildProcess.init(zig_args.items, b.allocator) catch unreachable;
868 defer child.deinit();861 defer child.deinit();
869862
870 child.env_map = b.env_map;863 child.env_map = b.env_map;
...@@ -886,19 +879,19 @@ pub const CompileErrorContext = struct {...@@ -886,19 +879,19 @@ pub const CompileErrorContext = struct {
886 switch (term) {879 switch (term) {
887 .Exited => |code| {880 .Exited => |code| {
888 if (code == 0) {881 if (code == 0) {
889 printInvocation(zig_args.span());882 printInvocation(zig_args.items);
890 return error.CompilationIncorrectlySucceeded;883 return error.CompilationIncorrectlySucceeded;
891 }884 }
892 },885 },
893 else => {886 else => {
894 warn("Process {} terminated unexpectedly\n", .{b.zig_exe});887 warn("Process {} terminated unexpectedly\n", .{b.zig_exe});
895 printInvocation(zig_args.span());888 printInvocation(zig_args.items);
896 return error.TestFailed;889 return error.TestFailed;
897 },890 },
898 }891 }
899892
900 const stdout = stdout_buf.span();893 const stdout = stdout_buf.items;
901 const stderr = stderr_buf.span();894 const stderr = stderr_buf.items;
902895
903 if (stdout.len != 0) {896 if (stdout.len != 0) {
904 warn(897 warn(
...@@ -927,12 +920,12 @@ pub const CompileErrorContext = struct {...@@ -927,12 +920,12 @@ pub const CompileErrorContext = struct {
927920
928 if (!ok) {921 if (!ok) {
929 warn("\n======== Expected these compile errors: ========\n", .{});922 warn("\n======== Expected these compile errors: ========\n", .{});
930 for (self.case.expected_errors.span()) |expected| {923 for (self.case.expected_errors.items) |expected| {
931 warn("{}\n", .{expected});924 warn("{}\n", .{expected});
932 }925 }
933 }926 }
934 } else {927 } else {
935 for (self.case.expected_errors.span()) |expected| {928 for (self.case.expected_errors.items) |expected| {
936 if (mem.indexOf(u8, stderr, expected) == null) {929 if (mem.indexOf(u8, stderr, expected) == null) {
937 warn(930 warn(
938 \\931 \\
...@@ -1032,7 +1025,7 @@ pub const CompileErrorContext = struct {...@@ -1032,7 +1025,7 @@ pub const CompileErrorContext = struct {
1032 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;1025 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
1033 }1026 }
1034 const write_src = b.addWriteFiles();1027 const write_src = b.addWriteFiles();
1035 for (case.sources.span()) |src_file| {1028 for (case.sources.items) |src_file| {
1036 write_src.add(src_file.filename, src_file.source);1029 write_src.add(src_file.filename, src_file.source);
1037 }1030 }
10381031
...@@ -1079,7 +1072,7 @@ pub const StandaloneContext = struct {...@@ -1079,7 +1072,7 @@ pub const StandaloneContext = struct {
1079 zig_args.append("--verbose") catch unreachable;1072 zig_args.append("--verbose") catch unreachable;
1080 }1073 }
10811074
1082 const run_cmd = b.addSystemCommand(zig_args.span());1075 const run_cmd = b.addSystemCommand(zig_args.items);
10831076
1084 const log_step = b.addLog("PASS {}\n", .{annotated_case_name});1077 const log_step = b.addLog("PASS {}\n", .{annotated_case_name});
1085 log_step.step.dependOn(&run_cmd.step);1078 log_step.step.dependOn(&run_cmd.step);
...@@ -1179,7 +1172,7 @@ pub const GenHContext = struct {...@@ -1179,7 +1172,7 @@ pub const GenHContext = struct {
1179 const full_h_path = self.obj.getOutputHPath();1172 const full_h_path = self.obj.getOutputHPath();
1180 const actual_h = try io.readFileAlloc(b.allocator, full_h_path);1173 const actual_h = try io.readFileAlloc(b.allocator, full_h_path);
11811174
1182 for (self.case.expected_lines.span()) |expected_line| {1175 for (self.case.expected_lines.items) |expected_line| {
1183 if (mem.indexOf(u8, actual_h, expected_line) == null) {1176 if (mem.indexOf(u8, actual_h, expected_line) == null) {
1184 warn(1177 warn(
1185 \\1178 \\
...@@ -1240,7 +1233,7 @@ pub const GenHContext = struct {...@@ -1240,7 +1233,7 @@ pub const GenHContext = struct {
1240 }1233 }
12411234
1242 const write_src = b.addWriteFiles();1235 const write_src = b.addWriteFiles();
1243 for (case.sources.span()) |src_file| {1236 for (case.sources.items) |src_file| {
1244 write_src.add(src_file.filename, src_file.source);1237 write_src.add(src_file.filename, src_file.source);
1245 }1238 }
12461239