authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-15 19:01:55-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-15 19:01:55-07:00
logccdf55310bee2dcf86b718d26a56933dc1a03443
treeb33a5cdb44395fd3ec399153213436dc3e836c48
parent2b2920f5998fc464c7ebd342c36879a17e76e4b4

stage2: properly model miscellaneous failed tasks

with error messages that go away after updates

2 files changed, 253 insertions(+), 43 deletions(-)

src/Compilation.zig+249-42
...@@ -53,6 +53,9 @@ c_object_work_queue: std.fifo.LinearFifo(*CObject, .Dynamic),...@@ -53,6 +53,9 @@ c_object_work_queue: std.fifo.LinearFifo(*CObject, .Dynamic),
53/// This data is accessed by multiple threads and is protected by `mutex`.53/// This data is accessed by multiple threads and is protected by `mutex`.
54failed_c_objects: std.AutoArrayHashMapUnmanaged(*CObject, *CObject.ErrorMsg) = .{},54failed_c_objects: std.AutoArrayHashMapUnmanaged(*CObject, *CObject.ErrorMsg) = .{},
5555
56/// Miscellaneous things that can fail.
57misc_failures: std.AutoArrayHashMapUnmanaged(MiscTask, MiscError) = .{},
58
56keep_source_files_loaded: bool,59keep_source_files_loaded: bool,
57use_clang: bool,60use_clang: bool,
58sanitize_c: bool,61sanitize_c: bool,
...@@ -256,6 +259,36 @@ pub const CObject = struct {...@@ -256,6 +259,36 @@ pub const CObject = struct {
256 }259 }
257};260};
258261
262pub const MiscTask = enum {
263 write_builtin_zig,
264 glibc_crt_file,
265 glibc_shared_objects,
266 musl_crt_file,
267 mingw_crt_file,
268 windows_import_lib,
269 libunwind,
270 libcxx,
271 libcxxabi,
272 libtsan,
273 compiler_rt,
274 libssp,
275 zig_libc,
276};
277
278pub const MiscError = struct {
279 /// Allocated with gpa.
280 msg: []u8,
281 children: ?AllErrors = null,
282
283 pub fn deinit(misc_err: *MiscError, gpa: *Allocator) void {
284 gpa.free(misc_err.msg);
285 if (misc_err.children) |*children| {
286 children.deinit(gpa);
287 }
288 misc_err.* = undefined;
289 }
290};
291
259/// To support incremental compilation, errors are stored in various places292/// To support incremental compilation, errors are stored in various places
260/// so that they can be created and destroyed appropriately. This structure293/// so that they can be created and destroyed appropriately. This structure
261/// is used to collect all the errors from the various places into one294/// is used to collect all the errors from the various places into one
...@@ -278,6 +311,7 @@ pub const AllErrors = struct {...@@ -278,6 +311,7 @@ pub const AllErrors = struct {
278 },311 },
279 plain: struct {312 plain: struct {
280 msg: []const u8,313 msg: []const u8,
314 notes: []Message = &.{},
281 },315 },
282316
283 pub fn renderToStdErr(msg: Message, ttyconf: std.debug.TTY.Config) void {317 pub fn renderToStdErr(msg: Message, ttyconf: std.debug.TTY.Config) void {
...@@ -285,7 +319,7 @@ pub const AllErrors = struct {...@@ -285,7 +319,7 @@ pub const AllErrors = struct {
285 const held = std.debug.getStderrMutex().acquire();319 const held = std.debug.getStderrMutex().acquire();
286 defer held.release();320 defer held.release();
287 const stderr = std.io.getStdErr();321 const stderr = std.io.getStdErr();
288 return msg.renderToStdErrInner(ttyconf, stderr, "error:", .Red) catch return;322 return msg.renderToStdErrInner(ttyconf, stderr, "error:", .Red, 0) catch return;
289 }323 }
290324
291 fn renderToStdErrInner(325 fn renderToStdErrInner(
...@@ -294,6 +328,7 @@ pub const AllErrors = struct {...@@ -294,6 +328,7 @@ pub const AllErrors = struct {
294 stderr_file: std.fs.File,328 stderr_file: std.fs.File,
295 kind: []const u8,329 kind: []const u8,
296 color: std.debug.TTY.Color,330 color: std.debug.TTY.Color,
331 indent: usize,
297 ) anyerror!void {332 ) anyerror!void {
298 const stderr = stderr_file.writer();333 const stderr = stderr_file.writer();
299 switch (msg) {334 switch (msg) {
...@@ -305,6 +340,7 @@ pub const AllErrors = struct {...@@ -305,6 +340,7 @@ pub const AllErrors = struct {
305 src.column + 1,340 src.column + 1,
306 });341 });
307 ttyconf.setColor(stderr, color);342 ttyconf.setColor(stderr, color);
343 try stderr.writeByteNTimes(' ', indent);
308 try stderr.writeAll(kind);344 try stderr.writeAll(kind);
309 ttyconf.setColor(stderr, .Bold);345 ttyconf.setColor(stderr, .Bold);
310 try stderr.print(" {s}\n", .{src.msg});346 try stderr.print(" {s}\n", .{src.msg});
...@@ -318,11 +354,19 @@ pub const AllErrors = struct {...@@ -318,11 +354,19 @@ pub const AllErrors = struct {
318 ttyconf.setColor(stderr, .Reset);354 ttyconf.setColor(stderr, .Reset);
319 }355 }
320 for (src.notes) |note| {356 for (src.notes) |note| {
321 try note.renderToStdErrInner(ttyconf, stderr_file, "note:", .Cyan);357 try note.renderToStdErrInner(ttyconf, stderr_file, "note:", .Cyan, indent);
322 }358 }
323 },359 },
324 .plain => |plain| {360 .plain => |plain| {
325 try stderr.print("{s}: {s}\n", .{ kind, plain.msg });361 ttyconf.setColor(stderr, color);
362 try stderr.writeByteNTimes(' ', indent);
363 try stderr.writeAll(kind);
364 ttyconf.setColor(stderr, .Reset);
365 try stderr.print(" {s}\n", .{plain.msg});
366 ttyconf.setColor(stderr, .Reset);
367 for (plain.notes) |note| {
368 try note.renderToStdErrInner(ttyconf, stderr_file, "error:", .Red, indent + 4);
369 }
326 },370 },
327 }371 }
328 }372 }
...@@ -380,6 +424,45 @@ pub const AllErrors = struct {...@@ -380,6 +424,45 @@ pub const AllErrors = struct {
380 ) !void {424 ) !void {
381 try errors.append(.{ .plain = .{ .msg = msg } });425 try errors.append(.{ .plain = .{ .msg = msg } });
382 }426 }
427
428 fn addPlainWithChildren(
429 arena: *std.heap.ArenaAllocator,
430 errors: *std.ArrayList(Message),
431 msg: []const u8,
432 optional_children: ?AllErrors,
433 ) !void {
434 const duped_msg = try arena.allocator.dupe(u8, msg);
435 if (optional_children) |*children| {
436 try errors.append(.{ .plain = .{
437 .msg = duped_msg,
438 .notes = try dupeList(children.list, &arena.allocator),
439 } });
440 } else {
441 try errors.append(.{ .plain = .{ .msg = duped_msg } });
442 }
443 }
444
445 fn dupeList(list: []const Message, arena: *Allocator) Allocator.Error![]Message {
446 const duped_list = try arena.alloc(Message, list.len);
447 for (list) |item, i| {
448 duped_list[i] = switch (item) {
449 .src => |src| .{ .src = .{
450 .msg = try arena.dupe(u8, src.msg),
451 .src_path = try arena.dupe(u8, src.src_path),
452 .line = src.line,
453 .column = src.column,
454 .byte_offset = src.byte_offset,
455 .source_line = if (src.source_line) |s| try arena.dupe(u8, s) else null,
456 .notes = try dupeList(src.notes, arena),
457 } },
458 .plain => |plain| .{ .plain = .{
459 .msg = try arena.dupe(u8, plain.msg),
460 .notes = try dupeList(plain.notes, arena),
461 } },
462 };
463 }
464 return duped_list;
465 }
383};466};
384467
385pub const Directory = struct {468pub const Directory = struct {
...@@ -1357,6 +1440,8 @@ pub fn destroy(self: *Compilation) void {...@@ -1357,6 +1440,8 @@ pub fn destroy(self: *Compilation) void {
1357 }1440 }
1358 self.failed_c_objects.deinit(gpa);1441 self.failed_c_objects.deinit(gpa);
13591442
1443 self.clearMiscFailures();
1444
1360 self.cache_parent.manifest_dir.close();1445 self.cache_parent.manifest_dir.close();
1361 if (self.owned_link_dir) |*dir| dir.close();1446 if (self.owned_link_dir) |*dir| dir.close();
13621447
...@@ -1366,6 +1451,14 @@ pub fn destroy(self: *Compilation) void {...@@ -1366,6 +1451,14 @@ pub fn destroy(self: *Compilation) void {
1366 self.arena_state.promote(gpa).deinit();1451 self.arena_state.promote(gpa).deinit();
1367}1452}
13681453
1454pub fn clearMiscFailures(comp: *Compilation) void {
1455 for (comp.misc_failures.items()) |*entry| {
1456 entry.value.deinit(comp.gpa);
1457 }
1458 comp.misc_failures.deinit(comp.gpa);
1459 comp.misc_failures = .{};
1460}
1461
1369pub fn getTarget(self: Compilation) Target {1462pub fn getTarget(self: Compilation) Target {
1370 return self.bin_file.options.target;1463 return self.bin_file.options.target;
1371}1464}
...@@ -1375,6 +1468,7 @@ pub fn update(self: *Compilation) !void {...@@ -1375,6 +1468,7 @@ pub fn update(self: *Compilation) !void {
1375 const tracy = trace(@src());1468 const tracy = trace(@src());
1376 defer tracy.end();1469 defer tracy.end();
13771470
1471 self.clearMiscFailures();
1378 self.c_object_cache_digest_set.clearRetainingCapacity();1472 self.c_object_cache_digest_set.clearRetainingCapacity();
13791473
1380 // For compiling C objects, we rely on the cache hash system to avoid duplicating work.1474 // For compiling C objects, we rely on the cache hash system to avoid duplicating work.
...@@ -1475,7 +1569,7 @@ pub fn makeBinFileWritable(self: *Compilation) !void {...@@ -1475,7 +1569,7 @@ pub fn makeBinFileWritable(self: *Compilation) !void {
1475}1569}
14761570
1477pub fn totalErrorCount(self: *Compilation) usize {1571pub fn totalErrorCount(self: *Compilation) usize {
1478 var total: usize = self.failed_c_objects.items().len;1572 var total: usize = self.failed_c_objects.count() + self.misc_failures.count();
14791573
1480 if (self.bin_file.options.module) |module| {1574 if (self.bin_file.options.module) |module| {
1481 total += module.failed_exports.items().len +1575 total += module.failed_exports.items().len +
...@@ -1539,6 +1633,9 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {...@@ -1539,6 +1633,9 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {
1539 },1633 },
1540 });1634 });
1541 }1635 }
1636 for (self.misc_failures.items()) |entry| {
1637 try AllErrors.addPlainWithChildren(&arena, &errors, entry.value.msg, entry.value.children);
1638 }
1542 if (self.bin_file.options.module) |module| {1639 if (self.bin_file.options.module) |module| {
1543 for (module.failed_files.items()) |entry| {1640 for (module.failed_files.items()) |entry| {
1544 try AllErrors.add(module, &arena, &errors, entry.value.*);1641 try AllErrors.add(module, &arena, &errors, entry.value.*);
...@@ -1775,89 +1872,160 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor...@@ -1775,89 +1872,160 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
1775 },1872 },
1776 .glibc_crt_file => |crt_file| {1873 .glibc_crt_file => |crt_file| {
1777 glibc.buildCRTFile(self, crt_file) catch |err| {1874 glibc.buildCRTFile(self, crt_file) catch |err| {
1778 // TODO Expose this as a normal compile error rather than crashing here.1875 // TODO Surface more error details.
1779 fatal("unable to build glibc CRT file: {s}", .{@errorName(err)});1876 try self.setMiscFailure(.glibc_crt_file, "unable to build glibc CRT file: {s}", .{
1877 @errorName(err),
1878 });
1780 };1879 };
1781 },1880 },
1782 .glibc_shared_objects => {1881 .glibc_shared_objects => {
1783 glibc.buildSharedObjects(self) catch |err| {1882 glibc.buildSharedObjects(self) catch |err| {
1784 // TODO Expose this as a normal compile error rather than crashing here.1883 // TODO Surface more error details.
1785 fatal("unable to build glibc shared objects: {s}", .{@errorName(err)});1884 try self.setMiscFailure(
1885 .glibc_shared_objects,
1886 "unable to build glibc shared objects: {s}",
1887 .{@errorName(err)},
1888 );
1786 };1889 };
1787 },1890 },
1788 .musl_crt_file => |crt_file| {1891 .musl_crt_file => |crt_file| {
1789 musl.buildCRTFile(self, crt_file) catch |err| {1892 musl.buildCRTFile(self, crt_file) catch |err| {
1790 // TODO Expose this as a normal compile error rather than crashing here.1893 // TODO Surface more error details.
1791 fatal("unable to build musl CRT file: {s}", .{@errorName(err)});1894 try self.setMiscFailure(
1895 .musl_crt_file,
1896 "unable to build musl CRT file: {s}",
1897 .{@errorName(err)},
1898 );
1792 };1899 };
1793 },1900 },
1794 .mingw_crt_file => |crt_file| {1901 .mingw_crt_file => |crt_file| {
1795 mingw.buildCRTFile(self, crt_file) catch |err| {1902 mingw.buildCRTFile(self, crt_file) catch |err| {
1796 // TODO Expose this as a normal compile error rather than crashing here.1903 // TODO Surface more error details.
1797 fatal("unable to build mingw-w64 CRT file: {s}", .{@errorName(err)});1904 try self.setMiscFailure(
1905 .mingw_crt_file,
1906 "unable to build mingw-w64 CRT file: {s}",
1907 .{@errorName(err)},
1908 );
1798 };1909 };
1799 },1910 },
1800 .windows_import_lib => |index| {1911 .windows_import_lib => |index| {
1801 const link_lib = self.bin_file.options.system_libs.items()[index].key;1912 const link_lib = self.bin_file.options.system_libs.items()[index].key;
1802 mingw.buildImportLib(self, link_lib) catch |err| {1913 mingw.buildImportLib(self, link_lib) catch |err| {
1803 // TODO Expose this as a normal compile error rather than crashing here.1914 // TODO Surface more error details.
1804 fatal("unable to generate DLL import .lib file: {s}", .{@errorName(err)});1915 try self.setMiscFailure(
1916 .windows_import_lib,
1917 "unable to generate DLL import .lib file: {s}",
1918 .{@errorName(err)},
1919 );
1805 };1920 };
1806 },1921 },
1807 .libunwind => {1922 .libunwind => {
1808 libunwind.buildStaticLib(self) catch |err| {1923 libunwind.buildStaticLib(self) catch |err| {
1809 // TODO Expose this as a normal compile error rather than crashing here.1924 // TODO Surface more error details.
1810 fatal("unable to build libunwind: {s}", .{@errorName(err)});1925 try self.setMiscFailure(
1926 .libunwind,
1927 "unable to build libunwind: {s}",
1928 .{@errorName(err)},
1929 );
1811 };1930 };
1812 },1931 },
1813 .libcxx => {1932 .libcxx => {
1814 libcxx.buildLibCXX(self) catch |err| {1933 libcxx.buildLibCXX(self) catch |err| {
1815 // TODO Expose this as a normal compile error rather than crashing here.1934 // TODO Surface more error details.
1816 fatal("unable to build libcxx: {s}", .{@errorName(err)});1935 try self.setMiscFailure(
1936 .libcxx,
1937 "unable to build libcxx: {s}",
1938 .{@errorName(err)},
1939 );
1817 };1940 };
1818 },1941 },
1819 .libcxxabi => {1942 .libcxxabi => {
1820 libcxx.buildLibCXXABI(self) catch |err| {1943 libcxx.buildLibCXXABI(self) catch |err| {
1821 // TODO Expose this as a normal compile error rather than crashing here.1944 // TODO Surface more error details.
1822 fatal("unable to build libcxxabi: {s}", .{@errorName(err)});1945 try self.setMiscFailure(
1946 .libcxxabi,
1947 "unable to build libcxxabi: {s}",
1948 .{@errorName(err)},
1949 );
1823 };1950 };
1824 },1951 },
1825 .libtsan => {1952 .libtsan => {
1826 libtsan.buildTsan(self) catch |err| {1953 libtsan.buildTsan(self) catch |err| {
1827 // TODO Expose this as a normal compile error rather than crashing here.1954 // TODO Surface more error details.
1828 fatal("unable to build TSAN library: {s}", .{@errorName(err)});1955 try self.setMiscFailure(
1956 .libtsan,
1957 "unable to build TSAN library: {s}",
1958 .{@errorName(err)},
1959 );
1829 };1960 };
1830 },1961 },
1831 .compiler_rt_lib => {1962 .compiler_rt_lib => {
1832 self.buildOutputFromZig("compiler_rt.zig", .Lib, &self.compiler_rt_static_lib) catch |err| {1963 self.buildOutputFromZig(
1833 // TODO Expose this as a normal compile error rather than crashing here.1964 "compiler_rt.zig",
1834 fatal("unable to build compiler_rt: {s}", .{@errorName(err)});1965 .Lib,
1966 &self.compiler_rt_static_lib,
1967 .compiler_rt,
1968 ) catch |err| switch (err) {
1969 error.OutOfMemory => return error.OutOfMemory,
1970 error.SubCompilationFailed => continue, // error reported already
1971 else => try self.setMiscFailure(
1972 .compiler_rt,
1973 "unable to build compiler_rt: {s}",
1974 .{@errorName(err)},
1975 ),
1835 };1976 };
1836 },1977 },
1837 .compiler_rt_obj => {1978 .compiler_rt_obj => {
1838 self.buildOutputFromZig("compiler_rt.zig", .Obj, &self.compiler_rt_obj) catch |err| {1979 self.buildOutputFromZig(
1839 // TODO Expose this as a normal compile error rather than crashing here.1980 "compiler_rt.zig",
1840 fatal("unable to build compiler_rt: {s}", .{@errorName(err)});1981 .Obj,
1982 &self.compiler_rt_obj,
1983 .compiler_rt,
1984 ) catch |err| switch (err) {
1985 error.OutOfMemory => return error.OutOfMemory,
1986 error.SubCompilationFailed => continue, // error reported already
1987 else => try self.setMiscFailure(
1988 .compiler_rt,
1989 "unable to build compiler_rt: {s}",
1990 .{@errorName(err)},
1991 ),
1841 };1992 };
1842 },1993 },
1843 .libssp => {1994 .libssp => {
1844 self.buildOutputFromZig("ssp.zig", .Lib, &self.libssp_static_lib) catch |err| {1995 self.buildOutputFromZig(
1845 // TODO Expose this as a normal compile error rather than crashing here.1996 "ssp.zig",
1846 fatal("unable to build libssp: {s}", .{@errorName(err)});1997 .Lib,
1998 &self.libssp_static_lib,
1999 .libssp,
2000 ) catch |err| switch (err) {
2001 error.OutOfMemory => return error.OutOfMemory,
2002 error.SubCompilationFailed => continue, // error reported already
2003 else => try self.setMiscFailure(
2004 .libssp,
2005 "unable to build libssp: {s}",
2006 .{@errorName(err)},
2007 ),
1847 };2008 };
1848 },2009 },
1849 .zig_libc => {2010 .zig_libc => {
1850 self.buildOutputFromZig("c.zig", .Lib, &self.libc_static_lib) catch |err| {2011 self.buildOutputFromZig(
1851 // TODO Expose this as a normal compile error rather than crashing here.2012 "c.zig",
1852 fatal("unable to build zig's multitarget libc: {s}", .{@errorName(err)});2013 .Lib,
2014 &self.libc_static_lib,
2015 .zig_libc,
2016 ) catch |err| switch (err) {
2017 error.OutOfMemory => return error.OutOfMemory,
2018 error.SubCompilationFailed => continue, // error reported already
2019 else => try self.setMiscFailure(
2020 .zig_libc,
2021 "unable to build zig's multitarget libc: {s}",
2022 .{@errorName(err)},
2023 ),
1853 };2024 };
1854 },2025 },
1855 .generate_builtin_zig => {2026 .generate_builtin_zig => {
1856 // This Job is only queued up if there is a zig module.2027 // This Job is only queued up if there is a zig module.
1857 self.updateBuiltinZigFile(self.bin_file.options.module.?) catch |err| {2028 try self.updateBuiltinZigFile(self.bin_file.options.module.?);
1858 // TODO Expose this as a normal compile error rather than crashing here.
1859 fatal("unable to update builtin.zig file: {s}", .{@errorName(err)});
1860 };
1861 },2029 },
1862 .stage1_module => {2030 .stage1_module => {
1863 if (!build_options.is_stage1)2031 if (!build_options.is_stage1)
...@@ -2858,13 +3026,31 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool {...@@ -2858,13 +3026,31 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool {
2858 target_util.libcNeedsLibUnwind(comp.getTarget());3026 target_util.libcNeedsLibUnwind(comp.getTarget());
2859}3027}
28603028
2861fn updateBuiltinZigFile(comp: *Compilation, mod: *Module) !void {3029fn updateBuiltinZigFile(comp: *Compilation, mod: *Module) Allocator.Error!void {
2862 const tracy = trace(@src());3030 const tracy = trace(@src());
2863 defer tracy.end();3031 defer tracy.end();
28643032
2865 const source = try comp.generateBuiltinZigSource(comp.gpa);3033 const source = try comp.generateBuiltinZigSource(comp.gpa);
2866 defer comp.gpa.free(source);3034 defer comp.gpa.free(source);
2867 try mod.zig_cache_artifact_directory.handle.writeFile("builtin.zig", source);3035
3036 mod.zig_cache_artifact_directory.handle.writeFile("builtin.zig", source) catch |err| {
3037 const dir_path: []const u8 = mod.zig_cache_artifact_directory.path orelse ".";
3038 try comp.setMiscFailure(.write_builtin_zig, "unable to write builtin.zig to {s}: {s}", .{
3039 dir_path,
3040 @errorName(err),
3041 });
3042 };
3043}
3044
3045fn setMiscFailure(
3046 comp: *Compilation,
3047 tag: MiscTask,
3048 comptime format: []const u8,
3049 args: anytype,
3050) Allocator.Error!void {
3051 try comp.misc_failures.ensureCapacity(comp.gpa, comp.misc_failures.count() + 1);
3052 const msg = try std.fmt.allocPrint(comp.gpa, format, args);
3053 comp.misc_failures.putAssumeCapacityNoClobber(tag, .{ .msg = msg });
2868}3054}
28693055
2870pub fn dump_argv(argv: []const []const u8) void {3056pub fn dump_argv(argv: []const []const u8) void {
...@@ -2874,7 +3060,7 @@ pub fn dump_argv(argv: []const []const u8) void {...@@ -2874,7 +3060,7 @@ pub fn dump_argv(argv: []const []const u8) void {
2874 std.debug.print("{s}\n", .{argv[argv.len - 1]});3060 std.debug.print("{s}\n", .{argv[argv.len - 1]});
2875}3061}
28763062
2877pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 {3063pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Allocator.Error![]u8 {
2878 const tracy = trace(@src());3064 const tracy = trace(@src());
2879 defer tracy.end();3065 defer tracy.end();
28803066
...@@ -3071,6 +3257,10 @@ pub fn updateSubCompilation(sub_compilation: *Compilation) !void {...@@ -3071,6 +3257,10 @@ pub fn updateSubCompilation(sub_compilation: *Compilation) !void {
3071 try sub_compilation.update();3257 try sub_compilation.update();
30723258
3073 // Look for compilation errors in this sub_compilation3259 // Look for compilation errors in this sub_compilation
3260 // TODO instead of logging these errors, handle them in the callsites
3261 // of updateSubCompilation and attach them as sub-errors, properly
3262 // surfacing the errors. You can see an example of this already
3263 // done inside buildOutputFromZig.
3074 var errors = try sub_compilation.getAllErrorsAlloc();3264 var errors = try sub_compilation.getAllErrorsAlloc();
3075 defer errors.deinit(sub_compilation.gpa);3265 defer errors.deinit(sub_compilation.gpa);
30763266
...@@ -3099,6 +3289,7 @@ fn buildOutputFromZig(...@@ -3099,6 +3289,7 @@ fn buildOutputFromZig(
3099 src_basename: []const u8,3289 src_basename: []const u8,
3100 output_mode: std.builtin.OutputMode,3290 output_mode: std.builtin.OutputMode,
3101 out: *?CRTFile,3291 out: *?CRTFile,
3292 misc_task_tag: MiscTask,
3102) !void {3293) !void {
3103 const tracy = trace(@src());3294 const tracy = trace(@src());
3104 defer tracy.end();3295 defer tracy.end();
...@@ -3173,7 +3364,23 @@ fn buildOutputFromZig(...@@ -3173,7 +3364,23 @@ fn buildOutputFromZig(
3173 });3364 });
3174 defer sub_compilation.destroy();3365 defer sub_compilation.destroy();
31753366
3176 try sub_compilation.updateSubCompilation();3367 try sub_compilation.update();
3368 // Look for compilation errors in this sub_compilation.
3369 var keep_errors = false;
3370 var errors = try sub_compilation.getAllErrorsAlloc();
3371 defer if (!keep_errors) errors.deinit(sub_compilation.gpa);
3372
3373 if (errors.list.len != 0) {
3374 try comp.misc_failures.ensureCapacity(comp.gpa, comp.misc_failures.count() + 1);
3375 comp.misc_failures.putAssumeCapacityNoClobber(misc_task_tag, .{
3376 .msg = try std.fmt.allocPrint(comp.gpa, "sub-compilation of {s} failed", .{
3377 @tagName(misc_task_tag),
3378 }),
3379 .children = errors,
3380 });
3381 keep_errors = true;
3382 return error.SubCompilationFailed;
3383 }
31773384
3178 assert(out.* == null);3385 assert(out.* == null);
3179 out.* = Compilation.CRTFile{3386 out.* = Compilation.CRTFile{
src/main.zig+4-1
...@@ -2623,7 +2623,10 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v...@@ -2623,7 +2623,10 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
2623 };2623 };
2624 defer comp.destroy();2624 defer comp.destroy();
26252625
2626 try updateModule(gpa, comp, .none);2626 updateModule(gpa, comp, .none) catch |err| switch (err) {
2627 error.SemanticAnalyzeFail => process.exit(1),
2628 else => |e| return e,
2629 };
2627 try comp.makeBinFileExecutable();2630 try comp.makeBinFileExecutable();
26282631
2629 child_argv.items[argv_index_exe] = try comp.bin_file.options.emit.?.directory.join(2632 child_argv.items[argv_index_exe] = try comp.bin_file.options.emit.?.directory.join(