authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-07-19 01:04:59-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-07-19 22:35:33-07:00
log4f742c4cfc3c3134a0d6ebfdfc354286ae97b2c1
treec20b44dbe98cb8cb7484b19aca727ad2957e42a2
parentb7e48c6bcd99457f84f0043a3f4590a6ac1f4933

dev: introduce dev environments that enable compiler feature sets


16 files changed, 518 insertions(+), 235 deletions(-)

CMakeLists.txt+1
...@@ -578,6 +578,7 @@ set(ZIG_STAGE2_SOURCES...@@ -578,6 +578,7 @@ set(ZIG_STAGE2_SOURCES
578 src/codegen/spirv/Section.zig578 src/codegen/spirv/Section.zig
579 src/codegen/spirv/spec.zig579 src/codegen/spirv/spec.zig
580 src/crash_report.zig580 src/crash_report.zig
581 src/dev.zig
581 src/glibc.zig582 src/glibc.zig
582 src/introspect.zig583 src/introspect.zig
583 src/libcxx.zig584 src/libcxx.zig
bootstrap.c+1-2
...@@ -140,8 +140,7 @@ int main(int argc, char **argv) {...@@ -140,8 +140,7 @@ int main(int argc, char **argv) {
140 "pub const value_tracing = false;\n"140 "pub const value_tracing = false;\n"
141 "pub const skip_non_native = false;\n"141 "pub const skip_non_native = false;\n"
142 "pub const force_gpa = false;\n"142 "pub const force_gpa = false;\n"
143 "pub const only_c = false;\n"143 "pub const dev = .core;\n"
144 "pub const only_core_functionality = true;\n"
145 , zig_version);144 , zig_version);
146 if (written < 100)145 if (written < 100)
147 panic("unable to write to config.zig file");146 panic("unable to write to config.zig file");
build.zig+4-6
...@@ -8,6 +8,7 @@ const io = std.io;...@@ -8,6 +8,7 @@ const io = std.io;
8const fs = std.fs;8const fs = std.fs;
9const InstallDirectoryOptions = std.Build.InstallDirectoryOptions;9const InstallDirectoryOptions = std.Build.InstallDirectoryOptions;
10const assert = std.debug.assert;10const assert = std.debug.assert;
11const DevEnv = @import("src/dev.zig").Env;
1112
12const zig_version: std.SemanticVersion = .{ .major = 0, .minor = 14, .patch = 0 };13const zig_version: std.SemanticVersion = .{ .major = 0, .minor = 14, .patch = 0 };
13const stack_size = 32 * 1024 * 1024;14const stack_size = 32 * 1024 * 1024;
...@@ -232,8 +233,7 @@ pub fn build(b: *std.Build) !void {...@@ -232,8 +233,7 @@ pub fn build(b: *std.Build) !void {
232 exe_options.addOption(bool, "llvm_has_arc", llvm_has_arc);233 exe_options.addOption(bool, "llvm_has_arc", llvm_has_arc);
233 exe_options.addOption(bool, "llvm_has_xtensa", llvm_has_xtensa);234 exe_options.addOption(bool, "llvm_has_xtensa", llvm_has_xtensa);
234 exe_options.addOption(bool, "force_gpa", force_gpa);235 exe_options.addOption(bool, "force_gpa", force_gpa);
235 exe_options.addOption(bool, "only_c", only_c);236 exe_options.addOption(DevEnv, "dev", b.option(DevEnv, "dev", "Build a compiler with a reduced feature set for development of specific features") orelse if (only_c) .bootstrap else .full);
236 exe_options.addOption(bool, "only_core_functionality", only_c);
237237
238 if (link_libc) {238 if (link_libc) {
239 exe.linkLibC();239 exe.linkLibC();
...@@ -393,8 +393,6 @@ pub fn build(b: *std.Build) !void {...@@ -393,8 +393,6 @@ pub fn build(b: *std.Build) !void {
393 test_cases_options.addOption(bool, "llvm_has_arc", llvm_has_arc);393 test_cases_options.addOption(bool, "llvm_has_arc", llvm_has_arc);
394 test_cases_options.addOption(bool, "llvm_has_xtensa", llvm_has_xtensa);394 test_cases_options.addOption(bool, "llvm_has_xtensa", llvm_has_xtensa);
395 test_cases_options.addOption(bool, "force_gpa", force_gpa);395 test_cases_options.addOption(bool, "force_gpa", force_gpa);
396 test_cases_options.addOption(bool, "only_c", only_c);
397 test_cases_options.addOption(bool, "only_core_functionality", true);
398 test_cases_options.addOption(bool, "enable_qemu", b.enable_qemu);396 test_cases_options.addOption(bool, "enable_qemu", b.enable_qemu);
399 test_cases_options.addOption(bool, "enable_wine", b.enable_wine);397 test_cases_options.addOption(bool, "enable_wine", b.enable_wine);
400 test_cases_options.addOption(bool, "enable_wasmtime", b.enable_wasmtime);398 test_cases_options.addOption(bool, "enable_wasmtime", b.enable_wasmtime);
...@@ -406,6 +404,7 @@ pub fn build(b: *std.Build) !void {...@@ -406,6 +404,7 @@ pub fn build(b: *std.Build) !void {
406 test_cases_options.addOption([:0]const u8, "version", version);404 test_cases_options.addOption([:0]const u8, "version", version);
407 test_cases_options.addOption(std.SemanticVersion, "semver", semver);405 test_cases_options.addOption(std.SemanticVersion, "semver", semver);
408 test_cases_options.addOption([]const []const u8, "test_filters", test_filters);406 test_cases_options.addOption([]const []const u8, "test_filters", test_filters);
407 test_cases_options.addOption(DevEnv, "dev", if (only_c) .bootstrap else .core);
409408
410 var chosen_opt_modes_buf: [4]builtin.OptimizeMode = undefined;409 var chosen_opt_modes_buf: [4]builtin.OptimizeMode = undefined;
411 var chosen_mode_index: usize = 0;410 var chosen_mode_index: usize = 0;
...@@ -575,7 +574,6 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {...@@ -575,7 +574,6 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
575 exe_options.addOption(u32, "mem_leak_frames", 0);574 exe_options.addOption(u32, "mem_leak_frames", 0);
576 exe_options.addOption(bool, "have_llvm", false);575 exe_options.addOption(bool, "have_llvm", false);
577 exe_options.addOption(bool, "force_gpa", false);576 exe_options.addOption(bool, "force_gpa", false);
578 exe_options.addOption(bool, "only_c", true);
579 exe_options.addOption([:0]const u8, "version", version);577 exe_options.addOption([:0]const u8, "version", version);
580 exe_options.addOption(std.SemanticVersion, "semver", semver);578 exe_options.addOption(std.SemanticVersion, "semver", semver);
581 exe_options.addOption(bool, "enable_debug_extensions", false);579 exe_options.addOption(bool, "enable_debug_extensions", false);
...@@ -585,7 +583,7 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {...@@ -585,7 +583,7 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
585 exe_options.addOption(bool, "enable_tracy_callstack", false);583 exe_options.addOption(bool, "enable_tracy_callstack", false);
586 exe_options.addOption(bool, "enable_tracy_allocation", false);584 exe_options.addOption(bool, "enable_tracy_allocation", false);
587 exe_options.addOption(bool, "value_tracing", false);585 exe_options.addOption(bool, "value_tracing", false);
588 exe_options.addOption(bool, "only_core_functionality", true);586 exe_options.addOption(DevEnv, "dev", .bootstrap);
589587
590 const run_opt = b.addSystemCommand(&.{588 const run_opt = b.addSystemCommand(&.{
591 "wasm-opt",589 "wasm-opt",
src/Compilation.zig+73-69
...@@ -38,6 +38,7 @@ const Zir = std.zig.Zir;...@@ -38,6 +38,7 @@ const Zir = std.zig.Zir;
38const Air = @import("Air.zig");38const Air = @import("Air.zig");
39const Builtin = @import("Builtin.zig");39const Builtin = @import("Builtin.zig");
40const LlvmObject = @import("codegen/llvm.zig").Object;40const LlvmObject = @import("codegen/llvm.zig").Object;
41const dev = @import("dev.zig");
4142
42pub const Config = @import("Compilation/Config.zig");43pub const Config = @import("Compilation/Config.zig");
4344
...@@ -94,8 +95,15 @@ native_system_include_paths: []const []const u8,...@@ -94,8 +95,15 @@ native_system_include_paths: []const []const u8,
94force_undefined_symbols: std.StringArrayHashMapUnmanaged(void),95force_undefined_symbols: std.StringArrayHashMapUnmanaged(void),
9596
96c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{},97c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{},
97win32_resource_table: if (build_options.only_core_functionality) void else std.AutoArrayHashMapUnmanaged(*Win32Resource, void) =98win32_resource_table: if (dev.env.supports(.win32_resource)) std.AutoArrayHashMapUnmanaged(*Win32Resource, void) else struct {
98 if (build_options.only_core_functionality) {} else .{},99 pub fn keys(_: @This()) [0]void {
100 return .{};
101 }
102 pub fn count(_: @This()) u0 {
103 return 0;
104 }
105 pub fn deinit(_: @This(), _: Allocator) void {}
106} = .{},
99107
100link_error_flags: link.File.ErrorFlags = .{},108link_error_flags: link.File.ErrorFlags = .{},
101link_errors: std.ArrayListUnmanaged(link.File.ErrorMsg) = .{},109link_errors: std.ArrayListUnmanaged(link.File.ErrorMsg) = .{},
...@@ -125,7 +133,13 @@ c_object_work_queue: std.fifo.LinearFifo(*CObject, .Dynamic),...@@ -125,7 +133,13 @@ c_object_work_queue: std.fifo.LinearFifo(*CObject, .Dynamic),
125133
126/// These jobs are to invoke the RC compiler to create a compiled resource file (.res), which134/// These jobs are to invoke the RC compiler to create a compiled resource file (.res), which
127/// gets linked with the Compilation.135/// gets linked with the Compilation.
128win32_resource_work_queue: if (build_options.only_core_functionality) void else std.fifo.LinearFifo(*Win32Resource, .Dynamic),136win32_resource_work_queue: if (dev.env.supports(.win32_resource)) std.fifo.LinearFifo(*Win32Resource, .Dynamic) else struct {
137 pub fn ensureUnusedCapacity(_: @This(), _: u0) error{}!void {}
138 pub fn readItem(_: @This()) ?noreturn {
139 return null;
140 }
141 pub fn deinit(_: @This()) void {}
142},
129143
130/// These jobs are to tokenize, parse, and astgen files, which may be outdated144/// These jobs are to tokenize, parse, and astgen files, which may be outdated
131/// since the last compilation, as well as scan for `@import` and queue up145/// since the last compilation, as well as scan for `@import` and queue up
...@@ -142,8 +156,12 @@ failed_c_objects: std.AutoArrayHashMapUnmanaged(*CObject, *CObject.Diag.Bundle)...@@ -142,8 +156,12 @@ failed_c_objects: std.AutoArrayHashMapUnmanaged(*CObject, *CObject.Diag.Bundle)
142156
143/// The ErrorBundle memory is owned by the `Win32Resource`, using Compilation's general purpose allocator.157/// The ErrorBundle memory is owned by the `Win32Resource`, using Compilation's general purpose allocator.
144/// This data is accessed by multiple threads and is protected by `mutex`.158/// This data is accessed by multiple threads and is protected by `mutex`.
145failed_win32_resources: if (build_options.only_core_functionality) void else std.AutoArrayHashMapUnmanaged(*Win32Resource, ErrorBundle) =159failed_win32_resources: if (dev.env.supports(.win32_resource)) std.AutoArrayHashMapUnmanaged(*Win32Resource, ErrorBundle) else struct {
146 if (build_options.only_core_functionality) {} else .{},160 pub fn values(_: @This()) [0]void {
161 return .{};
162 }
163 pub fn deinit(_: @This(), _: Allocator) void {}
164} = .{},
147165
148/// Miscellaneous things that can fail.166/// Miscellaneous things that can fail.
149misc_failures: std.AutoArrayHashMapUnmanaged(MiscTask, MiscError) = .{},167misc_failures: std.AutoArrayHashMapUnmanaged(MiscTask, MiscError) = .{},
...@@ -1484,7 +1502,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1484,7 +1502,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1484 .done = false,1502 .done = false,
1485 },1503 },
1486 .c_object_work_queue = std.fifo.LinearFifo(*CObject, .Dynamic).init(gpa),1504 .c_object_work_queue = std.fifo.LinearFifo(*CObject, .Dynamic).init(gpa),
1487 .win32_resource_work_queue = if (build_options.only_core_functionality) {} else std.fifo.LinearFifo(*Win32Resource, .Dynamic).init(gpa),1505 .win32_resource_work_queue = if (dev.env.supports(.win32_resource)) std.fifo.LinearFifo(*Win32Resource, .Dynamic).init(gpa) else .{},
1488 .astgen_work_queue = std.fifo.LinearFifo(Zcu.File.Index, .Dynamic).init(gpa),1506 .astgen_work_queue = std.fifo.LinearFifo(Zcu.File.Index, .Dynamic).init(gpa),
1489 .embed_file_work_queue = std.fifo.LinearFifo(*Zcu.EmbedFile, .Dynamic).init(gpa),1507 .embed_file_work_queue = std.fifo.LinearFifo(*Zcu.EmbedFile, .Dynamic).init(gpa),
1490 .c_source_files = options.c_source_files,1508 .c_source_files = options.c_source_files,
...@@ -1711,7 +1729,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1711,7 +1729,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1711 comp.emit_llvm_ir != null or1729 comp.emit_llvm_ir != null or
1712 comp.emit_llvm_bc != null))1730 comp.emit_llvm_bc != null))
1713 {1731 {
1714 if (build_options.only_c) unreachable;1732 dev.check(.llvm_backend);
1715 if (opt_zcu) |zcu| zcu.llvm_object = try LlvmObject.create(arena, comp);1733 if (opt_zcu) |zcu| zcu.llvm_object = try LlvmObject.create(arena, comp);
1716 }1734 }
17171735
...@@ -1738,8 +1756,11 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1738,8 +1756,11 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1738 }1756 }
17391757
1740 // Add a `Win32Resource` for each `rc_source_files` and one for `manifest_file`.1758 // Add a `Win32Resource` for each `rc_source_files` and one for `manifest_file`.
1741 if (!build_options.only_core_functionality) {1759 const win32_resource_count =
1742 try comp.win32_resource_table.ensureTotalCapacity(gpa, options.rc_source_files.len + @intFromBool(options.manifest_file != null));1760 options.rc_source_files.len + @intFromBool(options.manifest_file != null);
1761 if (win32_resource_count > 0) {
1762 dev.check(.win32_resource);
1763 try comp.win32_resource_table.ensureTotalCapacity(gpa, win32_resource_count);
1743 for (options.rc_source_files) |rc_source_file| {1764 for (options.rc_source_files) |rc_source_file| {
1744 const win32_resource = try gpa.create(Win32Resource);1765 const win32_resource = try gpa.create(Win32Resource);
1745 errdefer gpa.destroy(win32_resource);1766 errdefer gpa.destroy(win32_resource);
...@@ -1905,9 +1926,7 @@ pub fn destroy(comp: *Compilation) void {...@@ -1905,9 +1926,7 @@ pub fn destroy(comp: *Compilation) void {
1905 for (comp.work_queues) |work_queue| work_queue.deinit();1926 for (comp.work_queues) |work_queue| work_queue.deinit();
1906 if (!InternPool.single_threaded) comp.codegen_work.queue.deinit();1927 if (!InternPool.single_threaded) comp.codegen_work.queue.deinit();
1907 comp.c_object_work_queue.deinit();1928 comp.c_object_work_queue.deinit();
1908 if (!build_options.only_core_functionality) {1929 comp.win32_resource_work_queue.deinit();
1909 comp.win32_resource_work_queue.deinit();
1910 }
1911 comp.astgen_work_queue.deinit();1930 comp.astgen_work_queue.deinit();
1912 comp.embed_file_work_queue.deinit();1931 comp.embed_file_work_queue.deinit();
19131932
...@@ -1956,17 +1975,15 @@ pub fn destroy(comp: *Compilation) void {...@@ -1956,17 +1975,15 @@ pub fn destroy(comp: *Compilation) void {
1956 }1975 }
1957 comp.failed_c_objects.deinit(gpa);1976 comp.failed_c_objects.deinit(gpa);
19581977
1959 if (!build_options.only_core_functionality) {1978 for (comp.win32_resource_table.keys()) |key| {
1960 for (comp.win32_resource_table.keys()) |key| {1979 key.destroy(gpa);
1961 key.destroy(gpa);1980 }
1962 }1981 comp.win32_resource_table.deinit(gpa);
1963 comp.win32_resource_table.deinit(gpa);
19641982
1965 for (comp.failed_win32_resources.values()) |*value| {1983 for (comp.failed_win32_resources.values()) |*value| {
1966 value.deinit(gpa);1984 value.deinit(gpa);
1967 }
1968 comp.failed_win32_resources.deinit(gpa);
1969 }1985 }
1986 comp.failed_win32_resources.deinit(gpa);
19701987
1971 for (comp.link_errors.items) |*item| item.deinit(gpa);1988 for (comp.link_errors.items) |*item| item.deinit(gpa);
1972 comp.link_errors.deinit(gpa);1989 comp.link_errors.deinit(gpa);
...@@ -2153,17 +2170,15 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {...@@ -2153,17 +2170,15 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
21532170
2154 // For compiling Win32 resources, we rely on the cache hash system to avoid duplicating work.2171 // For compiling Win32 resources, we rely on the cache hash system to avoid duplicating work.
2155 // Add a Job for each Win32 resource file.2172 // Add a Job for each Win32 resource file.
2156 if (!build_options.only_core_functionality) {2173 try comp.win32_resource_work_queue.ensureUnusedCapacity(comp.win32_resource_table.count());
2157 try comp.win32_resource_work_queue.ensureUnusedCapacity(comp.win32_resource_table.count());2174 for (comp.win32_resource_table.keys()) |key| {
2158 for (comp.win32_resource_table.keys()) |key| {2175 comp.win32_resource_work_queue.writeItemAssumeCapacity(key);
2159 comp.win32_resource_work_queue.writeItemAssumeCapacity(key);2176 }
2160 }2177 if (comp.file_system_inputs) |fsi| {
2161 if (comp.file_system_inputs) |fsi| {2178 for (comp.win32_resource_table.keys()) |win32_resource| switch (win32_resource.src) {
2162 for (comp.win32_resource_table.keys()) |win32_resource| switch (win32_resource.src) {2179 .rc => |f| try comp.appendFileSystemInput(fsi, Cache.Path.cwd(), f.src_path),
2163 .rc => |f| try comp.appendFileSystemInput(fsi, Cache.Path.cwd(), f.src_path),2180 .manifest => continue,
2164 .manifest => continue,2181 };
2165 };
2166 }
2167 }2182 }
21682183
2169 if (comp.module) |zcu| {2184 if (comp.module) |zcu| {
...@@ -2397,7 +2412,6 @@ fn flush(comp: *Compilation, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:...@@ -2397,7 +2412,6 @@ fn flush(comp: *Compilation, arena: Allocator, tid: Zcu.PerThread.Id, prog_node:
2397 try link.File.C.flushEmitH(zcu);2412 try link.File.C.flushEmitH(zcu);
23982413
2399 if (zcu.llvm_object) |llvm_object| {2414 if (zcu.llvm_object) |llvm_object| {
2400 if (build_options.only_c) unreachable;
2401 const default_emit = switch (comp.cache_use) {2415 const default_emit = switch (comp.cache_use) {
2402 .whole => |whole| .{2416 .whole => |whole| .{
2403 .directory = whole.tmp_artifact_directory.?,2417 .directory = whole.tmp_artifact_directory.?,
...@@ -2541,17 +2555,15 @@ fn addNonIncrementalStuffToCacheManifest(...@@ -2541,17 +2555,15 @@ fn addNonIncrementalStuffToCacheManifest(
2541 man.hash.addListOfBytes(key.src.extra_flags);2555 man.hash.addListOfBytes(key.src.extra_flags);
2542 }2556 }
25432557
2544 if (!build_options.only_core_functionality) {2558 for (comp.win32_resource_table.keys()) |key| {
2545 for (comp.win32_resource_table.keys()) |key| {2559 switch (key.src) {
2546 switch (key.src) {2560 .rc => |rc_src| {
2547 .rc => |rc_src| {2561 _ = try man.addFile(rc_src.src_path, null);
2548 _ = try man.addFile(rc_src.src_path, null);2562 man.hash.addListOfBytes(rc_src.extra_flags);
2549 man.hash.addListOfBytes(rc_src.extra_flags);2563 },
2550 },2564 .manifest => |manifest_path| {
2551 .manifest => |manifest_path| {2565 _ = try man.addFile(manifest_path, null);
2552 _ = try man.addFile(manifest_path, null);2566 },
2553 },
2554 }
2555 }2567 }
2556 }2568 }
25572569
...@@ -2695,8 +2707,6 @@ pub fn emitLlvmObject(...@@ -2695,8 +2707,6 @@ pub fn emitLlvmObject(
2695 llvm_object: *LlvmObject,2707 llvm_object: *LlvmObject,
2696 prog_node: std.Progress.Node,2708 prog_node: std.Progress.Node,
2697) !void {2709) !void {
2698 if (build_options.only_c) @compileError("unreachable");
2699
2700 const sub_prog_node = prog_node.start("LLVM Emit Object", 0);2710 const sub_prog_node = prog_node.start("LLVM Emit Object", 0);
2701 defer sub_prog_node.end();2711 defer sub_prog_node.end();
27022712
...@@ -2860,6 +2870,7 @@ fn reportMultiModuleErrors(pt: Zcu.PerThread) !void {...@@ -2860,6 +2870,7 @@ fn reportMultiModuleErrors(pt: Zcu.PerThread) !void {
2860/// or whatever is needed so that it can be executed.2870/// or whatever is needed so that it can be executed.
2861/// After this, one must call` makeFileWritable` before calling `update`.2871/// After this, one must call` makeFileWritable` before calling `update`.
2862pub fn makeBinFileExecutable(comp: *Compilation) !void {2872pub fn makeBinFileExecutable(comp: *Compilation) !void {
2873 if (!dev.env.supports(.make_executable)) return;
2863 const lf = comp.bin_file orelse return;2874 const lf = comp.bin_file orelse return;
2864 return lf.makeExecutable();2875 return lf.makeExecutable();
2865}2876}
...@@ -2897,6 +2908,8 @@ const Header = extern struct {...@@ -2897,6 +2908,8 @@ const Header = extern struct {
2897/// saved, such as the target and most CLI flags. A cache hit will only occur2908/// saved, such as the target and most CLI flags. A cache hit will only occur
2898/// when subsequent compiler invocations use the same set of flags.2909/// when subsequent compiler invocations use the same set of flags.
2899pub fn saveState(comp: *Compilation) !void {2910pub fn saveState(comp: *Compilation) !void {
2911 dev.check(.incremental);
2912
2900 const lf = comp.bin_file orelse return;2913 const lf = comp.bin_file orelse return;
29012914
2902 const gpa = comp.gpa;2915 const gpa = comp.gpa;
...@@ -3001,10 +3014,8 @@ pub fn totalErrorCount(comp: *Compilation) u32 {...@@ -3001,10 +3014,8 @@ pub fn totalErrorCount(comp: *Compilation) u32 {
3001 total += bundle.diags.len;3014 total += bundle.diags.len;
3002 }3015 }
30033016
3004 if (!build_options.only_core_functionality) {3017 for (comp.failed_win32_resources.values()) |errs| {
3005 for (comp.failed_win32_resources.values()) |errs| {3018 total += errs.errorMessageCount();
3006 total += errs.errorMessageCount();
3007 }
3008 }3019 }
30093020
3010 if (comp.module) |zcu| {3021 if (comp.module) |zcu| {
...@@ -3082,10 +3093,8 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {...@@ -3082,10 +3093,8 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
3082 try diag_bundle.addToErrorBundle(&bundle);3093 try diag_bundle.addToErrorBundle(&bundle);
3083 }3094 }
30843095
3085 if (!build_options.only_core_functionality) {3096 for (comp.failed_win32_resources.values()) |error_bundle| {
3086 for (comp.failed_win32_resources.values()) |error_bundle| {3097 try bundle.addBundleAsRoots(error_bundle);
3087 try bundle.addBundleAsRoots(error_bundle);
3088 }
3089 }3098 }
30903099
3091 for (comp.lld_errors.items) |lld_error| {3100 for (comp.lld_errors.items) |lld_error| {
...@@ -3509,11 +3518,10 @@ fn performAllTheWorkInner(...@@ -3509,11 +3518,10 @@ fn performAllTheWorkInner(
3509 comp.work_queue_wait_group.reset();3518 comp.work_queue_wait_group.reset();
3510 defer comp.work_queue_wait_group.wait();3519 defer comp.work_queue_wait_group.wait();
35113520
3512 if (!build_options.only_c and !build_options.only_core_functionality) {3521 if (comp.docs_emit != null) {
3513 if (comp.docs_emit != null) {3522 dev.check(.docs_emit);
3514 comp.thread_pool.spawnWg(&comp.work_queue_wait_group, workerDocsCopy, .{comp});3523 comp.thread_pool.spawnWg(&comp.work_queue_wait_group, workerDocsCopy, .{comp});
3515 comp.work_queue_wait_group.spawnManager(workerDocsWasm, .{ comp, main_progress_node });3524 comp.work_queue_wait_group.spawnManager(workerDocsWasm, .{ comp, main_progress_node });
3516 }
3517 }3525 }
35183526
3519 {3527 {
...@@ -3585,12 +3593,10 @@ fn performAllTheWorkInner(...@@ -3585,12 +3593,10 @@ fn performAllTheWorkInner(
3585 });3593 });
3586 }3594 }
35873595
3588 if (!build_options.only_core_functionality) {3596 while (comp.win32_resource_work_queue.readItem()) |win32_resource| {
3589 while (comp.win32_resource_work_queue.readItem()) |win32_resource| {3597 comp.thread_pool.spawnWg(&comp.work_queue_wait_group, workerUpdateWin32Resource, .{
3590 comp.thread_pool.spawnWg(&comp.work_queue_wait_group, workerUpdateWin32Resource, .{3598 comp, win32_resource, main_progress_node,
3591 comp, win32_resource, main_progress_node,3599 });
3592 });
3593 }
3594 }3600 }
3595 }3601 }
35963602
...@@ -3867,9 +3873,6 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre...@@ -3867,9 +3873,6 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre
3867 };3873 };
3868 },3874 },
3869 .windows_import_lib => |index| {3875 .windows_import_lib => |index| {
3870 if (build_options.only_c)
3871 @panic("building import libs not included in core functionality");
3872
3873 const named_frame = tracy.namedFrame("windows_import_lib");3876 const named_frame = tracy.namedFrame("windows_import_lib");
3874 defer named_frame.end();3877 defer named_frame.end();
38753878
...@@ -4466,7 +4469,8 @@ pub const CImportResult = struct {...@@ -4466,7 +4469,8 @@ pub const CImportResult = struct {
4466/// This API is currently coupled pretty tightly to stage1's needs; it will need to be reworked4469/// This API is currently coupled pretty tightly to stage1's needs; it will need to be reworked
4467/// a bit when we want to start using it from self-hosted.4470/// a bit when we want to start using it from self-hosted.
4468pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module) !CImportResult {4471pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module) !CImportResult {
4469 if (build_options.only_core_functionality) @panic("@cImport is not available in a zig2.c build");4472 dev.check(.translate_c_command);
4473
4470 const tracy_trace = trace(@src());4474 const tracy_trace = trace(@src());
4471 defer tracy_trace.end();4475 defer tracy_trace.end();
44724476
src/Zcu.zig+4-6
...@@ -38,6 +38,7 @@ const Alignment = InternPool.Alignment;...@@ -38,6 +38,7 @@ const Alignment = InternPool.Alignment;
38const AnalUnit = InternPool.AnalUnit;38const AnalUnit = InternPool.AnalUnit;
39const BuiltinFn = std.zig.BuiltinFn;39const BuiltinFn = std.zig.BuiltinFn;
40const LlvmObject = @import("codegen/llvm.zig").Object;40const LlvmObject = @import("codegen/llvm.zig").Object;
41const dev = @import("dev.zig");
4142
42comptime {43comptime {
43 @setEvalBranchQuota(4000);44 @setEvalBranchQuota(4000);
...@@ -57,7 +58,7 @@ comp: *Compilation,...@@ -57,7 +58,7 @@ comp: *Compilation,
57/// Usually, the LlvmObject is managed by linker code, however, in the case58/// Usually, the LlvmObject is managed by linker code, however, in the case
58/// that -fno-emit-bin is specified, the linker code never executes, so we59/// that -fno-emit-bin is specified, the linker code never executes, so we
59/// store the LlvmObject here.60/// store the LlvmObject here.
60llvm_object: ?*LlvmObject,61llvm_object: if (dev.env.supports(.llvm_backend)) ?*LlvmObject else ?noreturn,
6162
62/// Pointer to externally managed resource.63/// Pointer to externally managed resource.
63root_mod: *Package.Module,64root_mod: *Package.Module,
...@@ -2403,10 +2404,7 @@ pub fn deinit(zcu: *Zcu) void {...@@ -2403,10 +2404,7 @@ pub fn deinit(zcu: *Zcu) void {
2403 const pt: Zcu.PerThread = .{ .tid = .main, .zcu = zcu };2404 const pt: Zcu.PerThread = .{ .tid = .main, .zcu = zcu };
2404 const gpa = zcu.gpa;2405 const gpa = zcu.gpa;
24052406
2406 if (zcu.llvm_object) |llvm_object| {2407 if (zcu.llvm_object) |llvm_object| llvm_object.deinit();
2407 if (build_options.only_c) unreachable;
2408 llvm_object.deinit();
2409 }
24102408
2411 for (zcu.import_table.keys()) |key| {2409 for (zcu.import_table.keys()) |key| {
2412 gpa.free(key);2410 gpa.free(key);
...@@ -3041,7 +3039,7 @@ pub fn deleteUnitExports(zcu: *Zcu, anal_unit: AnalUnit) void {...@@ -3041,7 +3039,7 @@ pub fn deleteUnitExports(zcu: *Zcu, anal_unit: AnalUnit) void {
3041 // `updateExports` on flush).3039 // `updateExports` on flush).
3042 // This case is needed because in some rare edge cases, `Sema` wants to add and delete exports3040 // This case is needed because in some rare edge cases, `Sema` wants to add and delete exports
3043 // within a single update.3041 // within a single update.
3044 if (!build_options.only_c) {3042 if (dev.env.supports(.incremental)) {
3045 for (exports, exports_base..) |exp, export_idx| {3043 for (exports, exports_base..) |exp, export_idx| {
3046 if (zcu.comp.bin_file) |lf| {3044 if (zcu.comp.bin_file) |lf| {
3047 lf.deleteExport(exp.exported, exp.opts.name);3045 lf.deleteExport(exp.exported, exp.opts.name);
src/Zcu/PerThread.zig+9-5
...@@ -64,6 +64,7 @@ pub fn astGenFile(...@@ -64,6 +64,7 @@ pub fn astGenFile(
64 path_digest: Cache.BinDigest,64 path_digest: Cache.BinDigest,
65 opt_root_decl: Zcu.Decl.OptionalIndex,65 opt_root_decl: Zcu.Decl.OptionalIndex,
66) !void {66) !void {
67 dev.check(.ast_gen);
67 assert(!file.mod.isBuiltin());68 assert(!file.mod.isBuiltin());
6869
69 const tracy = trace(@src());70 const tracy = trace(@src());
...@@ -504,6 +505,8 @@ pub fn ensureFileAnalyzed(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.Sem...@@ -504,6 +505,8 @@ pub fn ensureFileAnalyzed(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.Sem
504/// For example an inferred error set is not resolved until after `analyzeFnBody`.505/// For example an inferred error set is not resolved until after `analyzeFnBody`.
505/// is called.506/// is called.
506pub fn ensureDeclAnalyzed(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) Zcu.SemaError!void {507pub fn ensureDeclAnalyzed(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) Zcu.SemaError!void {
508 dev.check(.sema);
509
507 const tracy = trace(@src());510 const tracy = trace(@src());
508 defer tracy.end();511 defer tracy.end();
509512
...@@ -552,9 +555,9 @@ pub fn ensureDeclAnalyzed(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) Zcu.Sem...@@ -552,9 +555,9 @@ pub fn ensureDeclAnalyzed(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) Zcu.Sem
552 }555 }
553556
554 if (was_outdated) {557 if (was_outdated) {
558 dev.check(.incremental);
555 // The exports this Decl performs will be re-discovered, so we remove them here559 // The exports this Decl performs will be re-discovered, so we remove them here
556 // prior to re-analysis.560 // prior to re-analysis.
557 if (build_options.only_c) unreachable;
558 mod.deleteUnitExports(decl_as_depender);561 mod.deleteUnitExports(decl_as_depender);
559 mod.deleteUnitReferences(decl_as_depender);562 mod.deleteUnitReferences(decl_as_depender);
560 }563 }
...@@ -623,6 +626,8 @@ pub fn ensureDeclAnalyzed(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) Zcu.Sem...@@ -623,6 +626,8 @@ pub fn ensureDeclAnalyzed(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) Zcu.Sem
623}626}
624627
625pub fn ensureFuncBodyAnalyzed(pt: Zcu.PerThread, maybe_coerced_func_index: InternPool.Index) Zcu.SemaError!void {628pub fn ensureFuncBodyAnalyzed(pt: Zcu.PerThread, maybe_coerced_func_index: InternPool.Index) Zcu.SemaError!void {
629 dev.check(.sema);
630
626 const tracy = trace(@src());631 const tracy = trace(@src());
627 defer tracy.end();632 defer tracy.end();
628633
...@@ -684,7 +689,7 @@ pub fn ensureFuncBodyAnalyzed(pt: Zcu.PerThread, maybe_coerced_func_index: Inter...@@ -684,7 +689,7 @@ pub fn ensureFuncBodyAnalyzed(pt: Zcu.PerThread, maybe_coerced_func_index: Inter
684 zcu.potentially_outdated.swapRemove(func_as_depender);689 zcu.potentially_outdated.swapRemove(func_as_depender);
685690
686 if (was_outdated) {691 if (was_outdated) {
687 if (build_options.only_c) unreachable;692 dev.check(.incremental);
688 _ = zcu.outdated_ready.swapRemove(func_as_depender);693 _ = zcu.outdated_ready.swapRemove(func_as_depender);
689 zcu.deleteUnitExports(func_as_depender);694 zcu.deleteUnitExports(func_as_depender);
690 zcu.deleteUnitReferences(func_as_depender);695 zcu.deleteUnitReferences(func_as_depender);
...@@ -836,7 +841,6 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: Ai...@@ -836,7 +841,6 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: Ai
836 },841 },
837 };842 };
838 } else if (zcu.llvm_object) |llvm_object| {843 } else if (zcu.llvm_object) |llvm_object| {
839 if (build_options.only_c) unreachable;
840 llvm_object.updateFunc(pt, func_index, air, liveness) catch |err| switch (err) {844 llvm_object.updateFunc(pt, func_index, air, liveness) catch |err| switch (err) {
841 error.OutOfMemory => return error.OutOfMemory,845 error.OutOfMemory => return error.OutOfMemory,
842 };846 };
...@@ -845,6 +849,7 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: Ai...@@ -845,6 +849,7 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: Ai
845849
846/// https://github.com/ziglang/zig/issues/14307850/// https://github.com/ziglang/zig/issues/14307
847pub fn semaPkg(pt: Zcu.PerThread, pkg: *Module) !void {851pub fn semaPkg(pt: Zcu.PerThread, pkg: *Module) !void {
852 dev.check(.sema);
848 const import_file_result = try pt.importPkg(pkg);853 const import_file_result = try pt.importPkg(pkg);
849 const root_decl_index = pt.zcu.fileRootDecl(import_file_result.file_index);854 const root_decl_index = pt.zcu.fileRootDecl(import_file_result.file_index);
850 if (root_decl_index == .none) {855 if (root_decl_index == .none) {
...@@ -2481,7 +2486,6 @@ fn processExportsInner(...@@ -2481,7 +2486,6 @@ fn processExportsInner(
2481 if (zcu.comp.bin_file) |lf| {2486 if (zcu.comp.bin_file) |lf| {
2482 try zcu.handleUpdateExports(export_indices, lf.updateExports(pt, exported, export_indices));2487 try zcu.handleUpdateExports(export_indices, lf.updateExports(pt, exported, export_indices));
2483 } else if (zcu.llvm_object) |llvm_object| {2488 } else if (zcu.llvm_object) |llvm_object| {
2484 if (build_options.only_c) unreachable;
2485 try zcu.handleUpdateExports(export_indices, llvm_object.updateExports(pt, exported, export_indices));2489 try zcu.handleUpdateExports(export_indices, llvm_object.updateExports(pt, exported, export_indices));
2486 }2490 }
2487}2491}
...@@ -2654,7 +2658,6 @@ pub fn linkerUpdateDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) !void {...@@ -2654,7 +2658,6 @@ pub fn linkerUpdateDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) !void {
2654 },2658 },
2655 };2659 };
2656 } else if (zcu.llvm_object) |llvm_object| {2660 } else if (zcu.llvm_object) |llvm_object| {
2657 if (build_options.only_c) unreachable;
2658 llvm_object.updateDecl(pt, decl_index) catch |err| switch (err) {2661 llvm_object.updateDecl(pt, decl_index) catch |err| switch (err) {
2659 error.OutOfMemory => return error.OutOfMemory,2662 error.OutOfMemory => return error.OutOfMemory,
2660 };2663 };
...@@ -3271,6 +3274,7 @@ const BigIntMutable = std.math.big.int.Mutable;...@@ -3271,6 +3274,7 @@ const BigIntMutable = std.math.big.int.Mutable;
3271const build_options = @import("build_options");3274const build_options = @import("build_options");
3272const builtin = @import("builtin");3275const builtin = @import("builtin");
3273const Cache = std.Build.Cache;3276const Cache = std.Build.Cache;
3277const dev = @import("../dev.zig");
3274const InternPool = @import("../InternPool.zig");3278const InternPool = @import("../InternPool.zig");
3275const isUpDir = @import("../introspect.zig").isUpDir;3279const isUpDir = @import("../introspect.zig").isUpDir;
3276const Liveness = @import("../Liveness.zig");3280const Liveness = @import("../Liveness.zig");
src/codegen.zig+34-16
...@@ -22,6 +22,7 @@ const Type = @import("Type.zig");...@@ -22,6 +22,7 @@ const Type = @import("Type.zig");
22const Value = @import("Value.zig");22const Value = @import("Value.zig");
23const Zir = std.zig.Zir;23const Zir = std.zig.Zir;
24const Alignment = InternPool.Alignment;24const Alignment = InternPool.Alignment;
25const dev = @import("dev.zig");
2526
26pub const Result = union(enum) {27pub const Result = union(enum) {
27 /// The `code` parameter passed to `generateSymbol` has the value ok.28 /// The `code` parameter passed to `generateSymbol` has the value ok.
...@@ -43,6 +44,23 @@ pub const DebugInfoOutput = union(enum) {...@@ -43,6 +44,23 @@ pub const DebugInfoOutput = union(enum) {
43 none,44 none,
44};45};
4546
47fn devFeatureForBackend(comptime backend: std.builtin.CompilerBackend) dev.Feature {
48 comptime assert(mem.startsWith(u8, @tagName(backend), "stage2_"));
49 return @field(dev.Feature, @tagName(backend)["stage2_".len..] ++ "_backend");
50}
51
52fn importBackend(comptime backend: std.builtin.CompilerBackend) type {
53 return switch (backend) {
54 .stage2_aarch64 => @import("arch/aarch64/CodeGen.zig"),
55 .stage2_arm => @import("arch/arm/CodeGen.zig"),
56 .stage2_riscv64 => @import("arch/riscv64/CodeGen.zig"),
57 .stage2_sparc64 => @import("arch/sparc64/CodeGen.zig"),
58 .stage2_wasm => @import("arch/wasm/CodeGen.zig"),
59 .stage2_x86_64 => @import("arch/x86_64/CodeGen.zig"),
60 else => unreachable,
61 };
62}
63
46pub fn generateFunction(64pub fn generateFunction(
47 lf: *link.File,65 lf: *link.File,
48 pt: Zcu.PerThread,66 pt: Zcu.PerThread,
...@@ -58,21 +76,18 @@ pub fn generateFunction(...@@ -58,21 +76,18 @@ pub fn generateFunction(
58 const decl = zcu.declPtr(func.owner_decl);76 const decl = zcu.declPtr(func.owner_decl);
59 const namespace = zcu.namespacePtr(decl.src_namespace);77 const namespace = zcu.namespacePtr(decl.src_namespace);
60 const target = namespace.fileScope(zcu).mod.resolved_target.result;78 const target = namespace.fileScope(zcu).mod.resolved_target.result;
61 switch (target.cpu.arch) {79 switch (target_util.zigBackend(target, false)) {
62 .arm,
63 .armeb,
64 => return @import("arch/arm/CodeGen.zig").generate(lf, pt, src_loc, func_index, air, liveness, code, debug_output),
65 .aarch64,
66 .aarch64_be,
67 .aarch64_32,
68 => return @import("arch/aarch64/CodeGen.zig").generate(lf, pt, src_loc, func_index, air, liveness, code, debug_output),
69 .riscv64 => return @import("arch/riscv64/CodeGen.zig").generate(lf, pt, src_loc, func_index, air, liveness, code, debug_output),
70 .sparc64 => return @import("arch/sparc64/CodeGen.zig").generate(lf, pt, src_loc, func_index, air, liveness, code, debug_output),
71 .x86_64 => return @import("arch/x86_64/CodeGen.zig").generate(lf, pt, src_loc, func_index, air, liveness, code, debug_output),
72 .wasm32,
73 .wasm64,
74 => return @import("arch/wasm/CodeGen.zig").generate(lf, pt, src_loc, func_index, air, liveness, code, debug_output),
75 else => unreachable,80 else => unreachable,
81 inline .stage2_aarch64,
82 .stage2_arm,
83 .stage2_riscv64,
84 .stage2_sparc64,
85 .stage2_wasm,
86 .stage2_x86_64,
87 => |backend| {
88 dev.check(devFeatureForBackend(backend));
89 return importBackend(backend).generate(lf, pt, src_loc, func_index, air, liveness, code, debug_output);
90 },
76 }91 }
77}92}
7893
...@@ -89,9 +104,12 @@ pub fn generateLazyFunction(...@@ -89,9 +104,12 @@ pub fn generateLazyFunction(
89 const decl = zcu.declPtr(decl_index);104 const decl = zcu.declPtr(decl_index);
90 const namespace = zcu.namespacePtr(decl.src_namespace);105 const namespace = zcu.namespacePtr(decl.src_namespace);
91 const target = namespace.fileScope(zcu).mod.resolved_target.result;106 const target = namespace.fileScope(zcu).mod.resolved_target.result;
92 switch (target.cpu.arch) {107 switch (target_util.zigBackend(target, false)) {
93 .x86_64 => return @import("arch/x86_64/CodeGen.zig").generateLazy(lf, pt, src_loc, lazy_sym, code, debug_output),
94 else => unreachable,108 else => unreachable,
109 inline .stage2_x86_64 => |backend| {
110 dev.check(devFeatureForBackend(backend));
111 return importBackend(backend).generateLazy(lf, pt, src_loc, lazy_sym, code, debug_output);
112 },
95 }113 }
96}114}
97115
src/codegen/llvm.zig-1
...@@ -868,7 +868,6 @@ pub const Object = struct {...@@ -868,7 +868,6 @@ pub const Object = struct {
868 pub const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, Builder.Type);868 pub const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, Builder.Type);
869869
870 pub fn create(arena: Allocator, comp: *Compilation) !*Object {870 pub fn create(arena: Allocator, comp: *Compilation) !*Object {
871 if (build_options.only_c) unreachable;
872 const gpa = comp.gpa;871 const gpa = comp.gpa;
873 const target = comp.root_mod.resolved_target.result;872 const target = comp.root_mod.resolved_target.result;
874 const llvm_target_triple = try targetTriple(arena, target);873 const llvm_target_triple = try targetTriple(arena, target);
src/dev.zig created+238
...@@ -0,0 +1,238 @@
1pub const Env = enum {
2 /// zig1 features
3 bootstrap,
4
5 /// zig2 features
6 core,
7
8 /// stage3 features
9 full,
10
11 /// - `zig cc`
12 /// - `zig c++`
13 /// - `zig translate-c`
14 c_source,
15
16 /// - `zig ast-check`
17 /// - `zig changelist`
18 /// - `zig dump-zir`
19 ast_gen,
20
21 /// - ast_gen
22 /// - `zig build-* -fno-emit-bin`
23 sema,
24
25 /// - sema
26 /// - jit command on x86_64-linux host
27 /// - `zig build-* -fno-llvm -fno-lld -target x86_64-linux`
28 @"x86_64-linux",
29
30 pub inline fn supports(comptime dev_env: Env, comptime feature: Feature) bool {
31 return switch (dev_env) {
32 .full => true,
33 .bootstrap => switch (feature) {
34 .build_exe_command,
35 .build_obj_command,
36 .ast_gen,
37 .sema,
38 .c_backend,
39 .c_linker,
40 => true,
41 else => false,
42 },
43 .core => switch (feature) {
44 .build_exe_command,
45 .build_lib_command,
46 .build_obj_command,
47 .test_command,
48 .run_command,
49 .ar_command,
50 .build_command,
51 .clang_command,
52 .stdio_listen,
53 .build_import_lib,
54 .make_executable,
55 .make_writable,
56 .incremental,
57 .ast_gen,
58 .sema,
59 .llvm_backend,
60 .c_backend,
61 .wasm_backend,
62 .arm_backend,
63 .x86_64_backend,
64 .aarch64_backend,
65 .x86_backend,
66 .riscv64_backend,
67 .sparc64_backend,
68 .spirv64_backend,
69 .lld_linker,
70 .coff_linker,
71 .elf_linker,
72 .macho_linker,
73 .c_linker,
74 .wasm_linker,
75 .spirv_linker,
76 .plan9_linker,
77 .nvptx_linker,
78 => true,
79 .cc_command,
80 .translate_c_command,
81 .jit_command,
82 .fetch_command,
83 .init_command,
84 .targets_command,
85 .version_command,
86 .env_command,
87 .zen_command,
88 .help_command,
89 .ast_check_command,
90 .detect_cpu_command,
91 .changelist_command,
92 .dump_zir_command,
93 .llvm_ints_command,
94 .docs_emit,
95 // Avoid dragging networking into zig2.c because it adds dependencies on some
96 // linker symbols that are annoying to satisfy while bootstrapping.
97 .network_listen,
98 .win32_resource,
99 => false,
100 },
101 .c_source => switch (feature) {
102 .clang_command,
103 .cc_command,
104 .translate_c_command,
105 => true,
106 else => false,
107 },
108 .ast_gen => switch (feature) {
109 .ast_check_command,
110 .changelist_command,
111 .dump_zir_command,
112 .make_executable,
113 .make_writable,
114 .incremental,
115 .ast_gen,
116 => true,
117 else => false,
118 },
119 .sema => switch (feature) {
120 .build_exe_command,
121 .build_lib_command,
122 .build_obj_command,
123 .test_command,
124 .run_command,
125 .sema,
126 => true,
127 else => Env.ast_gen.supports(feature),
128 },
129 .@"x86_64-linux" => switch (feature) {
130 .x86_64_backend,
131 .elf_linker,
132 => true,
133 else => Env.sema.supports(feature),
134 },
135 };
136 }
137
138 pub inline fn supportsAny(comptime dev_env: Env, comptime features: []const Feature) bool {
139 inline for (features) |feature| if (dev_env.supports(feature)) return true;
140 return false;
141 }
142
143 pub inline fn supportsAll(comptime dev_env: Env, comptime features: []const Feature) bool {
144 inline for (features) |feature| if (!dev_env.supports(feature)) return false;
145 return true;
146 }
147};
148
149pub const Feature = enum {
150 build_exe_command,
151 build_lib_command,
152 build_obj_command,
153 test_command,
154 run_command,
155 ar_command,
156 build_command,
157 clang_command,
158 cc_command,
159 translate_c_command,
160 jit_command,
161 fetch_command,
162 init_command,
163 targets_command,
164 version_command,
165 env_command,
166 zen_command,
167 help_command,
168 ast_check_command,
169 detect_cpu_command,
170 changelist_command,
171 dump_zir_command,
172 llvm_ints_command,
173
174 docs_emit,
175 stdio_listen,
176 network_listen,
177 build_import_lib,
178 win32_resource,
179 make_executable,
180 make_writable,
181 incremental,
182 ast_gen,
183 sema,
184
185 llvm_backend,
186 c_backend,
187 wasm_backend,
188 arm_backend,
189 x86_64_backend,
190 aarch64_backend,
191 x86_backend,
192 riscv64_backend,
193 sparc64_backend,
194 spirv64_backend,
195
196 lld_linker,
197 coff_linker,
198 elf_linker,
199 macho_linker,
200 c_linker,
201 wasm_linker,
202 spirv_linker,
203 plan9_linker,
204 nvptx_linker,
205};
206
207/// Makes the code following the call to this function unreachable if `feature` is disabled.
208pub fn check(comptime feature: Feature) if (env.supports(feature)) void else noreturn {
209 if (env.supports(feature)) return;
210 @panic("development environment " ++ @tagName(env) ++ " does not support feature " ++ @tagName(feature));
211}
212
213/// Makes the code following the call to this function unreachable if all of `features` are disabled.
214pub fn checkAny(comptime features: []const Feature) if (env.supportsAny(features)) void else noreturn {
215 if (env.supportsAny(features)) return;
216 comptime var feature_tags: []const u8 = "";
217 inline for (features[0 .. features.len - 1]) |feature| feature_tags = feature_tags ++ @tagName(feature) ++ ", ";
218 feature_tags = feature_tags ++ "or " ++ @tagName(features[features.len - 1]);
219 @panic("development environment " ++ @tagName(env) ++ " does not support feature " ++ feature_tags);
220}
221
222/// Makes the code following the call to this function unreachable if any of `features` are disabled.
223pub fn checkAll(comptime features: []const Feature) if (env.supportsAll(features)) void else noreturn {
224 if (env.supportsAll(features)) return;
225 inline for (features) |feature| if (!env.supports(feature))
226 @panic("development environment " ++ @tagName(env) ++ " does not support feature " ++ @tagName(feature));
227}
228
229const build_options = @import("build_options");
230
231pub const env: Env = if (@hasDecl(build_options, "dev"))
232 @field(Env, @tagName(build_options.dev))
233else if (@hasDecl(build_options, "only_c") and build_options.only_c)
234 .bootstrap
235else if (@hasDecl(build_options, "only_core_functionality") and build_options.only_core_functionality)
236 .core
237else
238 .full;
src/link.zig+40-37
...@@ -21,6 +21,7 @@ const Value = @import("Value.zig");...@@ -21,6 +21,7 @@ const Value = @import("Value.zig");
21const LlvmObject = @import("codegen/llvm.zig").Object;21const LlvmObject = @import("codegen/llvm.zig").Object;
22const lldMain = @import("main.zig").lldMain;22const lldMain = @import("main.zig").lldMain;
23const Package = @import("Package.zig");23const Package = @import("Package.zig");
24const dev = @import("dev.zig");
2425
25/// When adding a new field, remember to update `hashAddSystemLibs`.26/// When adding a new field, remember to update `hashAddSystemLibs`.
26/// These are *always* dynamically linked. Static libraries will be27/// These are *always* dynamically linked. Static libraries will be
...@@ -192,7 +193,7 @@ pub const File = struct {...@@ -192,7 +193,7 @@ pub const File = struct {
192 ) !*File {193 ) !*File {
193 switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) {194 switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) {
194 inline else => |tag| {195 inline else => |tag| {
195 if (tag != .c and build_options.only_c) unreachable;196 dev.check(tag.devFeature());
196 const ptr = try tag.Type().open(arena, comp, emit, options);197 const ptr = try tag.Type().open(arena, comp, emit, options);
197 return &ptr.base;198 return &ptr.base;
198 },199 },
...@@ -207,7 +208,7 @@ pub const File = struct {...@@ -207,7 +208,7 @@ pub const File = struct {
207 ) !*File {208 ) !*File {
208 switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) {209 switch (Tag.fromObjectFormat(comp.root_mod.resolved_target.result.ofmt)) {
209 inline else => |tag| {210 inline else => |tag| {
210 if (tag != .c and build_options.only_c) unreachable;211 dev.check(tag.devFeature());
211 const ptr = try tag.Type().createEmpty(arena, comp, emit, options);212 const ptr = try tag.Type().createEmpty(arena, comp, emit, options);
212 return &ptr.base;213 return &ptr.base;
213 },214 },
...@@ -219,12 +220,13 @@ pub const File = struct {...@@ -219,12 +220,13 @@ pub const File = struct {
219 }220 }
220221
221 pub fn makeWritable(base: *File) !void {222 pub fn makeWritable(base: *File) !void {
223 dev.check(.make_writable);
222 const comp = base.comp;224 const comp = base.comp;
223 const gpa = comp.gpa;225 const gpa = comp.gpa;
224 switch (base.tag) {226 switch (base.tag) {
225 .coff, .elf, .macho, .plan9, .wasm => {227 .coff, .elf, .macho, .plan9, .wasm => {
226 if (build_options.only_c) unreachable;
227 if (base.file != null) return;228 if (base.file != null) return;
229 dev.checkAny(&.{ .coff_linker, .elf_linker, .macho_linker, .plan9_linker, .wasm_linker });
228 const emit = base.emit;230 const emit = base.emit;
229 if (base.child_pid) |pid| {231 if (base.child_pid) |pid| {
230 if (builtin.os.tag == .windows) {232 if (builtin.os.tag == .windows) {
...@@ -263,11 +265,12 @@ pub const File = struct {...@@ -263,11 +265,12 @@ pub const File = struct {
263 .mode = determineMode(use_lld, output_mode, link_mode),265 .mode = determineMode(use_lld, output_mode, link_mode),
264 });266 });
265 },267 },
266 .c, .spirv, .nvptx => {},268 .c, .spirv, .nvptx => dev.checkAny(&.{ .c_linker, .spirv_linker, .nvptx_linker }),
267 }269 }
268 }270 }
269271
270 pub fn makeExecutable(base: *File) !void {272 pub fn makeExecutable(base: *File) !void {
273 dev.check(.make_executable);
271 const comp = base.comp;274 const comp = base.comp;
272 const output_mode = comp.config.output_mode;275 const output_mode = comp.config.output_mode;
273 const link_mode = comp.config.link_mode;276 const link_mode = comp.config.link_mode;
...@@ -283,7 +286,7 @@ pub const File = struct {...@@ -283,7 +286,7 @@ pub const File = struct {
283 }286 }
284 switch (base.tag) {287 switch (base.tag) {
285 .elf => if (base.file) |f| {288 .elf => if (base.file) |f| {
286 if (build_options.only_c) unreachable;289 dev.check(.elf_linker);
287 if (base.zcu_object_sub_path != null and use_lld) {290 if (base.zcu_object_sub_path != null and use_lld) {
288 // The file we have open is not the final file that we want to291 // The file we have open is not the final file that we want to
289 // make executable, so we don't have to close it.292 // make executable, so we don't have to close it.
...@@ -302,7 +305,7 @@ pub const File = struct {...@@ -302,7 +305,7 @@ pub const File = struct {
302 }305 }
303 },306 },
304 .coff, .macho, .plan9, .wasm => if (base.file) |f| {307 .coff, .macho, .plan9, .wasm => if (base.file) |f| {
305 if (build_options.only_c) unreachable;308 dev.checkAny(&.{ .coff_linker, .macho_linker, .plan9_linker, .wasm_linker });
306 if (base.zcu_object_sub_path != null) {309 if (base.zcu_object_sub_path != null) {
307 // The file we have open is not the final file that we want to310 // The file we have open is not the final file that we want to
308 // make executable, so we don't have to close it.311 // make executable, so we don't have to close it.
...@@ -321,7 +324,7 @@ pub const File = struct {...@@ -321,7 +324,7 @@ pub const File = struct {
321 }324 }
322 }325 }
323 },326 },
324 .c, .spirv, .nvptx => {},327 .c, .spirv, .nvptx => dev.checkAny(&.{ .c_linker, .spirv_linker, .nvptx_linker }),
325 }328 }
326 }329 }
327330
...@@ -366,13 +369,13 @@ pub const File = struct {...@@ -366,13 +369,13 @@ pub const File = struct {
366 /// constant. Returns the symbol index of the lowered constant in the read-only section369 /// constant. Returns the symbol index of the lowered constant in the read-only section
367 /// of the final binary.370 /// of the final binary.
368 pub fn lowerUnnamedConst(base: *File, pt: Zcu.PerThread, val: Value, decl_index: InternPool.DeclIndex) UpdateDeclError!u32 {371 pub fn lowerUnnamedConst(base: *File, pt: Zcu.PerThread, val: Value, decl_index: InternPool.DeclIndex) UpdateDeclError!u32 {
369 if (build_options.only_c) @compileError("unreachable");
370 switch (base.tag) {372 switch (base.tag) {
371 .spirv => unreachable,373 .spirv => unreachable,
372 .c => unreachable,374 .c => unreachable,
373 .nvptx => unreachable,375 .nvptx => unreachable,
374 inline else => |t| {376 inline else => |tag| {
375 return @as(*t.Type(), @fieldParentPtr("base", base)).lowerUnnamedConst(pt, val, decl_index);377 dev.check(tag.devFeature());
378 return @as(*tag.Type(), @fieldParentPtr("base", base)).lowerUnnamedConst(pt, val, decl_index);
376 },379 },
377 }380 }
378 }381 }
...@@ -383,15 +386,15 @@ pub const File = struct {...@@ -383,15 +386,15 @@ pub const File = struct {
383 /// Optionally, it is possible to specify where to expect the symbol defined if it386 /// Optionally, it is possible to specify where to expect the symbol defined if it
384 /// is an import.387 /// is an import.
385 pub fn getGlobalSymbol(base: *File, name: []const u8, lib_name: ?[]const u8) UpdateDeclError!u32 {388 pub fn getGlobalSymbol(base: *File, name: []const u8, lib_name: ?[]const u8) UpdateDeclError!u32 {
386 if (build_options.only_c) @compileError("unreachable");
387 log.debug("getGlobalSymbol '{s}' (expected in '{?s}')", .{ name, lib_name });389 log.debug("getGlobalSymbol '{s}' (expected in '{?s}')", .{ name, lib_name });
388 switch (base.tag) {390 switch (base.tag) {
389 .plan9 => unreachable,391 .plan9 => unreachable,
390 .spirv => unreachable,392 .spirv => unreachable,
391 .c => unreachable,393 .c => unreachable,
392 .nvptx => unreachable,394 .nvptx => unreachable,
393 inline else => |t| {395 inline else => |tag| {
394 return @as(*t.Type(), @fieldParentPtr("base", base)).getGlobalSymbol(name, lib_name);396 dev.check(tag.devFeature());
397 return @as(*tag.Type(), @fieldParentPtr("base", base)).getGlobalSymbol(name, lib_name);
395 },398 },
396 }399 }
397 }400 }
...@@ -402,7 +405,7 @@ pub const File = struct {...@@ -402,7 +405,7 @@ pub const File = struct {
402 assert(decl.has_tv);405 assert(decl.has_tv);
403 switch (base.tag) {406 switch (base.tag) {
404 inline else => |tag| {407 inline else => |tag| {
405 if (tag != .c and build_options.only_c) unreachable;408 dev.check(tag.devFeature());
406 return @as(*tag.Type(), @fieldParentPtr("base", base)).updateDecl(pt, decl_index);409 return @as(*tag.Type(), @fieldParentPtr("base", base)).updateDecl(pt, decl_index);
407 },410 },
408 }411 }
...@@ -418,7 +421,7 @@ pub const File = struct {...@@ -418,7 +421,7 @@ pub const File = struct {
418 ) UpdateDeclError!void {421 ) UpdateDeclError!void {
419 switch (base.tag) {422 switch (base.tag) {
420 inline else => |tag| {423 inline else => |tag| {
421 if (tag != .c and build_options.only_c) unreachable;424 dev.check(tag.devFeature());
422 return @as(*tag.Type(), @fieldParentPtr("base", base)).updateFunc(pt, func_index, air, liveness);425 return @as(*tag.Type(), @fieldParentPtr("base", base)).updateFunc(pt, func_index, air, liveness);
423 },426 },
424 }427 }
...@@ -430,7 +433,7 @@ pub const File = struct {...@@ -430,7 +433,7 @@ pub const File = struct {
430 switch (base.tag) {433 switch (base.tag) {
431 .spirv, .nvptx => {},434 .spirv, .nvptx => {},
432 inline else => |tag| {435 inline else => |tag| {
433 if (tag != .c and build_options.only_c) unreachable;436 dev.check(tag.devFeature());
434 return @as(*tag.Type(), @fieldParentPtr("base", base)).updateDeclLineNumber(pt, decl_index);437 return @as(*tag.Type(), @fieldParentPtr("base", base)).updateDeclLineNumber(pt, decl_index);
435 },438 },
436 }439 }
...@@ -454,7 +457,7 @@ pub const File = struct {...@@ -454,7 +457,7 @@ pub const File = struct {
454 if (base.file) |f| f.close();457 if (base.file) |f| f.close();
455 switch (base.tag) {458 switch (base.tag) {
456 inline else => |tag| {459 inline else => |tag| {
457 if (tag != .c and build_options.only_c) unreachable;460 dev.check(tag.devFeature());
458 @as(*tag.Type(), @fieldParentPtr("base", base)).deinit();461 @as(*tag.Type(), @fieldParentPtr("base", base)).deinit();
459 },462 },
460 }463 }
...@@ -536,12 +539,9 @@ pub const File = struct {...@@ -536,12 +539,9 @@ pub const File = struct {
536 /// and `use_lld`, not only `effectiveOutputMode`.539 /// and `use_lld`, not only `effectiveOutputMode`.
537 /// `arena` has the lifetime of the call to `Compilation.update`.540 /// `arena` has the lifetime of the call to `Compilation.update`.
538 pub fn flush(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void {541 pub fn flush(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void {
539 if (build_options.only_c) {
540 assert(base.tag == .c);
541 return @as(*C, @fieldParentPtr("base", base)).flush(arena, tid, prog_node);
542 }
543 const comp = base.comp;542 const comp = base.comp;
544 if (comp.clang_preprocessor_mode == .yes or comp.clang_preprocessor_mode == .pch) {543 if (comp.clang_preprocessor_mode == .yes or comp.clang_preprocessor_mode == .pch) {
544 dev.check(.clang_command);
545 const gpa = comp.gpa;545 const gpa = comp.gpa;
546 const emit = base.emit;546 const emit = base.emit;
547 // TODO: avoid extra link step when it's just 1 object file (the `zig cc -c` case)547 // TODO: avoid extra link step when it's just 1 object file (the `zig cc -c` case)
...@@ -565,6 +565,7 @@ pub const File = struct {...@@ -565,6 +565,7 @@ pub const File = struct {
565 }565 }
566 switch (base.tag) {566 switch (base.tag) {
567 inline else => |tag| {567 inline else => |tag| {
568 dev.check(tag.devFeature());
568 return @as(*tag.Type(), @fieldParentPtr("base", base)).flush(arena, tid, prog_node);569 return @as(*tag.Type(), @fieldParentPtr("base", base)).flush(arena, tid, prog_node);
569 },570 },
570 }571 }
...@@ -575,7 +576,7 @@ pub const File = struct {...@@ -575,7 +576,7 @@ pub const File = struct {
575 pub fn flushModule(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void {576 pub fn flushModule(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void {
576 switch (base.tag) {577 switch (base.tag) {
577 inline else => |tag| {578 inline else => |tag| {
578 if (tag != .c and build_options.only_c) unreachable;579 dev.check(tag.devFeature());
579 return @as(*tag.Type(), @fieldParentPtr("base", base)).flushModule(arena, tid, prog_node);580 return @as(*tag.Type(), @fieldParentPtr("base", base)).flushModule(arena, tid, prog_node);
580 },581 },
581 }582 }
...@@ -585,7 +586,7 @@ pub const File = struct {...@@ -585,7 +586,7 @@ pub const File = struct {
585 pub fn freeDecl(base: *File, decl_index: InternPool.DeclIndex) void {586 pub fn freeDecl(base: *File, decl_index: InternPool.DeclIndex) void {
586 switch (base.tag) {587 switch (base.tag) {
587 inline else => |tag| {588 inline else => |tag| {
588 if (tag != .c and build_options.only_c) unreachable;589 dev.check(tag.devFeature());
589 @as(*tag.Type(), @fieldParentPtr("base", base)).freeDecl(decl_index);590 @as(*tag.Type(), @fieldParentPtr("base", base)).freeDecl(decl_index);
590 },591 },
591 }592 }
...@@ -608,7 +609,7 @@ pub const File = struct {...@@ -608,7 +609,7 @@ pub const File = struct {
608 ) UpdateExportsError!void {609 ) UpdateExportsError!void {
609 switch (base.tag) {610 switch (base.tag) {
610 inline else => |tag| {611 inline else => |tag| {
611 if (tag != .c and build_options.only_c) unreachable;612 dev.check(tag.devFeature());
612 return @as(*tag.Type(), @fieldParentPtr("base", base)).updateExports(pt, exported, export_indices);613 return @as(*tag.Type(), @fieldParentPtr("base", base)).updateExports(pt, exported, export_indices);
613 },614 },
614 }615 }
...@@ -627,12 +628,12 @@ pub const File = struct {...@@ -627,12 +628,12 @@ pub const File = struct {
627 /// May be called before or after updateFunc/updateDecl therefore it is up to the linker to allocate628 /// May be called before or after updateFunc/updateDecl therefore it is up to the linker to allocate
628 /// the block/atom.629 /// the block/atom.
629 pub fn getDeclVAddr(base: *File, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex, reloc_info: RelocInfo) !u64 {630 pub fn getDeclVAddr(base: *File, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex, reloc_info: RelocInfo) !u64 {
630 if (build_options.only_c) @compileError("unreachable");
631 switch (base.tag) {631 switch (base.tag) {
632 .c => unreachable,632 .c => unreachable,
633 .spirv => unreachable,633 .spirv => unreachable,
634 .nvptx => unreachable,634 .nvptx => unreachable,
635 inline else => |tag| {635 inline else => |tag| {
636 dev.check(tag.devFeature());
636 return @as(*tag.Type(), @fieldParentPtr("base", base)).getDeclVAddr(pt, decl_index, reloc_info);637 return @as(*tag.Type(), @fieldParentPtr("base", base)).getDeclVAddr(pt, decl_index, reloc_info);
637 },638 },
638 }639 }
...@@ -647,24 +648,24 @@ pub const File = struct {...@@ -647,24 +648,24 @@ pub const File = struct {
647 decl_align: InternPool.Alignment,648 decl_align: InternPool.Alignment,
648 src_loc: Zcu.LazySrcLoc,649 src_loc: Zcu.LazySrcLoc,
649 ) !LowerResult {650 ) !LowerResult {
650 if (build_options.only_c) @compileError("unreachable");
651 switch (base.tag) {651 switch (base.tag) {
652 .c => unreachable,652 .c => unreachable,
653 .spirv => unreachable,653 .spirv => unreachable,
654 .nvptx => unreachable,654 .nvptx => unreachable,
655 inline else => |tag| {655 inline else => |tag| {
656 dev.check(tag.devFeature());
656 return @as(*tag.Type(), @fieldParentPtr("base", base)).lowerAnonDecl(pt, decl_val, decl_align, src_loc);657 return @as(*tag.Type(), @fieldParentPtr("base", base)).lowerAnonDecl(pt, decl_val, decl_align, src_loc);
657 },658 },
658 }659 }
659 }660 }
660661
661 pub fn getAnonDeclVAddr(base: *File, decl_val: InternPool.Index, reloc_info: RelocInfo) !u64 {662 pub fn getAnonDeclVAddr(base: *File, decl_val: InternPool.Index, reloc_info: RelocInfo) !u64 {
662 if (build_options.only_c) @compileError("unreachable");
663 switch (base.tag) {663 switch (base.tag) {
664 .c => unreachable,664 .c => unreachable,
665 .spirv => unreachable,665 .spirv => unreachable,
666 .nvptx => unreachable,666 .nvptx => unreachable,
667 inline else => |tag| {667 inline else => |tag| {
668 dev.check(tag.devFeature());
668 return @as(*tag.Type(), @fieldParentPtr("base", base)).getAnonDeclVAddr(decl_val, reloc_info);669 return @as(*tag.Type(), @fieldParentPtr("base", base)).getAnonDeclVAddr(decl_val, reloc_info);
669 },670 },
670 }671 }
...@@ -675,7 +676,6 @@ pub const File = struct {...@@ -675,7 +676,6 @@ pub const File = struct {
675 exported: Zcu.Exported,676 exported: Zcu.Exported,
676 name: InternPool.NullTerminatedString,677 name: InternPool.NullTerminatedString,
677 ) void {678 ) void {
678 if (build_options.only_c) @compileError("unreachable");
679 switch (base.tag) {679 switch (base.tag) {
680 .plan9,680 .plan9,
681 .spirv,681 .spirv,
...@@ -683,12 +683,15 @@ pub const File = struct {...@@ -683,12 +683,15 @@ pub const File = struct {
683 => {},683 => {},
684684
685 inline else => |tag| {685 inline else => |tag| {
686 dev.check(tag.devFeature());
686 return @as(*tag.Type(), @fieldParentPtr("base", base)).deleteExport(exported, name);687 return @as(*tag.Type(), @fieldParentPtr("base", base)).deleteExport(exported, name);
687 },688 },
688 }689 }
689 }690 }
690691
691 pub fn linkAsArchive(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void {692 pub fn linkAsArchive(base: *File, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) FlushError!void {
693 dev.check(.lld_linker);
694
692 const tracy = trace(@src());695 const tracy = trace(@src());
693 defer tracy.end();696 defer tracy.end();
694697
...@@ -743,10 +746,8 @@ pub const File = struct {...@@ -743,10 +746,8 @@ pub const File = struct {
743 for (comp.c_object_table.keys()) |key| {746 for (comp.c_object_table.keys()) |key| {
744 _ = try man.addFile(key.status.success.object_path, null);747 _ = try man.addFile(key.status.success.object_path, null);
745 }748 }
746 if (!build_options.only_core_functionality) {749 for (comp.win32_resource_table.keys()) |key| {
747 for (comp.win32_resource_table.keys()) |key| {750 _ = try man.addFile(key.status.success.res_path, null);
748 _ = try man.addFile(key.status.success.res_path, null);
749 }
750 }751 }
751 try man.addOptionalFile(zcu_obj_path);752 try man.addOptionalFile(zcu_obj_path);
752 try man.addOptionalFile(compiler_rt_path);753 try man.addOptionalFile(compiler_rt_path);
...@@ -777,7 +778,7 @@ pub const File = struct {...@@ -777,7 +778,7 @@ pub const File = struct {
777 };778 };
778 }779 }
779780
780 const win32_resource_table_len = if (build_options.only_core_functionality) 0 else comp.win32_resource_table.count();781 const win32_resource_table_len = comp.win32_resource_table.count();
781 const num_object_files = objects.len + comp.c_object_table.count() + win32_resource_table_len + 2;782 const num_object_files = objects.len + comp.c_object_table.count() + win32_resource_table_len + 2;
782 var object_files = try std.ArrayList([*:0]const u8).initCapacity(gpa, num_object_files);783 var object_files = try std.ArrayList([*:0]const u8).initCapacity(gpa, num_object_files);
783 defer object_files.deinit();784 defer object_files.deinit();
...@@ -788,10 +789,8 @@ pub const File = struct {...@@ -788,10 +789,8 @@ pub const File = struct {
788 for (comp.c_object_table.keys()) |key| {789 for (comp.c_object_table.keys()) |key| {
789 object_files.appendAssumeCapacity(try arena.dupeZ(u8, key.status.success.object_path));790 object_files.appendAssumeCapacity(try arena.dupeZ(u8, key.status.success.object_path));
790 }791 }
791 if (!build_options.only_core_functionality) {792 for (comp.win32_resource_table.keys()) |key| {
792 for (comp.win32_resource_table.keys()) |key| {793 object_files.appendAssumeCapacity(try arena.dupeZ(u8, key.status.success.res_path));
793 object_files.appendAssumeCapacity(try arena.dupeZ(u8, key.status.success.res_path));
794 }
795 }794 }
796 if (zcu_obj_path) |p| {795 if (zcu_obj_path) |p| {
797 object_files.appendAssumeCapacity(try arena.dupeZ(u8, p));796 object_files.appendAssumeCapacity(try arena.dupeZ(u8, p));
...@@ -869,6 +868,10 @@ pub const File = struct {...@@ -869,6 +868,10 @@ pub const File = struct {
869 .dxcontainer => @panic("TODO implement dxcontainer object format"),868 .dxcontainer => @panic("TODO implement dxcontainer object format"),
870 };869 };
871 }870 }
871
872 pub fn devFeature(tag: Tag) dev.Feature {
873 return @field(dev.Feature, @tagName(tag) ++ "_linker");
874 }
872 };875 };
873876
874 pub const ErrorFlags = struct {877 pub const ErrorFlags = struct {
src/link/Coff/lld.zig+7-8
...@@ -2,6 +2,7 @@ const std = @import("std");...@@ -2,6 +2,7 @@ const std = @import("std");
2const build_options = @import("build_options");2const build_options = @import("build_options");
3const allocPrint = std.fmt.allocPrint;3const allocPrint = std.fmt.allocPrint;
4const assert = std.debug.assert;4const assert = std.debug.assert;
5const dev = @import("../../dev.zig");
5const fs = std.fs;6const fs = std.fs;
6const log = std.log.scoped(.link);7const log = std.log.scoped(.link);
7const mem = std.mem;8const mem = std.mem;
...@@ -18,6 +19,8 @@ const Compilation = @import("../../Compilation.zig");...@@ -18,6 +19,8 @@ const Compilation = @import("../../Compilation.zig");
18const Zcu = @import("../../Zcu.zig");19const Zcu = @import("../../Zcu.zig");
1920
20pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void {21pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void {
22 dev.check(.lld_linker);
23
21 const tracy = trace(@src());24 const tracy = trace(@src());
22 defer tracy.end();25 defer tracy.end();
2326
...@@ -77,10 +80,8 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no...@@ -77,10 +80,8 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no
77 for (comp.c_object_table.keys()) |key| {80 for (comp.c_object_table.keys()) |key| {
78 _ = try man.addFile(key.status.success.object_path, null);81 _ = try man.addFile(key.status.success.object_path, null);
79 }82 }
80 if (!build_options.only_core_functionality) {83 for (comp.win32_resource_table.keys()) |key| {
81 for (comp.win32_resource_table.keys()) |key| {84 _ = try man.addFile(key.status.success.res_path, null);
82 _ = try man.addFile(key.status.success.res_path, null);
83 }
84 }85 }
85 try man.addOptionalFile(module_obj_path);86 try man.addOptionalFile(module_obj_path);
86 man.hash.addOptionalBytes(entry_name);87 man.hash.addOptionalBytes(entry_name);
...@@ -274,10 +275,8 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no...@@ -274,10 +275,8 @@ pub fn linkWithLLD(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no
274 try argv.append(key.status.success.object_path);275 try argv.append(key.status.success.object_path);
275 }276 }
276277
277 if (!build_options.only_core_functionality) {278 for (comp.win32_resource_table.keys()) |key| {
278 for (comp.win32_resource_table.keys()) |key| {279 try argv.append(key.status.success.res_path);
279 try argv.append(key.status.success.res_path);
280 }
281 }280 }
282281
283 if (module_obj_path) |p| {282 if (module_obj_path) |p| {
src/link/Elf.zig+3
...@@ -2148,6 +2148,8 @@ fn scanRelocs(self: *Elf) !void {...@@ -2148,6 +2148,8 @@ fn scanRelocs(self: *Elf) !void {
2148}2148}
21492149
2150fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void {2150fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void {
2151 dev.check(.lld_linker);
2152
2151 const tracy = trace(@src());2153 const tracy = trace(@src());
2152 defer tracy.end();2154 defer tracy.end();
21532155
...@@ -6430,6 +6432,7 @@ const math = std.math;...@@ -6430,6 +6432,7 @@ const math = std.math;
6430const mem = std.mem;6432const mem = std.mem;
64316433
6432const codegen = @import("../codegen.zig");6434const codegen = @import("../codegen.zig");
6435const dev = @import("../dev.zig");
6433const eh_frame = @import("Elf/eh_frame.zig");6436const eh_frame = @import("Elf/eh_frame.zig");
6434const gc = @import("Elf/gc.zig");6437const gc = @import("Elf/gc.zig");
6435const glibc = @import("../glibc.zig");6438const glibc = @import("../glibc.zig");
src/link/Wasm.zig+3
...@@ -6,6 +6,7 @@ const assert = std.debug.assert;...@@ -6,6 +6,7 @@ const assert = std.debug.assert;
6const build_options = @import("build_options");6const build_options = @import("build_options");
7const builtin = @import("builtin");7const builtin = @import("builtin");
8const codegen = @import("../codegen.zig");8const codegen = @import("../codegen.zig");
9const dev = @import("../dev.zig");
9const fs = std.fs;10const fs = std.fs;
10const leb = std.leb;11const leb = std.leb;
11const link = @import("../link.zig");12const link = @import("../link.zig");
...@@ -3325,6 +3326,8 @@ fn emitImport(wasm: *Wasm, writer: anytype, import: types.Import) !void {...@@ -3325,6 +3326,8 @@ fn emitImport(wasm: *Wasm, writer: anytype, import: types.Import) !void {
3325}3326}
33263327
3327fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void {3328fn linkWithLLD(wasm: *Wasm, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Progress.Node) !void {
3329 dev.check(.lld_linker);
3330
3328 const tracy = trace(@src());3331 const tracy = trace(@src());
3329 defer tracy.end();3332 defer tracy.end();
33303333
src/main.zig+97-82
...@@ -30,6 +30,7 @@ const Zcu = @import("Zcu.zig");...@@ -30,6 +30,7 @@ const Zcu = @import("Zcu.zig");
30const AstGen = std.zig.AstGen;30const AstGen = std.zig.AstGen;
31const mingw = @import("mingw.zig");31const mingw = @import("mingw.zig");
32const Server = std.zig.Server;32const Server = std.zig.Server;
33const dev = @import("dev.zig");
3334
34pub const std_options = .{35pub const std_options = .{
35 .wasiCwd = wasi_cwd,36 .wasiCwd = wasi_cwd,
...@@ -195,17 +196,6 @@ pub fn main() anyerror!void {...@@ -195,17 +196,6 @@ pub fn main() anyerror!void {
195 wasi_preopens = try fs.wasi.preopensAlloc(arena);196 wasi_preopens = try fs.wasi.preopensAlloc(arena);
196 }197 }
197198
198 // Short circuit some of the other logic for bootstrapping.
199 if (build_options.only_c) {
200 if (mem.eql(u8, args[1], "build-exe")) {
201 return buildOutputType(gpa, arena, args, .{ .build = .Exe });
202 } else if (mem.eql(u8, args[1], "build-obj")) {
203 return buildOutputType(gpa, arena, args, .{ .build = .Obj });
204 } else {
205 @panic("only build-exe or build-obj is supported in a -Donly-c build");
206 }
207 }
208
209 return mainArgs(gpa, arena, args);199 return mainArgs(gpa, arena, args);
210}200}
211201
...@@ -227,6 +217,7 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -227,6 +217,7 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
227 }217 }
228218
229 if (process.can_execv and std.posix.getenvZ("ZIG_IS_DETECTING_LIBC_PATHS") != null) {219 if (process.can_execv and std.posix.getenvZ("ZIG_IS_DETECTING_LIBC_PATHS") != null) {
220 dev.check(.cc_command);
230 // In this case we have accidentally invoked ourselves as "the system C compiler"221 // In this case we have accidentally invoked ourselves as "the system C compiler"
231 // to figure out where libc is installed. This is essentially infinite recursion222 // to figure out where libc is installed. This is essentially infinite recursion
232 // via child process execution due to the CC environment variable pointing to Zig.223 // via child process execution due to the CC environment variable pointing to Zig.
...@@ -260,39 +251,49 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -260,39 +251,49 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
260 const cmd = args[1];251 const cmd = args[1];
261 const cmd_args = args[2..];252 const cmd_args = args[2..];
262 if (mem.eql(u8, cmd, "build-exe")) {253 if (mem.eql(u8, cmd, "build-exe")) {
254 dev.check(.build_exe_command);
263 return buildOutputType(gpa, arena, args, .{ .build = .Exe });255 return buildOutputType(gpa, arena, args, .{ .build = .Exe });
264 } else if (mem.eql(u8, cmd, "build-lib")) {256 } else if (mem.eql(u8, cmd, "build-lib")) {
257 dev.check(.build_lib_command);
265 return buildOutputType(gpa, arena, args, .{ .build = .Lib });258 return buildOutputType(gpa, arena, args, .{ .build = .Lib });
266 } else if (mem.eql(u8, cmd, "build-obj")) {259 } else if (mem.eql(u8, cmd, "build-obj")) {
260 dev.check(.build_obj_command);
267 return buildOutputType(gpa, arena, args, .{ .build = .Obj });261 return buildOutputType(gpa, arena, args, .{ .build = .Obj });
268 } else if (mem.eql(u8, cmd, "test")) {262 } else if (mem.eql(u8, cmd, "test")) {
263 dev.check(.test_command);
269 return buildOutputType(gpa, arena, args, .zig_test);264 return buildOutputType(gpa, arena, args, .zig_test);
270 } else if (mem.eql(u8, cmd, "run")) {265 } else if (mem.eql(u8, cmd, "run")) {
266 dev.check(.run_command);
271 return buildOutputType(gpa, arena, args, .run);267 return buildOutputType(gpa, arena, args, .run);
272 } else if (mem.eql(u8, cmd, "dlltool") or268 } else if (mem.eql(u8, cmd, "dlltool") or
273 mem.eql(u8, cmd, "ranlib") or269 mem.eql(u8, cmd, "ranlib") or
274 mem.eql(u8, cmd, "lib") or270 mem.eql(u8, cmd, "lib") or
275 mem.eql(u8, cmd, "ar"))271 mem.eql(u8, cmd, "ar"))
276 {272 {
273 dev.check(.ar_command);
277 return process.exit(try llvmArMain(arena, args));274 return process.exit(try llvmArMain(arena, args));
278 } else if (mem.eql(u8, cmd, "build")) {275 } else if (mem.eql(u8, cmd, "build")) {
276 dev.check(.build_command);
279 return cmdBuild(gpa, arena, cmd_args);277 return cmdBuild(gpa, arena, cmd_args);
280 } else if (mem.eql(u8, cmd, "clang") or278 } else if (mem.eql(u8, cmd, "clang") or
281 mem.eql(u8, cmd, "-cc1") or mem.eql(u8, cmd, "-cc1as"))279 mem.eql(u8, cmd, "-cc1") or mem.eql(u8, cmd, "-cc1as"))
282 {280 {
281 dev.check(.clang_command);
283 return process.exit(try clangMain(arena, args));282 return process.exit(try clangMain(arena, args));
284 } else if (mem.eql(u8, cmd, "ld.lld") or283 } else if (mem.eql(u8, cmd, "ld.lld") or
285 mem.eql(u8, cmd, "lld-link") or284 mem.eql(u8, cmd, "lld-link") or
286 mem.eql(u8, cmd, "wasm-ld"))285 mem.eql(u8, cmd, "wasm-ld"))
287 {286 {
287 dev.check(.lld_linker);
288 return process.exit(try lldMain(arena, args, true));288 return process.exit(try lldMain(arena, args, true));
289 } else if (build_options.only_core_functionality) {
290 @panic("only a few subcommands are supported in a zig2.c build");
291 } else if (mem.eql(u8, cmd, "cc")) {289 } else if (mem.eql(u8, cmd, "cc")) {
290 dev.check(.cc_command);
292 return buildOutputType(gpa, arena, args, .cc);291 return buildOutputType(gpa, arena, args, .cc);
293 } else if (mem.eql(u8, cmd, "c++")) {292 } else if (mem.eql(u8, cmd, "c++")) {
293 dev.check(.cc_command);
294 return buildOutputType(gpa, arena, args, .cpp);294 return buildOutputType(gpa, arena, args, .cpp);
295 } else if (mem.eql(u8, cmd, "translate-c")) {295 } else if (mem.eql(u8, cmd, "translate-c")) {
296 dev.check(.translate_c_command);
296 return buildOutputType(gpa, arena, args, .translate_c);297 return buildOutputType(gpa, arena, args, .translate_c);
297 } else if (mem.eql(u8, cmd, "rc")) {298 } else if (mem.eql(u8, cmd, "rc")) {
298 const use_server = cmd_args.len > 0 and std.mem.eql(u8, cmd_args[0], "--zig-integration");299 const use_server = cmd_args.len > 0 and std.mem.eql(u8, cmd_args[0], "--zig-integration");
...@@ -332,16 +333,19 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -332,16 +333,19 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
332 } else if (mem.eql(u8, cmd, "init")) {333 } else if (mem.eql(u8, cmd, "init")) {
333 return cmdInit(gpa, arena, cmd_args);334 return cmdInit(gpa, arena, cmd_args);
334 } else if (mem.eql(u8, cmd, "targets")) {335 } else if (mem.eql(u8, cmd, "targets")) {
336 dev.check(.targets_command);
335 const host = std.zig.resolveTargetQueryOrFatal(.{});337 const host = std.zig.resolveTargetQueryOrFatal(.{});
336 const stdout = io.getStdOut().writer();338 const stdout = io.getStdOut().writer();
337 return @import("print_targets.zig").cmdTargets(arena, cmd_args, stdout, host);339 return @import("print_targets.zig").cmdTargets(arena, cmd_args, stdout, host);
338 } else if (mem.eql(u8, cmd, "version")) {340 } else if (mem.eql(u8, cmd, "version")) {
341 dev.check(.version_command);
339 try std.io.getStdOut().writeAll(build_options.version ++ "\n");342 try std.io.getStdOut().writeAll(build_options.version ++ "\n");
340 // Check libc++ linkage to make sure Zig was built correctly, but only343 // Check libc++ linkage to make sure Zig was built correctly, but only
341 // for "env" and "version" to avoid affecting the startup time for344 // for "env" and "version" to avoid affecting the startup time for
342 // build-critical commands (check takes about ~10 μs)345 // build-critical commands (check takes about ~10 μs)
343 return verifyLibcxxCorrectlyLinked();346 return verifyLibcxxCorrectlyLinked();
344 } else if (mem.eql(u8, cmd, "env")) {347 } else if (mem.eql(u8, cmd, "env")) {
348 dev.check(.env_command);
345 verifyLibcxxCorrectlyLinked();349 verifyLibcxxCorrectlyLinked();
346 return @import("print_env.zig").cmdEnv(arena, cmd_args, io.getStdOut().writer());350 return @import("print_env.zig").cmdEnv(arena, cmd_args, io.getStdOut().writer());
347 } else if (mem.eql(u8, cmd, "reduce")) {351 } else if (mem.eql(u8, cmd, "reduce")) {
...@@ -350,8 +354,10 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -350,8 +354,10 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
350 .root_src_path = "reduce.zig",354 .root_src_path = "reduce.zig",
351 });355 });
352 } else if (mem.eql(u8, cmd, "zen")) {356 } else if (mem.eql(u8, cmd, "zen")) {
357 dev.check(.zen_command);
353 return io.getStdOut().writeAll(info_zen);358 return io.getStdOut().writeAll(info_zen);
354 } else if (mem.eql(u8, cmd, "help") or mem.eql(u8, cmd, "-h") or mem.eql(u8, cmd, "--help")) {359 } else if (mem.eql(u8, cmd, "help") or mem.eql(u8, cmd, "-h") or mem.eql(u8, cmd, "--help")) {
360 dev.check(.help_command);
355 return io.getStdOut().writeAll(usage);361 return io.getStdOut().writeAll(usage);
356 } else if (mem.eql(u8, cmd, "ast-check")) {362 } else if (mem.eql(u8, cmd, "ast-check")) {
357 return cmdAstCheck(gpa, arena, cmd_args);363 return cmdAstCheck(gpa, arena, cmd_args);
...@@ -726,14 +732,10 @@ const ArgMode = union(enum) {...@@ -726,14 +732,10 @@ const ArgMode = union(enum) {
726 run,732 run,
727};733};
728734
729/// Avoid dragging networking into zig2.c because it adds dependencies on some
730/// linker symbols that are annoying to satisfy while bootstrapping.
731const Ip4Address = if (build_options.only_core_functionality) void else std.net.Ip4Address;
732
733const Listen = union(enum) {735const Listen = union(enum) {
734 none,736 none,
735 ip4: Ip4Address,737 stdio: if (dev.env.supports(.stdio_listen)) void else noreturn,
736 stdio,738 ip4: if (dev.env.supports(.network_listen)) std.net.Ip4Address else noreturn,
737};739};
738740
739const ArgsIterator = struct {741const ArgsIterator = struct {
...@@ -1338,9 +1340,10 @@ fn buildOutputType(...@@ -1338,9 +1340,10 @@ fn buildOutputType(
1338 } else if (mem.eql(u8, arg, "--listen")) {1340 } else if (mem.eql(u8, arg, "--listen")) {
1339 const next_arg = args_iter.nextOrFatal();1341 const next_arg = args_iter.nextOrFatal();
1340 if (mem.eql(u8, next_arg, "-")) {1342 if (mem.eql(u8, next_arg, "-")) {
1343 dev.check(.stdio_listen);
1341 listen = .stdio;1344 listen = .stdio;
1342 } else {1345 } else {
1343 if (build_options.only_core_functionality) unreachable;1346 dev.check(.network_listen);
1344 // example: --listen 127.0.0.1:90001347 // example: --listen 127.0.0.1:9000
1345 var it = std.mem.splitScalar(u8, next_arg, ':');1348 var it = std.mem.splitScalar(u8, next_arg, ':');
1346 const host = it.next().?;1349 const host = it.next().?;
...@@ -1351,6 +1354,7 @@ fn buildOutputType(...@@ -1351,6 +1354,7 @@ fn buildOutputType(
1351 fatal("invalid host: '{s}': {s}", .{ host, @errorName(err) }) };1354 fatal("invalid host: '{s}': {s}", .{ host, @errorName(err) }) };
1352 }1355 }
1353 } else if (mem.eql(u8, arg, "--listen=-")) {1356 } else if (mem.eql(u8, arg, "--listen=-")) {
1357 dev.check(.stdio_listen);
1354 listen = .stdio;1358 listen = .stdio;
1355 } else if (mem.eql(u8, arg, "--debug-link-snapshot")) {1359 } else if (mem.eql(u8, arg, "--debug-link-snapshot")) {
1356 if (!build_options.enable_link_snapshots) {1360 if (!build_options.enable_link_snapshots) {
...@@ -1359,6 +1363,7 @@ fn buildOutputType(...@@ -1359,6 +1363,7 @@ fn buildOutputType(
1359 enable_link_snapshots = true;1363 enable_link_snapshots = true;
1360 }1364 }
1361 } else if (mem.eql(u8, arg, "-fincremental")) {1365 } else if (mem.eql(u8, arg, "-fincremental")) {
1366 dev.check(.incremental);
1362 opt_incremental = true;1367 opt_incremental = true;
1363 } else if (mem.eql(u8, arg, "-fno-incremental")) {1368 } else if (mem.eql(u8, arg, "-fno-incremental")) {
1364 opt_incremental = false;1369 opt_incremental = false;
...@@ -1762,7 +1767,7 @@ fn buildOutputType(...@@ -1762,7 +1767,7 @@ fn buildOutputType(
1762 }1767 }
1763 },1768 },
1764 .cc, .cpp => {1769 .cc, .cpp => {
1765 if (build_options.only_c) unreachable;1770 dev.check(.cc_command);
17661771
1767 emit_h = .no;1772 emit_h = .no;
1768 soname = .no;1773 soname = .no;
...@@ -3395,7 +3400,6 @@ fn buildOutputType(...@@ -3395,7 +3400,6 @@ fn buildOutputType(
3395 switch (listen) {3400 switch (listen) {
3396 .none => {},3401 .none => {},
3397 .stdio => {3402 .stdio => {
3398 if (build_options.only_c) unreachable;
3399 try serve(3403 try serve(
3400 comp,3404 comp,
3401 std.io.getStdIn(),3405 std.io.getStdIn(),
...@@ -3409,8 +3413,6 @@ fn buildOutputType(...@@ -3409,8 +3413,6 @@ fn buildOutputType(
3409 return cleanExit();3413 return cleanExit();
3410 },3414 },
3411 .ip4 => |ip4_addr| {3415 .ip4 => |ip4_addr| {
3412 if (build_options.only_core_functionality) unreachable;
3413
3414 const addr: std.net.Address = .{ .in = ip4_addr };3416 const addr: std.net.Address = .{ .in = ip4_addr };
34153417
3416 var server = try addr.listen(.{3418 var server = try addr.listen(.{
...@@ -3454,50 +3456,50 @@ fn buildOutputType(...@@ -3454,50 +3456,50 @@ fn buildOutputType(
3454 else => |e| return e,3456 else => |e| return e,
3455 };3457 };
3456 }3458 }
3457 if (build_options.only_c) return cleanExit();
3458 try comp.makeBinFileExecutable();3459 try comp.makeBinFileExecutable();
3459 saveState(comp, incremental);3460 saveState(comp, incremental);
34603461
3461 if (test_exec_args.items.len == 0 and target.ofmt == .c) default_exec_args: {3462 if (switch (arg_mode) {
3462 // Default to using `zig run` to execute the produced .c code from `zig test`.3463 .run => true,
3463 const c_code_loc = emit_bin_loc orelse break :default_exec_args;3464 .zig_test => !test_no_exec,
3464 const c_code_directory = c_code_loc.directory orelse comp.bin_file.?.emit.directory;3465 else => false,
3465 const c_code_path = try fs.path.join(arena, &[_][]const u8{3466 }) {
3466 c_code_directory.path orelse ".", c_code_loc.basename,3467 dev.checkAny(&.{ .run_command, .test_command });
3467 });3468
3468 try test_exec_args.appendSlice(arena, &.{ self_exe_path, "run" });3469 if (test_exec_args.items.len == 0 and target.ofmt == .c) default_exec_args: {
3469 if (zig_lib_directory.path) |p| {3470 // Default to using `zig run` to execute the produced .c code from `zig test`.
3470 try test_exec_args.appendSlice(arena, &.{ "-I", p });3471 const c_code_loc = emit_bin_loc orelse break :default_exec_args;
3471 }3472 const c_code_directory = c_code_loc.directory orelse comp.bin_file.?.emit.directory;
34723473 const c_code_path = try fs.path.join(arena, &[_][]const u8{
3473 if (create_module.resolved_options.link_libc) {3474 c_code_directory.path orelse ".", c_code_loc.basename,
3474 try test_exec_args.append(arena, "-lc");
3475 } else if (target.os.tag == .windows) {
3476 try test_exec_args.appendSlice(arena, &.{
3477 "--subsystem", "console",
3478 "-lkernel32", "-lntdll",
3479 });3475 });
3480 }3476 try test_exec_args.appendSlice(arena, &.{ self_exe_path, "run" });
3477 if (zig_lib_directory.path) |p| {
3478 try test_exec_args.appendSlice(arena, &.{ "-I", p });
3479 }
34813480
3482 const first_cli_mod = create_module.modules.values()[0];3481 if (create_module.resolved_options.link_libc) {
3483 if (first_cli_mod.target_arch_os_abi) |triple| {3482 try test_exec_args.append(arena, "-lc");
3484 try test_exec_args.appendSlice(arena, &.{ "-target", triple });3483 } else if (target.os.tag == .windows) {
3485 }3484 try test_exec_args.appendSlice(arena, &.{
3486 if (first_cli_mod.target_mcpu) |mcpu| {3485 "--subsystem", "console",
3487 try test_exec_args.append(arena, try std.fmt.allocPrint(arena, "-mcpu={s}", .{mcpu}));3486 "-lkernel32", "-lntdll",
3488 }3487 });
3489 if (create_module.dynamic_linker) |dl| {3488 }
3490 try test_exec_args.appendSlice(arena, &.{ "--dynamic-linker", dl });3489
3490 const first_cli_mod = create_module.modules.values()[0];
3491 if (first_cli_mod.target_arch_os_abi) |triple| {
3492 try test_exec_args.appendSlice(arena, &.{ "-target", triple });
3493 }
3494 if (first_cli_mod.target_mcpu) |mcpu| {
3495 try test_exec_args.append(arena, try std.fmt.allocPrint(arena, "-mcpu={s}", .{mcpu}));
3496 }
3497 if (create_module.dynamic_linker) |dl| {
3498 try test_exec_args.appendSlice(arena, &.{ "--dynamic-linker", dl });
3499 }
3500 try test_exec_args.append(arena, c_code_path);
3491 }3501 }
3492 try test_exec_args.append(arena, c_code_path);
3493 }
34943502
3495 const run_or_test = switch (arg_mode) {
3496 .run => true,
3497 .zig_test => !test_no_exec,
3498 else => false,
3499 };
3500 if (run_or_test) {
3501 try runOrTest(3503 try runOrTest(
3502 comp,3504 comp,
3503 gpa,3505 gpa,
...@@ -4459,7 +4461,8 @@ fn cmdTranslateC(...@@ -4459,7 +4461,8 @@ fn cmdTranslateC(
4459 file_system_inputs: ?*std.ArrayListUnmanaged(u8),4461 file_system_inputs: ?*std.ArrayListUnmanaged(u8),
4460 prog_node: std.Progress.Node,4462 prog_node: std.Progress.Node,
4461) !void {4463) !void {
4462 if (build_options.only_core_functionality) @panic("@translate-c is not available in a zig2.c build");4464 dev.check(.translate_c_command);
4465
4463 const color: Color = .auto;4466 const color: Color = .auto;
4464 assert(comp.c_source_files.len == 1);4467 assert(comp.c_source_files.len == 1);
4465 const c_source_file = comp.c_source_files[0];4468 const c_source_file = comp.c_source_files[0];
...@@ -4627,6 +4630,8 @@ const usage_init =...@@ -4627,6 +4630,8 @@ const usage_init =
4627;4630;
46284631
4629fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {4632fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
4633 dev.check(.init_command);
4634
4630 {4635 {
4631 var i: usize = 0;4636 var i: usize = 0;
4632 while (i < args.len) : (i += 1) {4637 while (i < args.len) : (i += 1) {
...@@ -4678,6 +4683,8 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -4678,6 +4683,8 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
4678}4683}
46794684
4680fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {4685fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
4686 dev.check(.build_command);
4687
4681 var build_file: ?[]const u8 = null;4688 var build_file: ?[]const u8 = null;
4682 var override_lib_dir: ?[]const u8 = try EnvVar.ZIG_LIB_DIR.get(arena);4689 var override_lib_dir: ?[]const u8 = try EnvVar.ZIG_LIB_DIR.get(arena);
4683 var override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena);4690 var override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena);
...@@ -4969,16 +4976,12 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -4969,16 +4976,12 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
4969 });4976 });
4970 defer thread_pool.deinit();4977 defer thread_pool.deinit();
49714978
4972 // Dummy http client that is not actually used when only_core_functionality is enabled.4979 // Dummy http client that is not actually used when fetch_command is unsupported.
4973 // Prevents bootstrap from depending on a bunch of unnecessary stuff.4980 // Prevents bootstrap from depending on a bunch of unnecessary stuff.
4974 const HttpClient = if (build_options.only_core_functionality) struct {4981 var http_client: if (dev.env.supports(.fetch_command)) std.http.Client else struct {
4975 allocator: Allocator,4982 allocator: Allocator,
4976 fn deinit(self: *@This()) void {4983 fn deinit(_: @This()) void {}
4977 _ = self;4984 } = .{ .allocator = gpa };
4978 }
4979 } else std.http.Client;
4980
4981 var http_client: HttpClient = .{ .allocator = gpa };
4982 defer http_client.deinit();4985 defer http_client.deinit();
49834986
4984 var unlazy_set: Package.Fetch.JobQueue.UnlazySet = .{};4987 var unlazy_set: Package.Fetch.JobQueue.UnlazySet = .{};
...@@ -5045,16 +5048,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5045,16 +5048,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5045 var cleanup_build_dir: ?fs.Dir = null;5048 var cleanup_build_dir: ?fs.Dir = null;
5046 defer if (cleanup_build_dir) |*dir| dir.close();5049 defer if (cleanup_build_dir) |*dir| dir.close();
50475050
5048 if (build_options.only_core_functionality) {5051 if (dev.env.supports(.fetch_command)) {
5049 try createEmptyDependenciesModule(
5050 arena,
5051 root_mod,
5052 global_cache_directory,
5053 local_cache_directory,
5054 builtin_mod,
5055 config,
5056 );
5057 } else {
5058 const fetch_prog_node = root_prog_node.start("Fetch Packages", 0);5052 const fetch_prog_node = root_prog_node.start("Fetch Packages", 0);
5059 defer fetch_prog_node.end();5053 defer fetch_prog_node.end();
50605054
...@@ -5203,7 +5197,14 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5203,7 +5197,14 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5203 }5197 }
5204 }5198 }
5205 }5199 }
5206 }5200 } else try createEmptyDependenciesModule(
5201 arena,
5202 root_mod,
5203 global_cache_directory,
5204 local_cache_directory,
5205 builtin_mod,
5206 config,
5207 );
52075208
5208 try root_mod.deps.put(arena, "@build", build_mod);5209 try root_mod.deps.put(arena, "@build", build_mod);
52095210
...@@ -5269,7 +5270,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {...@@ -5269,7 +5270,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
5269 if (code == 2) process.exit(2);5270 if (code == 2) process.exit(2);
52705271
5271 if (code == 3) {5272 if (code == 3) {
5272 if (build_options.only_core_functionality) process.exit(3);5273 if (!dev.env.supports(.fetch_command)) process.exit(3);
5273 // Indicates the configure phase failed due to missing lazy5274 // Indicates the configure phase failed due to missing lazy
5274 // dependencies and stdout contains the hashes of the ones5275 // dependencies and stdout contains the hashes of the ones
5275 // that are missing.5276 // that are missing.
...@@ -5346,6 +5347,8 @@ fn jitCmd(...@@ -5346,6 +5347,8 @@ fn jitCmd(
5346 args: []const []const u8,5347 args: []const []const u8,
5347 options: JitCmdOptions,5348 options: JitCmdOptions,
5348) !void {5349) !void {
5350 dev.check(.jit_command);
5351
5349 const color: Color = .auto;5352 const color: Color = .auto;
5350 const root_prog_node = if (options.progress_node) |node| node else std.Progress.start(.{5353 const root_prog_node = if (options.progress_node) |node| node else std.Progress.start(.{
5351 .disable_printing = (color == .off),5354 .disable_printing = (color == .off),
...@@ -5995,6 +5998,8 @@ fn cmdAstCheck(...@@ -5995,6 +5998,8 @@ fn cmdAstCheck(
5995 arena: Allocator,5998 arena: Allocator,
5996 args: []const []const u8,5999 args: []const []const u8,
5997) !void {6000) !void {
6001 dev.check(.ast_check_command);
6002
5998 const Zir = std.zig.Zir;6003 const Zir = std.zig.Zir;
59996004
6000 var color: Color = .auto;6005 var color: Color = .auto;
...@@ -6154,6 +6159,8 @@ fn cmdDetectCpu(...@@ -6154,6 +6159,8 @@ fn cmdDetectCpu(
6154 arena: Allocator,6159 arena: Allocator,
6155 args: []const []const u8,6160 args: []const []const u8,
6156) !void {6161) !void {
6162 dev.check(.detect_cpu_command);
6163
6157 _ = gpa;6164 _ = gpa;
6158 _ = arena;6165 _ = arena;
61596166
...@@ -6293,6 +6300,8 @@ fn cmdDumpLlvmInts(...@@ -6293,6 +6300,8 @@ fn cmdDumpLlvmInts(
6293 arena: Allocator,6300 arena: Allocator,
6294 args: []const []const u8,6301 args: []const []const u8,
6295) !void {6302) !void {
6303 dev.check(.llvm_ints_command);
6304
6296 _ = gpa;6305 _ = gpa;
62976306
6298 if (!build_options.have_llvm)6307 if (!build_options.have_llvm)
...@@ -6336,6 +6345,8 @@ fn cmdDumpZir(...@@ -6336,6 +6345,8 @@ fn cmdDumpZir(
6336 arena: Allocator,6345 arena: Allocator,
6337 args: []const []const u8,6346 args: []const []const u8,
6338) !void {6347) !void {
6348 dev.check(.dump_zir_command);
6349
6339 _ = arena;6350 _ = arena;
6340 const Zir = std.zig.Zir;6351 const Zir = std.zig.Zir;
63416352
...@@ -6395,6 +6406,8 @@ fn cmdChangelist(...@@ -6395,6 +6406,8 @@ fn cmdChangelist(
6395 arena: Allocator,6406 arena: Allocator,
6396 args: []const []const u8,6407 args: []const []const u8,
6397) !void {6408) !void {
6409 dev.check(.changelist_command);
6410
6398 const color: Color = .auto;6411 const color: Color = .auto;
6399 const Zir = std.zig.Zir;6412 const Zir = std.zig.Zir;
64006413
...@@ -6895,6 +6908,8 @@ fn cmdFetch(...@@ -6895,6 +6908,8 @@ fn cmdFetch(
6895 arena: Allocator,6908 arena: Allocator,
6896 args: []const []const u8,6909 args: []const []const u8,
6897) !void {6910) !void {
6911 dev.check(.fetch_command);
6912
6898 const color: Color = .auto;6913 const color: Color = .auto;
6899 const work_around_btrfs_bug = native_os == .linux and6914 const work_around_btrfs_bug = native_os == .linux and
6900 EnvVar.ZIG_BTRFS_WORKAROUND.isSet();6915 EnvVar.ZIG_BTRFS_WORKAROUND.isSet();
src/mingw.zig+3-1
...@@ -9,6 +9,7 @@ const builtin = @import("builtin");...@@ -9,6 +9,7 @@ const builtin = @import("builtin");
9const Compilation = @import("Compilation.zig");9const Compilation = @import("Compilation.zig");
10const build_options = @import("build_options");10const build_options = @import("build_options");
11const Cache = std.Build.Cache;11const Cache = std.Build.Cache;
12const dev = @import("dev.zig");
1213
13pub const CRTFile = enum {14pub const CRTFile = enum {
14 crt2_o,15 crt2_o,
...@@ -157,7 +158,8 @@ fn add_cc_args(...@@ -157,7 +158,8 @@ fn add_cc_args(
157}158}
158159
159pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {160pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
160 if (build_options.only_c) @compileError("building import libs not included in core functionality");161 dev.check(.build_import_lib);
162
161 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);163 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
162 defer arena_allocator.deinit();164 defer arena_allocator.deinit();
163 const arena = arena_allocator.allocator();165 const arena = arena_allocator.allocator();
stage1/config.zig.in+1-2
...@@ -12,5 +12,4 @@ pub const enable_tracy = false;...@@ -12,5 +12,4 @@ pub const enable_tracy = false;
12pub const value_tracing = false;12pub const value_tracing = false;
13pub const skip_non_native = false;13pub const skip_non_native = false;
14pub const force_gpa = false;14pub const force_gpa = false;
15pub const only_c = false;15pub const dev = .core;
16pub const only_core_functionality = true;