authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-07-14 21:18:09-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-07-14 21:18:09-07:00
log716b128a24ffc44a8694f3d61e3d74b5297fd564
treea3d37e3df26af301e478162229ebe2ea481cf2ee
parentabf895595189eb45df8c97f4029c58976815b450

frontend: add -fincremental, -fno-incremental flag

Remove --debug-incremental This flag is also added to the build system. Importantly, this tells Compile step whether or not to keep the compiler running between rebuilds. It defaults off because it is currently crashing zirUpdateRefs.

8 files changed, 36 insertions(+), 21 deletions(-)

lib/compiler/build_runner.zig+7
...@@ -72,6 +72,7 @@ pub fn main() !void {...@@ -72,6 +72,7 @@ pub fn main() !void {
72 .query = .{},72 .query = .{},
73 .result = try std.zig.system.resolveTargetQuery(.{}),73 .result = try std.zig.system.resolveTargetQuery(.{}),
74 },74 },
75 .incremental = null,
75 };76 };
7677
77 graph.cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() });78 graph.cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() });
...@@ -235,6 +236,10 @@ pub fn main() !void {...@@ -235,6 +236,10 @@ pub fn main() !void {
235 prominent_compile_errors = true;236 prominent_compile_errors = true;
236 } else if (mem.eql(u8, arg, "--watch")) {237 } else if (mem.eql(u8, arg, "--watch")) {
237 watch = true;238 watch = true;
239 } else if (mem.eql(u8, arg, "-fincremental")) {
240 graph.incremental = true;
241 } else if (mem.eql(u8, arg, "-fno-incremental")) {
242 graph.incremental = false;
238 } else if (mem.eql(u8, arg, "-fwine")) {243 } else if (mem.eql(u8, arg, "-fwine")) {
239 builder.enable_wine = true;244 builder.enable_wine = true;
240 } else if (mem.eql(u8, arg, "-fno-wine")) {245 } else if (mem.eql(u8, arg, "-fno-wine")) {
...@@ -1216,6 +1221,8 @@ fn usage(b: *std.Build, out_stream: anytype) !void {...@@ -1216,6 +1221,8 @@ fn usage(b: *std.Build, out_stream: anytype) !void {
1216 \\ --fetch Exit after fetching dependency tree1221 \\ --fetch Exit after fetching dependency tree
1217 \\ --watch Continuously rebuild when source files are modified1222 \\ --watch Continuously rebuild when source files are modified
1218 \\ --debounce <ms> Delay before rebuilding after changed file detected1223 \\ --debounce <ms> Delay before rebuilding after changed file detected
1224 \\ -fincremental Enable incremental compilation
1225 \\ -fno-incremental Disable incremental compilation
1219 \\1226 \\
1220 \\Project-Specific Options:1227 \\Project-Specific Options:
1221 \\1228 \\
lib/std/Build.zig+1
...@@ -120,6 +120,7 @@ pub const Graph = struct {...@@ -120,6 +120,7 @@ pub const Graph = struct {
120 needed_lazy_dependencies: std.StringArrayHashMapUnmanaged(void) = .{},120 needed_lazy_dependencies: std.StringArrayHashMapUnmanaged(void) = .{},
121 /// Information about the native target. Computed before build() is invoked.121 /// Information about the native target. Computed before build() is invoked.
122 host: ResolvedTarget,122 host: ResolvedTarget,
123 incremental: ?bool,
123};124};
124125
125const AvailableDeps = []const struct { []const u8, []const u8 };126const AvailableDeps = []const struct { []const u8, []const u8 };
lib/std/Build/Step/Compile.zig+3-1
...@@ -1679,6 +1679,8 @@ fn getZigArgs(compile: *Compile) ![][]const u8 {...@@ -1679,6 +1679,8 @@ fn getZigArgs(compile: *Compile) ![][]const u8 {
1679 b.fmt("{}", .{err_limit}),1679 b.fmt("{}", .{err_limit}),
1680 });1680 });
16811681
1682 try addFlag(&zig_args, "incremental", b.graph.incremental);
1683
1682 try zig_args.append("--listen=-");1684 try zig_args.append("--listen=-");
16831685
1684 // Windows has an argument length limit of 32,766 characters, macOS 262,144 and Linux1686 // Windows has an argument length limit of 32,766 characters, macOS 262,144 and Linux
...@@ -1750,7 +1752,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {...@@ -1750,7 +1752,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void {
1750 const maybe_output_bin_path = step.evalZigProcess(1752 const maybe_output_bin_path = step.evalZigProcess(
1751 zig_args,1753 zig_args,
1752 options.progress_node,1754 options.progress_node,
1753 options.watch,1755 (b.graph.incremental == true) and options.watch,
1754 ) catch |err| switch (err) {1756 ) catch |err| switch (err) {
1755 error.NeedCompileErrorCheck => {1757 error.NeedCompileErrorCheck => {
1756 assert(compile.expect_errors != null);1758 assert(compile.expect_errors != null);
src/Compilation.zig+3-3
...@@ -169,7 +169,7 @@ time_report: bool,...@@ -169,7 +169,7 @@ time_report: bool,
169stack_report: bool,169stack_report: bool,
170debug_compiler_runtime_libs: bool,170debug_compiler_runtime_libs: bool,
171debug_compile_errors: bool,171debug_compile_errors: bool,
172debug_incremental: bool,172incremental: bool,
173job_queued_compiler_rt_lib: bool = false,173job_queued_compiler_rt_lib: bool = false,
174job_queued_compiler_rt_obj: bool = false,174job_queued_compiler_rt_obj: bool = false,
175job_queued_update_builtin_zig: bool,175job_queued_update_builtin_zig: bool,
...@@ -1134,7 +1134,7 @@ pub const CreateOptions = struct {...@@ -1134,7 +1134,7 @@ pub const CreateOptions = struct {
1134 verbose_llvm_cpu_features: bool = false,1134 verbose_llvm_cpu_features: bool = false,
1135 debug_compiler_runtime_libs: bool = false,1135 debug_compiler_runtime_libs: bool = false,
1136 debug_compile_errors: bool = false,1136 debug_compile_errors: bool = false,
1137 debug_incremental: bool = false,1137 incremental: bool = false,
1138 /// Normally when you create a `Compilation`, Zig will automatically build1138 /// Normally when you create a `Compilation`, Zig will automatically build
1139 /// and link in required dependencies, such as compiler-rt and libc. When1139 /// and link in required dependencies, such as compiler-rt and libc. When
1140 /// building such dependencies themselves, this flag must be set to avoid1140 /// building such dependencies themselves, this flag must be set to avoid
...@@ -1516,7 +1516,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -1516,7 +1516,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
1516 .test_name_prefix = options.test_name_prefix,1516 .test_name_prefix = options.test_name_prefix,
1517 .debug_compiler_runtime_libs = options.debug_compiler_runtime_libs,1517 .debug_compiler_runtime_libs = options.debug_compiler_runtime_libs,
1518 .debug_compile_errors = options.debug_compile_errors,1518 .debug_compile_errors = options.debug_compile_errors,
1519 .debug_incremental = options.debug_incremental,1519 .incremental = options.incremental,
1520 .libcxx_abi_version = options.libcxx_abi_version,1520 .libcxx_abi_version = options.libcxx_abi_version,
1521 .root_name = root_name,1521 .root_name = root_name,
1522 .sysroot = sysroot,1522 .sysroot = sysroot,
src/Sema.zig+6-6
...@@ -2726,7 +2726,7 @@ fn maybeRemoveOutdatedType(sema: *Sema, ty: InternPool.Index) !bool {...@@ -2726,7 +2726,7 @@ fn maybeRemoveOutdatedType(sema: *Sema, ty: InternPool.Index) !bool {
2726 const pt = sema.pt;2726 const pt = sema.pt;
2727 const zcu = pt.zcu;2727 const zcu = pt.zcu;
27282728
2729 if (!zcu.comp.debug_incremental) return false;2729 if (!zcu.comp.incremental) return false;
27302730
2731 const decl_index = Type.fromInterned(ty).getOwnerDecl(zcu);2731 const decl_index = Type.fromInterned(ty).getOwnerDecl(zcu);
2732 const decl_as_depender = AnalUnit.wrap(.{ .decl = decl_index });2732 const decl_as_depender = AnalUnit.wrap(.{ .decl = decl_index });
...@@ -2826,7 +2826,7 @@ fn zirStructDecl(...@@ -2826,7 +2826,7 @@ fn zirStructDecl(
2826 mod.declPtr(new_decl_index).owns_tv = true;2826 mod.declPtr(new_decl_index).owns_tv = true;
2827 errdefer pt.abortAnonDecl(new_decl_index);2827 errdefer pt.abortAnonDecl(new_decl_index);
28282828
2829 if (pt.zcu.comp.debug_incremental) {2829 if (pt.zcu.comp.incremental) {
2830 try ip.addDependency(2830 try ip.addDependency(
2831 sema.gpa,2831 sema.gpa,
2832 AnalUnit.wrap(.{ .decl = new_decl_index }),2832 AnalUnit.wrap(.{ .decl = new_decl_index }),
...@@ -3064,7 +3064,7 @@ fn zirEnumDecl(...@@ -3064,7 +3064,7 @@ fn zirEnumDecl(
3064 new_decl.owns_tv = true;3064 new_decl.owns_tv = true;
3065 errdefer if (!done) pt.abortAnonDecl(new_decl_index);3065 errdefer if (!done) pt.abortAnonDecl(new_decl_index);
30663066
3067 if (pt.zcu.comp.debug_incremental) {3067 if (pt.zcu.comp.incremental) {
3068 try mod.intern_pool.addDependency(3068 try mod.intern_pool.addDependency(
3069 gpa,3069 gpa,
3070 AnalUnit.wrap(.{ .decl = new_decl_index }),3070 AnalUnit.wrap(.{ .decl = new_decl_index }),
...@@ -3331,7 +3331,7 @@ fn zirUnionDecl(...@@ -3331,7 +3331,7 @@ fn zirUnionDecl(
3331 mod.declPtr(new_decl_index).owns_tv = true;3331 mod.declPtr(new_decl_index).owns_tv = true;
3332 errdefer pt.abortAnonDecl(new_decl_index);3332 errdefer pt.abortAnonDecl(new_decl_index);
33333333
3334 if (pt.zcu.comp.debug_incremental) {3334 if (pt.zcu.comp.incremental) {
3335 try mod.intern_pool.addDependency(3335 try mod.intern_pool.addDependency(
3336 gpa,3336 gpa,
3337 AnalUnit.wrap(.{ .decl = new_decl_index }),3337 AnalUnit.wrap(.{ .decl = new_decl_index }),
...@@ -3421,7 +3421,7 @@ fn zirOpaqueDecl(...@@ -3421,7 +3421,7 @@ fn zirOpaqueDecl(
3421 mod.declPtr(new_decl_index).owns_tv = true;3421 mod.declPtr(new_decl_index).owns_tv = true;
3422 errdefer pt.abortAnonDecl(new_decl_index);3422 errdefer pt.abortAnonDecl(new_decl_index);
34233423
3424 if (pt.zcu.comp.debug_incremental) {3424 if (pt.zcu.comp.incremental) {
3425 try ip.addDependency(3425 try ip.addDependency(
3426 gpa,3426 gpa,
3427 AnalUnit.wrap(.{ .decl = new_decl_index }),3427 AnalUnit.wrap(.{ .decl = new_decl_index }),
...@@ -38098,7 +38098,7 @@ fn isKnownZigType(sema: *Sema, ref: Air.Inst.Ref, tag: std.builtin.TypeId) bool...@@ -38098,7 +38098,7 @@ fn isKnownZigType(sema: *Sema, ref: Air.Inst.Ref, tag: std.builtin.TypeId) bool
3809838098
38099pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void {38099pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void {
38100 const zcu = sema.pt.zcu;38100 const zcu = sema.pt.zcu;
38101 if (!zcu.comp.debug_incremental) return;38101 if (!zcu.comp.incremental) return;
3810238102
38103 // Avoid creating dependencies on ourselves. This situation can arise when we analyze the fields38103 // Avoid creating dependencies on ourselves. This situation can arise when we analyze the fields
38104 // of a type and they use `@This()`. This dependency would be unnecessary, and in fact would38104 // of a type and they use `@This()`. This dependency would be unnecessary, and in fact would
src/Zcu.zig+1-1
...@@ -2679,7 +2679,7 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni...@@ -2679,7 +2679,7 @@ fn markTransitiveDependersPotentiallyOutdated(zcu: *Zcu, maybe_outdated: AnalUni
2679}2679}
26802680
2681pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {2681pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit {
2682 if (!zcu.comp.debug_incremental) return null;2682 if (!zcu.comp.incremental) return null;
26832683
2684 if (zcu.outdated.count() == 0 and zcu.potentially_outdated.count() == 0) {2684 if (zcu.outdated.count() == 0 and zcu.potentially_outdated.count() == 0) {
2685 log.debug("findOutdatedToAnalyze: no outdated depender", .{});2685 log.debug("findOutdatedToAnalyze: no outdated depender", .{});
src/Zcu/PerThread.zig+1-1
...@@ -888,7 +888,7 @@ fn getFileRootStruct(...@@ -888,7 +888,7 @@ fn getFileRootStruct(
888 };888 };
889 errdefer wip_ty.cancel(ip, pt.tid);889 errdefer wip_ty.cancel(ip, pt.tid);
890890
891 if (zcu.comp.debug_incremental) {891 if (zcu.comp.incremental) {
892 try ip.addDependency(892 try ip.addDependency(
893 gpa,893 gpa,
894 InternPool.AnalUnit.wrap(.{ .decl = decl_index }),894 InternPool.AnalUnit.wrap(.{ .decl = decl_index }),
src/main.zig+14-9
...@@ -404,6 +404,8 @@ const usage_build_generic =...@@ -404,6 +404,8 @@ const usage_build_generic =
404 \\ -h, --help Print this help and exit404 \\ -h, --help Print this help and exit
405 \\ --color [auto|off|on] Enable or disable colored error messages405 \\ --color [auto|off|on] Enable or disable colored error messages
406 \\ -j<N> Limit concurrent jobs (default is to use all CPU cores)406 \\ -j<N> Limit concurrent jobs (default is to use all CPU cores)
407 \\ -fincremental Enable incremental compilation
408 \\ -fno-incremental Disable incremental compilation
407 \\ -femit-bin[=path] (default) Output machine code409 \\ -femit-bin[=path] (default) Output machine code
408 \\ -fno-emit-bin Do not output machine code410 \\ -fno-emit-bin Do not output machine code
409 \\ -femit-asm[=path] Output .s (assembly code)411 \\ -femit-asm[=path] Output .s (assembly code)
...@@ -642,7 +644,6 @@ const usage_build_generic =...@@ -642,7 +644,6 @@ const usage_build_generic =
642 \\ --debug-log [scope] Enable printing debug/info log messages for scope644 \\ --debug-log [scope] Enable printing debug/info log messages for scope
643 \\ --debug-compile-errors Crash with helpful diagnostics at the first compile error645 \\ --debug-compile-errors Crash with helpful diagnostics at the first compile error
644 \\ --debug-link-snapshot Enable dumping of the linker's state in JSON format646 \\ --debug-link-snapshot Enable dumping of the linker's state in JSON format
645 \\ --debug-incremental Enable experimental feature: incremental compilation
646 \\647 \\
647;648;
648649
...@@ -904,7 +905,7 @@ fn buildOutputType(...@@ -904,7 +905,7 @@ fn buildOutputType(
904 var minor_subsystem_version: ?u16 = null;905 var minor_subsystem_version: ?u16 = null;
905 var mingw_unicode_entry_point: bool = false;906 var mingw_unicode_entry_point: bool = false;
906 var enable_link_snapshots: bool = false;907 var enable_link_snapshots: bool = false;
907 var debug_incremental: bool = false;908 var opt_incremental: ?bool = null;
908 var install_name: ?[]const u8 = null;909 var install_name: ?[]const u8 = null;
909 var hash_style: link.File.Elf.HashStyle = .both;910 var hash_style: link.File.Elf.HashStyle = .both;
910 var entitlements: ?[]const u8 = null;911 var entitlements: ?[]const u8 = null;
...@@ -1357,8 +1358,10 @@ fn buildOutputType(...@@ -1357,8 +1358,10 @@ fn buildOutputType(
1357 } else {1358 } else {
1358 enable_link_snapshots = true;1359 enable_link_snapshots = true;
1359 }1360 }
1360 } else if (mem.eql(u8, arg, "--debug-incremental")) {1361 } else if (mem.eql(u8, arg, "-fincremental")) {
1361 debug_incremental = true;1362 opt_incremental = true;
1363 } else if (mem.eql(u8, arg, "-fno-incremental")) {
1364 opt_incremental = false;
1362 } else if (mem.eql(u8, arg, "--entitlements")) {1365 } else if (mem.eql(u8, arg, "--entitlements")) {
1363 entitlements = args_iter.nextOrFatal();1366 entitlements = args_iter.nextOrFatal();
1364 } else if (mem.eql(u8, arg, "-fcompiler-rt")) {1367 } else if (mem.eql(u8, arg, "-fcompiler-rt")) {
...@@ -3225,6 +3228,8 @@ fn buildOutputType(...@@ -3225,6 +3228,8 @@ fn buildOutputType(
3225 break :b .incremental;3228 break :b .incremental;
3226 };3229 };
32273230
3231 const incremental = opt_incremental orelse false;
3232
3228 process.raiseFileDescriptorLimit();3233 process.raiseFileDescriptorLimit();
32293234
3230 var file_system_inputs: std.ArrayListUnmanaged(u8) = .{};3235 var file_system_inputs: std.ArrayListUnmanaged(u8) = .{};
...@@ -3336,7 +3341,7 @@ fn buildOutputType(...@@ -3336,7 +3341,7 @@ fn buildOutputType(
3336 .cache_mode = cache_mode,3341 .cache_mode = cache_mode,
3337 .subsystem = subsystem,3342 .subsystem = subsystem,
3338 .debug_compile_errors = debug_compile_errors,3343 .debug_compile_errors = debug_compile_errors,
3339 .debug_incremental = debug_incremental,3344 .incremental = incremental,
3340 .enable_link_snapshots = enable_link_snapshots,3345 .enable_link_snapshots = enable_link_snapshots,
3341 .install_name = install_name,3346 .install_name = install_name,
3342 .entitlements = entitlements,3347 .entitlements = entitlements,
...@@ -3443,7 +3448,7 @@ fn buildOutputType(...@@ -3443,7 +3448,7 @@ fn buildOutputType(
3443 updateModule(comp, color, root_prog_node) catch |err| switch (err) {3448 updateModule(comp, color, root_prog_node) catch |err| switch (err) {
3444 error.SemanticAnalyzeFail => {3449 error.SemanticAnalyzeFail => {
3445 assert(listen == .none);3450 assert(listen == .none);
3446 saveState(comp, debug_incremental);3451 saveState(comp, incremental);
3447 process.exit(1);3452 process.exit(1);
3448 },3453 },
3449 else => |e| return e,3454 else => |e| return e,
...@@ -3451,7 +3456,7 @@ fn buildOutputType(...@@ -3451,7 +3456,7 @@ fn buildOutputType(
3451 }3456 }
3452 if (build_options.only_c) return cleanExit();3457 if (build_options.only_c) return cleanExit();
3453 try comp.makeBinFileExecutable();3458 try comp.makeBinFileExecutable();
3454 saveState(comp, debug_incremental);3459 saveState(comp, incremental);
34553460
3456 if (test_exec_args.items.len == 0 and target.ofmt == .c) default_exec_args: {3461 if (test_exec_args.items.len == 0 and target.ofmt == .c) default_exec_args: {
3457 // Default to using `zig run` to execute the produced .c code from `zig test`.3462 // Default to using `zig run` to execute the produced .c code from `zig test`.
...@@ -4032,8 +4037,8 @@ fn createModule(...@@ -4032,8 +4037,8 @@ fn createModule(
4032 return mod;4037 return mod;
4033}4038}
40344039
4035fn saveState(comp: *Compilation, debug_incremental: bool) void {4040fn saveState(comp: *Compilation, incremental: bool) void {
4036 if (debug_incremental) {4041 if (incremental) {
4037 comp.saveState() catch |err| {4042 comp.saveState() catch |err| {
4038 warn("unable to save incremental compilation state: {s}", .{@errorName(err)});4043 warn("unable to save incremental compilation state: {s}", .{@errorName(err)});
4039 };4044 };