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 * restore the legacy -femit-h feature using the stage1 backend
2 * tests passing with -Dskip-non-native
3 * `-ftime-report`
4 * -fstack-report print stack size diagnostics\n"
1 * MachO LLD linking
52 * subsystem
63 * mingw-w64
7 * MachO LLD linking
84 * COFF LLD linking
95 * WASM LLD linking
106 * audit the CLI options for stage2
117 * audit the base cache hash
128 * 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
149 * windows CUSTOMBUILD : error : unable to build compiler_rt: FileNotFound [D:\a\1\s\build\zig_install_lib_files.vcxproj]
1510 * 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
1714 * implement proper parsing of clang stderr/stdout and exposing compile errors with the Compilation API
1815 * implement proper parsing of LLD stderr/stdout and exposing compile errors with the Compilation API
......@@ -51,3 +48,4 @@
5148 * update musl.zig static data to use native path separator in static data rather than replacing '/' at runtime
5249 * 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)
5350 * 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 {
211211 test_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes));
212212 test_step.dependOn(tests.addStandaloneTests(b, test_filter, modes));
213213 test_step.dependOn(tests.addStackTraceTests(b, test_filter, modes));
214 const test_cli = 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);
214 test_step.dependOn(tests.addCliTests(b, test_filter, modes));
218215 test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes));
219216 test_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes));
220217 test_step.dependOn(tests.addTranslateCTests(b, test_filter));
doc/docgen.zig+85-162
......@@ -4,7 +4,7 @@ const io = std.io;
44const fs = std.fs;
55const process = std.process;
66const ChildProcess = std.ChildProcess;
7const warn = std.debug.warn;
7const print = std.debug.print;
88const mem = std.mem;
99const testing = std.testing;
1010
......@@ -215,23 +215,23 @@ const Tokenizer = struct {
215215fn parseError(tokenizer: *Tokenizer, token: Token, comptime fmt: []const u8, args: anytype) anyerror {
216216 const loc = tokenizer.getTokenLocation(token);
217217 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);
219219 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]});
221221 {
222222 var i: usize = 0;
223223 while (i < loc.column) : (i += 1) {
224 warn(" ", .{});
224 print(" ", .{});
225225 }
226226 }
227227 {
228228 const caret_count = token.end - token.start;
229229 var i: usize = 0;
230230 while (i < caret_count) : (i += 1) {
231 warn("~", .{});
231 print("~", .{});
232232 }
233233 }
234 warn("\n", .{});
234 print("\n", .{});
235235 }
236236 return error.ParseError;
237237}
......@@ -274,6 +274,7 @@ const Code = struct {
274274 link_objects: []const []const u8,
275275 target_str: ?[]const u8,
276276 link_libc: bool,
277 disable_cache: bool,
277278
278279 const Id = union(enum) {
279280 Test,
......@@ -522,6 +523,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
522523 defer link_objects.deinit();
523524 var target_str: ?[]const u8 = null;
524525 var link_libc = false;
526 var disable_cache = false;
525527
526528 const source_token = while (true) {
527529 const content_tok = try eatToken(tokenizer, Token.Id.Content);
......@@ -532,6 +534,8 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
532534 mode = .ReleaseFast;
533535 } else if (mem.eql(u8, end_tag_name, "code_release_safe")) {
534536 mode = .ReleaseSafe;
537 } else if (mem.eql(u8, end_tag_name, "code_disable_cache")) {
538 disable_cache = true;
535539 } else if (mem.eql(u8, end_tag_name, "code_link_object")) {
536540 _ = try eatToken(tokenizer, Token.Id.Separator);
537541 const obj_tok = try eatToken(tokenizer, Token.Id.TagContent);
......@@ -572,6 +576,7 @@ fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
572576 .link_objects = link_objects.toOwnedSlice(),
573577 .target_str = target_str,
574578 .link_libc = link_libc,
579 .disable_cache = disable_cache,
575580 },
576581 });
577582 tokenizer.code_node_count += 1;
......@@ -1032,7 +1037,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
10321037 },
10331038 .Code => |code| {
10341039 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
10371042 const raw_source = tokenizer.buffer[code.source_token.start..code.source_token.end];
10381043 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
10551060 var build_args = std.ArrayList([]const u8).init(allocator);
10561061 defer build_args.deinit();
10571062 try build_args.appendSlice(&[_][]const u8{
1058 zig_exe,
1059 "build-exe",
1060 tmp_source_file_name,
1061 "--name",
1062 code.name,
1063 "--color",
1064 "on",
1065 "--cache",
1066 "on",
1063 zig_exe, "build-exe",
1064 "--name", code.name,
1065 "--color", "on",
1066 "--enable-cache", tmp_source_file_name,
10671067 });
10681068 try out.print("<pre><code class=\"shell\">$ zig build-exe {}.zig", .{code.name});
10691069 switch (code.mode) {
10701070 .Debug => {},
1071 .ReleaseSafe => {
1072 try build_args.append("--release-safe");
1073 try out.print(" --release-safe", .{});
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", .{});
1071 else => {
1072 try build_args.appendSlice(&[_][]const u8{ "-O", @tagName(code.mode) });
1073 try out.print(" -O {s}", .{@tagName(code.mode)});
10821074 },
10831075 }
10841076 for (code.link_objects) |link_object| {
......@@ -1087,9 +1079,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
10871079 allocator,
10881080 &[_][]const u8{ tmp_dir_name, name_with_ext },
10891081 );
1090 try build_args.append("--object");
10911082 try build_args.append(full_path_object);
1092 try out.print(" --object {}", .{name_with_ext});
1083 try out.print(" {s}", .{name_with_ext});
10931084 }
10941085 if (code.link_libc) {
10951086 try build_args.append("-lc");
......@@ -1114,20 +1105,14 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
11141105 switch (result.term) {
11151106 .Exited => |exit_code| {
11161107 if (exit_code == 0) {
1117 warn("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});
1118 for (build_args.items) |arg|
1119 warn("{} ", .{arg})
1120 else
1121 warn("\n", .{});
1108 print("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});
1109 dumpArgs(build_args.items);
11221110 return parseError(tokenizer, code.source_token, "example incorrectly compiled", .{});
11231111 }
11241112 },
11251113 else => {
1126 warn("{}\nThe following command crashed:\n", .{result.stderr});
1127 for (build_args.items) |arg|
1128 warn("{} ", .{arg})
1129 else
1130 warn("\n", .{});
1114 print("{}\nThe following command crashed:\n", .{result.stderr});
1115 dumpArgs(build_args.items);
11311116 return parseError(tokenizer, code.source_token, "example compile crashed", .{});
11321117 },
11331118 }
......@@ -1174,11 +1159,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
11741159 switch (result.term) {
11751160 .Exited => |exit_code| {
11761161 if (exit_code == 0) {
1177 warn("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});
1178 for (run_args) |arg|
1179 warn("{} ", .{arg})
1180 else
1181 warn("\n", .{});
1162 print("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});
1163 dumpArgs(run_args);
11821164 return parseError(tokenizer, code.source_token, "example incorrectly compiled", .{});
11831165 }
11841166 },
......@@ -1206,27 +1188,13 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
12061188 var test_args = std.ArrayList([]const u8).init(allocator);
12071189 defer test_args.deinit();
12081190
1209 try test_args.appendSlice(&[_][]const u8{
1210 zig_exe,
1211 "test",
1212 tmp_source_file_name,
1213 "--cache",
1214 "on",
1215 });
1191 try test_args.appendSlice(&[_][]const u8{ zig_exe, "test", tmp_source_file_name });
12161192 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", .{code.name});
12171193 switch (code.mode) {
12181194 .Debug => {},
1219 .ReleaseSafe => {
1220 try test_args.append("--release-safe");
1221 try out.print(" --release-safe", .{});
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", .{});
1195 else => {
1196 try test_args.appendSlice(&[_][]const u8{ "-O", @tagName(code.mode) });
1197 try out.print(" -O {s}", .{@tagName(code.mode)});
12301198 },
12311199 }
12321200 if (code.link_libc) {
......@@ -1252,23 +1220,13 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
12521220 "--color",
12531221 "on",
12541222 tmp_source_file_name,
1255 "--output-dir",
1256 tmp_dir_name,
12571223 });
12581224 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", .{code.name});
12591225 switch (code.mode) {
12601226 .Debug => {},
1261 .ReleaseSafe => {
1262 try test_args.append("--release-safe");
1263 try out.print(" --release-safe", .{});
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", .{});
1227 else => {
1228 try test_args.appendSlice(&[_][]const u8{ "-O", @tagName(code.mode) });
1229 try out.print(" -O {s}", .{@tagName(code.mode)});
12721230 },
12731231 }
12741232 const result = try ChildProcess.exec(.{
......@@ -1280,25 +1238,19 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
12801238 switch (result.term) {
12811239 .Exited => |exit_code| {
12821240 if (exit_code == 0) {
1283 warn("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});
1284 for (test_args.items) |arg|
1285 warn("{} ", .{arg})
1286 else
1287 warn("\n", .{});
1241 print("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});
1242 dumpArgs(test_args.items);
12881243 return parseError(tokenizer, code.source_token, "example incorrectly compiled", .{});
12891244 }
12901245 },
12911246 else => {
1292 warn("{}\nThe following command crashed:\n", .{result.stderr});
1293 for (test_args.items) |arg|
1294 warn("{} ", .{arg})
1295 else
1296 warn("\n", .{});
1247 print("{}\nThe following command crashed:\n", .{result.stderr});
1248 dumpArgs(test_args.items);
12971249 return parseError(tokenizer, code.source_token, "example compile crashed", .{});
12981250 },
12991251 }
13001252 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 });
13021254 return parseError(tokenizer, code.source_token, "example did not have expected compile error", .{});
13031255 }
13041256 const escaped_stderr = try escapeHtml(allocator, result.stderr);
......@@ -1314,23 +1266,21 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
13141266 zig_exe,
13151267 "test",
13161268 tmp_source_file_name,
1317 "--output-dir",
1318 tmp_dir_name,
13191269 });
13201270 var mode_arg: []const u8 = "";
13211271 switch (code.mode) {
13221272 .Debug => {},
13231273 .ReleaseSafe => {
1324 try test_args.append("--release-safe");
1325 mode_arg = " --release-safe";
1274 try test_args.append("-OReleaseSafe");
1275 mode_arg = "-OReleaseSafe";
13261276 },
13271277 .ReleaseFast => {
1328 try test_args.append("--release-fast");
1329 mode_arg = " --release-fast";
1278 try test_args.append("-OReleaseFast");
1279 mode_arg = "-OReleaseFast";
13301280 },
13311281 .ReleaseSmall => {
1332 try test_args.append("--release-small");
1333 mode_arg = " --release-small";
1282 try test_args.append("-OReleaseSmall");
1283 mode_arg = "-OReleaseSmall";
13341284 },
13351285 }
13361286
......@@ -1343,25 +1293,19 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
13431293 switch (result.term) {
13441294 .Exited => |exit_code| {
13451295 if (exit_code == 0) {
1346 warn("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});
1347 for (test_args.items) |arg|
1348 warn("{} ", .{arg})
1349 else
1350 warn("\n", .{});
1296 print("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});
1297 dumpArgs(test_args.items);
13511298 return parseError(tokenizer, code.source_token, "example test incorrectly succeeded", .{});
13521299 }
13531300 },
13541301 else => {
1355 warn("{}\nThe following command crashed:\n", .{result.stderr});
1356 for (test_args.items) |arg|
1357 warn("{} ", .{arg})
1358 else
1359 warn("\n", .{});
1302 print("{}\nThe following command crashed:\n", .{result.stderr});
1303 dumpArgs(test_args.items);
13601304 return parseError(tokenizer, code.source_token, "example compile crashed", .{});
13611305 },
13621306 }
13631307 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 });
13651309 return parseError(tokenizer, code.source_token, "example did not have expected runtime safety error message", .{});
13661310 }
13671311 const escaped_stderr = try escapeHtml(allocator, result.stderr);
......@@ -1395,32 +1339,20 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
13951339 "on",
13961340 "--name",
13971341 code.name,
1398 "--output-dir",
1399 tmp_dir_name,
1342 try std.fmt.allocPrint(allocator, "-femit-bin={s}{c}{s}", .{
1343 tmp_dir_name, fs.path.sep, name_plus_obj_ext,
1344 }),
14001345 });
1401
14021346 if (!code.is_inline) {
14031347 try out.print("<pre><code class=\"shell\">$ zig build-obj {}.zig", .{code.name});
14041348 }
14051349
14061350 switch (code.mode) {
14071351 .Debug => {},
1408 .ReleaseSafe => {
1409 try build_args.append("--release-safe");
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");
1352 else => {
1353 try build_args.appendSlice(&[_][]const u8{ "-O", @tagName(code.mode) });
14221354 if (!code.is_inline) {
1423 try out.print(" --release-small", .{});
1355 try out.print(" -O {s}", .{@tagName(code.mode)});
14241356 }
14251357 },
14261358 }
......@@ -1440,25 +1372,19 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
14401372 switch (result.term) {
14411373 .Exited => |exit_code| {
14421374 if (exit_code == 0) {
1443 warn("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});
1444 for (build_args.items) |arg|
1445 warn("{} ", .{arg})
1446 else
1447 warn("\n", .{});
1375 print("{}\nThe following command incorrectly succeeded:\n", .{result.stderr});
1376 dumpArgs(build_args.items);
14481377 return parseError(tokenizer, code.source_token, "example build incorrectly succeeded", .{});
14491378 }
14501379 },
14511380 else => {
1452 warn("{}\nThe following command crashed:\n", .{result.stderr});
1453 for (build_args.items) |arg|
1454 warn("{} ", .{arg})
1455 else
1456 warn("\n", .{});
1381 print("{}\nThe following command crashed:\n", .{result.stderr});
1382 dumpArgs(build_args.items);
14571383 return parseError(tokenizer, code.source_token, "example compile crashed", .{});
14581384 },
14591385 }
14601386 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 });
14621388 return parseError(tokenizer, code.source_token, "example did not have expected compile error message", .{});
14631389 }
14641390 const escaped_stderr = try escapeHtml(allocator, result.stderr);
......@@ -1472,6 +1398,12 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
14721398 }
14731399 },
14741400 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
14751407 var test_args = std.ArrayList([]const u8).init(allocator);
14761408 defer test_args.deinit();
14771409
......@@ -1479,23 +1411,16 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
14791411 zig_exe,
14801412 "build-lib",
14811413 tmp_source_file_name,
1482 "--output-dir",
1483 tmp_dir_name,
1414 try std.fmt.allocPrint(allocator, "-femit-bin={s}{s}{s}", .{
1415 tmp_dir_name, fs.path.sep_str, bin_basename,
1416 }),
14841417 });
14851418 try out.print("<pre><code class=\"shell\">$ zig build-lib {}.zig", .{code.name});
14861419 switch (code.mode) {
14871420 .Debug => {},
1488 .ReleaseSafe => {
1489 try test_args.append("--release-safe");
1490 try out.print(" --release-safe", .{});
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", .{});
1421 else => {
1422 try test_args.appendSlice(&[_][]const u8{ "-O", @tagName(code.mode) });
1423 try out.print(" -O {s}", .{@tagName(code.mode)});
14991424 },
15001425 }
15011426 if (code.target_str) |triple| {
......@@ -1508,7 +1433,7 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: any
15081433 try out.print("\n{}{}</code></pre>\n", .{ escaped_stderr, escaped_stdout });
15091434 },
15101435 }
1511 warn("OK\n", .{});
1436 print("OK\n", .{});
15121437 },
15131438 }
15141439 }
......@@ -1524,20 +1449,14 @@ fn exec(allocator: *mem.Allocator, env_map: *std.BufMap, args: []const []const u
15241449 switch (result.term) {
15251450 .Exited => |exit_code| {
15261451 if (exit_code != 0) {
1527 warn("{}\nThe following command exited with code {}:\n", .{ result.stderr, exit_code });
1528 for (args) |arg|
1529 warn("{} ", .{arg})
1530 else
1531 warn("\n", .{});
1452 print("{}\nThe following command exited with code {}:\n", .{ result.stderr, exit_code });
1453 dumpArgs(args);
15321454 return error.ChildExitError;
15331455 }
15341456 },
15351457 else => {
1536 warn("{}\nThe following command crashed:\n", .{result.stderr});
1537 for (args) |arg|
1538 warn("{} ", .{arg})
1539 else
1540 warn("\n", .{});
1458 print("{}\nThe following command crashed:\n", .{result.stderr});
1459 dumpArgs(args);
15411460 return error.ChildCrashed;
15421461 },
15431462 }
......@@ -1545,9 +1464,13 @@ fn exec(allocator: *mem.Allocator, env_map: *std.BufMap, args: []const []const u
15451464}
15461465
15471466fn getBuiltinCode(allocator: *mem.Allocator, env_map: *std.BufMap, zig_exe: []const u8) ![]const u8 {
1548 const result = try exec(allocator, env_map, &[_][]const u8{
1549 zig_exe,
1550 "builtin",
1551 });
1467 const result = try exec(allocator, env_map, &[_][]const u8{ zig_exe, "build-obj", "--show-builtin" });
15521468 return result.stdout;
15531469}
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);
10781078 but you can switch to {#syntax#}Optimized{#endsyntax#} mode on a per-block basis:</p>
10791079 {#code_begin|obj|foo#}
10801080 {#code_release_fast#}
1081 {#code_disable_cache#}
10811082const std = @import("std");
10821083const builtin = std.builtin;
10831084const big = @as(f64, 1 << 40);
lib/std/log.zig+3-5
......@@ -101,14 +101,12 @@ pub const Level = enum {
101101 debug,
102102};
103103
104/// The default log level is based on build mode. Note that in ReleaseSmall
105/// builds the default level is emerg but no messages will be stored/logged
106/// by the default logger to save space.
104/// The default log level is based on build mode.
107105pub const default_level: Level = switch (builtin.mode) {
108106 .Debug => .debug,
109107 .ReleaseSafe => .notice,
110108 .ReleaseFast => .err,
111 .ReleaseSmall => .emerg,
109 .ReleaseSmall => .err,
112110};
113111
114112/// The current log level. This is set to root.log_level if present, otherwise
......@@ -131,7 +129,7 @@ fn log(
131129 // On freestanding one must provide a log function; we do not have
132130 // any I/O configured.
133131 return;
134 } else if (builtin.mode != .ReleaseSmall) {
132 } else {
135133 const level_txt = switch (message_level) {
136134 .emerg => "emergency",
137135 .alert => "alert",
src/Compilation.zig+10-3
......@@ -714,6 +714,10 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
714714 };
715715 };
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
717721 const bin_file = try link.File.openPath(gpa, .{
718722 .emit = bin_file_emit,
719723 .root_name = root_name,
......@@ -1313,13 +1317,13 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
13131317 const tmp_dir_sub_path = try std.fs.path.join(arena, &[_][]const u8{ "o", &tmp_digest });
13141318 var zig_cache_tmp_dir = try comp.local_cache_directory.handle.makeOpenPath(tmp_dir_sub_path, .{});
13151319 defer zig_cache_tmp_dir.close();
1316 const cimport_c_basename = "cimport.c";
1320 const cimport_basename = "cimport.h";
13171321 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,
13191323 });
13201324 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);
13231327 if (comp.verbose_cimport) {
13241328 log.info("C import source: {}", .{out_h_path});
13251329 }
......@@ -2542,6 +2546,9 @@ fn updateStage1Module(comp: *Compilation) !void {
25422546 });
25432547 break :blk try directory.join(arena, &[_][]const u8{bin_basename});
25442548 } 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 }
25452552 const emit_h_path = try stage1LocPath(arena, comp.emit_h, directory);
25462553 const emit_asm_path = try stage1LocPath(arena, comp.emit_asm, directory);
25472554 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;
77const Allocator = mem.Allocator;
88const ArrayList = std.ArrayList;
99const ast = std.zig.ast;
10const warn = std.log.warn;
11
1012const Compilation = @import("Compilation.zig");
1113const link = @import("link.zig");
1214const Package = @import("Package.zig");
1315const zir = @import("zir.zig");
1416const build_options = @import("build_options");
15const warn = std.log.warn;
1617const introspect = @import("introspect.zig");
1718const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
1819const translate_c = @import("translate_c.zig");
1920const Cache = @import("Cache.zig");
21const target_util = @import("target.zig");
2022
2123pub fn fatal(comptime format: []const u8, args: anytype) noreturn {
2224 std.log.emerg(format, args);
......@@ -773,6 +775,7 @@ fn buildOutputType(
773775 dll_export_fns = false;
774776 } else if (mem.eql(u8, arg, "--show-builtin")) {
775777 show_builtin = true;
778 emit_bin = .no;
776779 } else if (mem.eql(u8, arg, "--strip")) {
777780 strip = true;
778781 } else if (mem.eql(u8, arg, "--single-threaded")) {
......@@ -1219,12 +1222,12 @@ fn buildOutputType(
12191222 var i: usize = 0;
12201223 while (i < system_libs.items.len) {
12211224 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)) {
12231226 link_libc = true;
12241227 _ = system_libs.orderedRemove(i);
12251228 continue;
12261229 }
1227 if (is_libcpp_lib_name(target_info.target, lib_name)) {
1230 if (target_util.is_libcpp_lib_name(target_info.target, lib_name)) {
12281231 link_libcpp = true;
12291232 _ = system_libs.orderedRemove(i);
12301233 continue;
......@@ -2809,62 +2812,6 @@ pub const ClangArgIterator = struct {
28092812 }
28102813};
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
28682815fn parseCodeModel(arg: []const u8) std.builtin.CodeModel {
28692816 return std.meta.stringToEnum(std.builtin.CodeModel, arg) orelse
28702817 fatal("unsupported machine code model: '{}'", .{arg});
src/stage1.zig+23-3
......@@ -5,13 +5,15 @@
55const std = @import("std");
66const assert = std.debug.assert;
77const mem = std.mem;
8const CrossTarget = std.zig.CrossTarget;
9const Target = std.Target;
10
811const build_options = @import("build_options");
912const stage2 = @import("main.zig");
1013const fatal = stage2.fatal;
11const CrossTarget = std.zig.CrossTarget;
12const Target = std.Target;
1314const Compilation = @import("Compilation.zig");
1415const translate_c = @import("translate_c.zig");
16const target_util = @import("target.zig");
1517
1618comptime {
1719 assert(std.builtin.link_libc);
......@@ -370,7 +372,25 @@ export fn stage2_add_link_lib(
370372 symbol_name_ptr: [*c]const u8,
371373 symbol_name_len: usize,
372374) ?[*:0]const u8 {
373 return null; // no error
375 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;
374394}
375395
376396export fn stage2_fetch_file(
src/stage1/stage1.h+1-1
......@@ -117,8 +117,8 @@ struct Stage2ProgressNode;
117117
118118enum BuildMode {
119119 BuildModeDebug,
120 BuildModeFastRelease,
121120 BuildModeSafeRelease,
121 BuildModeFastRelease,
122122 BuildModeSmallRelease,
123123};
124124
src/stage1/zig0.cpp+1-1
......@@ -33,7 +33,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
3333 "Options:\n"
3434 " --color [auto|off|on] enable or disable colored error messages\n"
3535 " --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"
3737 " --pkg-begin [name] [path] make pkg available to import and push current pkg\n"
3838 " --pkg-end pop current pkg\n"
3939 " -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 {
223223 .emscripten => .Emscripten,
224224 };
225225}
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 {
23472347 \\ exit(0);
23482348 \\}
23492349 , &[_][]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",
23512351 });
23522352
23532353 cases.addTest("libc headers note",
test/tests.zig+21-28
......@@ -634,7 +634,7 @@ pub const StackTracesContext = struct {
634634
635635 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;
638638 defer child.deinit();
639639
640640 child.stdin_behavior = .Ignore;
......@@ -643,7 +643,7 @@ pub const StackTracesContext = struct {
643643 child.env_map = b.env_map;
644644
645645 if (b.verbose) {
646 printInvocation(args.span());
646 printInvocation(args.items);
647647 }
648648 child.spawn() catch |err| debug.panic("Unable to spawn {}: {}\n", .{ full_exe_path, @errorName(err) });
649649
......@@ -666,23 +666,23 @@ pub const StackTracesContext = struct {
666666 code,
667667 expect_code,
668668 });
669 printInvocation(args.span());
669 printInvocation(args.items);
670670 return error.TestFailed;
671671 }
672672 },
673673 .Signal => |signum| {
674674 warn("Process {} terminated on signal {}\n", .{ full_exe_path, signum });
675 printInvocation(args.span());
675 printInvocation(args.items);
676676 return error.TestFailed;
677677 },
678678 .Stopped => |signum| {
679679 warn("Process {} stopped on signal {}\n", .{ full_exe_path, signum });
680 printInvocation(args.span());
680 printInvocation(args.items);
681681 return error.TestFailed;
682682 },
683683 .Unknown => |code| {
684684 warn("Process {} terminated unexpectedly with error code {}\n", .{ full_exe_path, code });
685 printInvocation(args.span());
685 printInvocation(args.items);
686686 return error.TestFailed;
687687 },
688688 }
......@@ -837,34 +837,27 @@ pub const CompileErrorContext = struct {
837837 } else {
838838 try zig_args.append("build-obj");
839839 }
840 const root_src_basename = self.case.sources.span()[0].filename;
840 const root_src_basename = self.case.sources.items[0].filename;
841841 try zig_args.append(self.write_src.getOutputPath(root_src_basename));
842842
843843 zig_args.append("--name") catch unreachable;
844844 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
849846 if (!self.case.target.isNative()) {
850847 try zig_args.append("-target");
851848 try zig_args.append(try self.case.target.zigTriple(b.allocator));
852849 }
853850
854 switch (self.build_mode) {
855 Mode.Debug => {},
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 }
851 zig_args.append("-O") catch unreachable;
852 zig_args.append(@tagName(self.build_mode)) catch unreachable;
860853
861854 warn("Test {}/{} {}...", .{ self.test_index + 1, self.context.test_index, self.name });
862855
863856 if (b.verbose) {
864 printInvocation(zig_args.span());
857 printInvocation(zig_args.items);
865858 }
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;
868861 defer child.deinit();
869862
870863 child.env_map = b.env_map;
......@@ -886,19 +879,19 @@ pub const CompileErrorContext = struct {
886879 switch (term) {
887880 .Exited => |code| {
888881 if (code == 0) {
889 printInvocation(zig_args.span());
882 printInvocation(zig_args.items);
890883 return error.CompilationIncorrectlySucceeded;
891884 }
892885 },
893886 else => {
894887 warn("Process {} terminated unexpectedly\n", .{b.zig_exe});
895 printInvocation(zig_args.span());
888 printInvocation(zig_args.items);
896889 return error.TestFailed;
897890 },
898891 }
899892
900 const stdout = stdout_buf.span();
901 const stderr = stderr_buf.span();
893 const stdout = stdout_buf.items;
894 const stderr = stderr_buf.items;
902895
903896 if (stdout.len != 0) {
904897 warn(
......@@ -927,12 +920,12 @@ pub const CompileErrorContext = struct {
927920
928921 if (!ok) {
929922 warn("\n======== Expected these compile errors: ========\n", .{});
930 for (self.case.expected_errors.span()) |expected| {
923 for (self.case.expected_errors.items) |expected| {
931924 warn("{}\n", .{expected});
932925 }
933926 }
934927 } else {
935 for (self.case.expected_errors.span()) |expected| {
928 for (self.case.expected_errors.items) |expected| {
936929 if (mem.indexOf(u8, stderr, expected) == null) {
937930 warn(
938931 \\
......@@ -1032,7 +1025,7 @@ pub const CompileErrorContext = struct {
10321025 if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
10331026 }
10341027 const write_src = b.addWriteFiles();
1035 for (case.sources.span()) |src_file| {
1028 for (case.sources.items) |src_file| {
10361029 write_src.add(src_file.filename, src_file.source);
10371030 }
10381031
......@@ -1079,7 +1072,7 @@ pub const StandaloneContext = struct {
10791072 zig_args.append("--verbose") catch unreachable;
10801073 }
10811074
1082 const run_cmd = b.addSystemCommand(zig_args.span());
1075 const run_cmd = b.addSystemCommand(zig_args.items);
10831076
10841077 const log_step = b.addLog("PASS {}\n", .{annotated_case_name});
10851078 log_step.step.dependOn(&run_cmd.step);
......@@ -1179,7 +1172,7 @@ pub const GenHContext = struct {
11791172 const full_h_path = self.obj.getOutputHPath();
11801173 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| {
11831176 if (mem.indexOf(u8, actual_h, expected_line) == null) {
11841177 warn(
11851178 \\
......@@ -1240,7 +1233,7 @@ pub const GenHContext = struct {
12401233 }
12411234
12421235 const write_src = b.addWriteFiles();
1243 for (case.sources.span()) |src_file| {
1236 for (case.sources.items) |src_file| {
12441237 write_src.add(src_file.filename, src_file.source);
12451238 }
12461239