| ... | ... | @@ -46,6 +46,12 @@ sanitize_c: bool, |
| 46 | 46 | clang_passthrough_mode: bool, |
| 47 | 47 | /// Whether to print clang argvs to stdout. |
| 48 | 48 | verbose_cc: bool, |
| 49 | verbose_tokenize: bool, |
| 50 | verbose_ast: bool, |
| 51 | verbose_ir: bool, |
| 52 | verbose_llvm_ir: bool, |
| 53 | verbose_cimport: bool, |
| 54 | verbose_llvm_cpu_features: bool, |
| 49 | 55 | disable_c_depfile: bool, |
| 50 | 56 | is_test: bool, |
| 51 | 57 | |
| ... | ... | @@ -59,18 +65,21 @@ zig_cache_directory: Directory, |
| 59 | 65 | libc_include_dir_list: []const []const u8, |
| 60 | 66 | rand: *std.rand.Random, |
| 61 | 67 | |
| 62 | | /// Populated when we build libc++.a. A Job to build this is placed in the queue |
| 68 | /// Populated when we build the libc++ static library. A Job to build this is placed in the queue |
| 63 | 69 | /// and resolved before calling linker.flush(). |
| 64 | 70 | libcxx_static_lib: ?[]const u8 = null, |
| 65 | | /// Populated when we build libc++abi.a. A Job to build this is placed in the queue |
| 71 | /// Populated when we build the libc++abi static library. A Job to build this is placed in the queue |
| 66 | 72 | /// and resolved before calling linker.flush(). |
| 67 | 73 | libcxxabi_static_lib: ?[]const u8 = null, |
| 68 | | /// Populated when we build libunwind.a. A Job to build this is placed in the queue |
| 74 | /// Populated when we build the libunwind static library. A Job to build this is placed in the queue |
| 69 | 75 | /// and resolved before calling linker.flush(). |
| 70 | 76 | libunwind_static_lib: ?CRTFile = null, |
| 71 | | /// Populated when we build c.a. A Job to build this is placed in the queue |
| 77 | /// Populated when we build the libc static library. A Job to build this is placed in the queue |
| 72 | 78 | /// and resolved before calling linker.flush(). |
| 73 | | libc_static_lib: ?[]const u8 = null, |
| 79 | libc_static_lib: ?CRTFile = null, |
| 80 | /// Populated when we build the libcompiler_rt static library. A Job to build this is placed in the queue |
| 81 | /// and resolved before calling linker.flush(). |
| 82 | compiler_rt_static_lib: ?CRTFile = null, |
| 74 | 83 | |
| 75 | 84 | glibc_so_files: ?glibc.BuiltSharedObjects = null, |
| 76 | 85 | |
| ... | ... | @@ -121,6 +130,11 @@ const Job = union(enum) { |
| 121 | 130 | glibc_shared_objects, |
| 122 | 131 | /// libunwind.a, usually needed when linking libc |
| 123 | 132 | libunwind: void, |
| 133 | /// needed when producing a dynamic library or executable |
| 134 | libcompiler_rt: void, |
| 135 | /// needed when not linking libc and using LLVM for code generation because it generates |
| 136 | /// calls to, for example, memcpy and memset. |
| 137 | zig_libc: void, |
| 124 | 138 | |
| 125 | 139 | /// Generate builtin.zig source code and write it into the correct place. |
| 126 | 140 | generate_builtin_zig: void, |
| ... | ... | @@ -310,6 +324,15 @@ pub const InitOptions = struct { |
| 310 | 324 | }; |
| 311 | 325 | |
| 312 | 326 | pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 327 | const is_dyn_lib = switch (options.output_mode) { |
| 328 | .Obj, .Exe => false, |
| 329 | .Lib => (options.link_mode orelse .Static) == .Dynamic, |
| 330 | }; |
| 331 | const is_exe_or_dyn_lib = switch (options.output_mode) { |
| 332 | .Obj => false, |
| 333 | .Lib => is_dyn_lib, |
| 334 | .Exe => true, |
| 335 | }; |
| 313 | 336 | const comp: *Compilation = comp: { |
| 314 | 337 | // For allocations that have the same lifetime as Compilation. This arena is used only during this |
| 315 | 338 | // initialization and then is freed in deinit(). |
| ... | ... | @@ -375,15 +398,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 375 | 398 | return error.MachineCodeModelNotSupported; |
| 376 | 399 | } |
| 377 | 400 | |
| 378 | | const is_dyn_lib = switch (options.output_mode) { |
| 379 | | .Obj, .Exe => false, |
| 380 | | .Lib => (options.link_mode orelse .Static) == .Dynamic, |
| 381 | | }; |
| 382 | | const is_exe_or_dyn_lib = switch (options.output_mode) { |
| 383 | | .Obj => false, |
| 384 | | .Lib => is_dyn_lib, |
| 385 | | .Exe => true, |
| 386 | | }; |
| 387 | 401 | const must_dynamic_link = dl: { |
| 388 | 402 | if (target_util.cannotDynamicLink(options.target)) |
| 389 | 403 | break :dl false; |
| ... | ... | @@ -461,6 +475,27 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 461 | 475 | }; |
| 462 | 476 | |
| 463 | 477 | const single_threaded = options.single_threaded or target_util.isSingleThreaded(options.target); |
| 478 | const function_sections = options.function_sections orelse false; |
| 479 | |
| 480 | const llvm_cpu_features: ?[*:0]const u8 = if (build_options.have_llvm and use_llvm) blk: { |
| 481 | var buf = std.ArrayList(u8).init(arena); |
| 482 | for (options.target.cpu.arch.allFeaturesList()) |feature, index_usize| { |
| 483 | const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize); |
| 484 | const is_enabled = options.target.cpu.features.isEnabled(index); |
| 485 | |
| 486 | if (feature.llvm_name) |llvm_name| { |
| 487 | const plus_or_minus = "-+"[@boolToInt(is_enabled)]; |
| 488 | try buf.ensureCapacity(buf.items.len + 2 + llvm_name.len); |
| 489 | buf.appendAssumeCapacity(plus_or_minus); |
| 490 | buf.appendSliceAssumeCapacity(llvm_name); |
| 491 | buf.appendSliceAssumeCapacity(","); |
| 492 | } |
| 493 | } |
| 494 | assert(mem.endsWith(u8, buf.items, ",")); |
| 495 | buf.items[buf.items.len - 1] = 0; |
| 496 | buf.shrink(buf.items.len); |
| 497 | break :blk buf.items[0 .. buf.items.len - 1 :0].ptr; |
| 498 | } else null; |
| 464 | 499 | |
| 465 | 500 | // We put everything into the cache hash that *cannot be modified during an incremental update*. |
| 466 | 501 | // For example, one cannot change the target between updates, but one can change source files, |
| ... | ... | @@ -489,8 +524,10 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 489 | 524 | cache.hash.add(pic); |
| 490 | 525 | cache.hash.add(stack_check); |
| 491 | 526 | cache.hash.add(link_mode); |
| 527 | cache.hash.add(function_sections); |
| 492 | 528 | cache.hash.add(options.strip); |
| 493 | 529 | cache.hash.add(options.link_libc); |
| 530 | cache.hash.add(options.link_libcpp); |
| 494 | 531 | cache.hash.add(options.output_mode); |
| 495 | 532 | cache.hash.add(options.machine_code_model); |
| 496 | 533 | // TODO audit this and make sure everything is in it |
| ... | ... | @@ -596,10 +633,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 596 | 633 | owned_link_dir = artifact_dir; |
| 597 | 634 | const link_artifact_directory: Directory = .{ |
| 598 | 635 | .handle = artifact_dir, |
| 599 | | .path = if (options.zig_cache_directory.path) |p| |
| 600 | | try std.fs.path.join(arena, &[_][]const u8{ p, artifact_sub_dir }) |
| 601 | | else |
| 602 | | artifact_sub_dir, |
| 636 | .path = try options.zig_cache_directory.join(arena, &[_][]const u8{artifact_sub_dir}), |
| 603 | 637 | }; |
| 604 | 638 | break :blk link_artifact_directory; |
| 605 | 639 | }; |
| ... | ... | @@ -609,26 +643,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 609 | 643 | .ReleaseFast, .ReleaseSmall => false, |
| 610 | 644 | }; |
| 611 | 645 | |
| 612 | | const llvm_cpu_features: ?[*:0]const u8 = if (build_options.have_llvm and use_llvm) blk: { |
| 613 | | var buf = std.ArrayList(u8).init(arena); |
| 614 | | for (options.target.cpu.arch.allFeaturesList()) |feature, index_usize| { |
| 615 | | const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize); |
| 616 | | const is_enabled = options.target.cpu.features.isEnabled(index); |
| 617 | | |
| 618 | | if (feature.llvm_name) |llvm_name| { |
| 619 | | const plus_or_minus = "-+"[@boolToInt(is_enabled)]; |
| 620 | | try buf.ensureCapacity(buf.items.len + 2 + llvm_name.len); |
| 621 | | buf.appendAssumeCapacity(plus_or_minus); |
| 622 | | buf.appendSliceAssumeCapacity(llvm_name); |
| 623 | | buf.appendSliceAssumeCapacity(","); |
| 624 | | } |
| 625 | | } |
| 626 | | assert(mem.endsWith(u8, buf.items, ",")); |
| 627 | | buf.items[buf.items.len - 1] = 0; |
| 628 | | buf.shrink(buf.items.len); |
| 629 | | break :blk buf.items[0 .. buf.items.len - 1 :0].ptr; |
| 630 | | } else null; |
| 631 | | |
| 632 | 646 | const stage1_module: ?*stage1.Module = if (build_options.is_stage1 and use_llvm) blk: { |
| 633 | 647 | // Here we use the legacy stage1 C++ compiler to compile Zig code. |
| 634 | 648 | const stage2_target = try arena.create(stage1.Stage2Target); |
| ... | ... | @@ -646,7 +660,9 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 646 | 660 | if (options.color == .Off) progress.terminal = null; |
| 647 | 661 | |
| 648 | 662 | const mod = module.?; |
| 649 | | const main_zig_file = mod.root_pkg.root_src_path; |
| 663 | const main_zig_file = try mod.root_pkg.root_src_directory.join(arena, &[_][]const u8{ |
| 664 | mod.root_pkg.root_src_path, |
| 665 | }); |
| 650 | 666 | const zig_lib_dir = options.zig_lib_directory.path.?; |
| 651 | 667 | const builtin_sub = &[_][]const u8{"builtin.zig"}; |
| 652 | 668 | const builtin_zig_path = try mod.zig_cache_artifact_directory.join(arena, builtin_sub); |
| ... | ... | @@ -700,7 +716,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 700 | 716 | .dll_export_fns = dll_export_fns, |
| 701 | 717 | .link_mode_dynamic = link_mode == .Dynamic, |
| 702 | 718 | .valgrind_enabled = valgrind, |
| 703 | | .function_sections = options.function_sections orelse false, |
| 719 | .function_sections = function_sections, |
| 704 | 720 | .enable_stack_probing = stack_check, |
| 705 | 721 | .enable_time_report = options.time_report, |
| 706 | 722 | .enable_stack_report = false, |
| ... | ... | @@ -790,6 +806,12 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 790 | 806 | .rand = options.rand, |
| 791 | 807 | .clang_passthrough_mode = options.clang_passthrough_mode, |
| 792 | 808 | .verbose_cc = options.verbose_cc, |
| 809 | .verbose_tokenize = options.verbose_tokenize, |
| 810 | .verbose_ast = options.verbose_ast, |
| 811 | .verbose_ir = options.verbose_ir, |
| 812 | .verbose_llvm_ir = options.verbose_llvm_ir, |
| 813 | .verbose_cimport = options.verbose_cimport, |
| 814 | .verbose_llvm_cpu_features = options.verbose_llvm_cpu_features, |
| 793 | 815 | .disable_c_depfile = options.disable_c_depfile, |
| 794 | 816 | .owned_link_dir = owned_link_dir, |
| 795 | 817 | .is_test = options.is_test, |
| ... | ... | @@ -823,10 +845,15 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 823 | 845 | if (comp.wantBuildLibUnwindFromSource()) { |
| 824 | 846 | try comp.work_queue.writeItem(.{ .libunwind = {} }); |
| 825 | 847 | } |
| 826 | | |
| 827 | 848 | if (comp.stage1_module) |module| { |
| 828 | 849 | try comp.work_queue.writeItem(.{ .stage1_module = {} }); |
| 829 | 850 | } |
| 851 | if (is_exe_or_dyn_lib) { |
| 852 | try comp.work_queue.writeItem(.{ .libcompiler_rt = {} }); |
| 853 | if (!comp.bin_file.options.link_libc) { |
| 854 | try comp.work_queue.writeItem(.{ .zig_libc = {} }); |
| 855 | } |
| 856 | } |
| 830 | 857 | |
| 831 | 858 | return comp; |
| 832 | 859 | } |
| ... | ... | @@ -852,8 +879,14 @@ pub fn destroy(self: *Compilation) void { |
| 852 | 879 | self.crt_files.deinit(gpa); |
| 853 | 880 | } |
| 854 | 881 | |
| 855 | | if (self.libunwind_static_lib) |*unwind_crt_file| { |
| 856 | | unwind_crt_file.deinit(gpa); |
| 882 | if (self.libunwind_static_lib) |*crt_file| { |
| 883 | crt_file.deinit(gpa); |
| 884 | } |
| 885 | if (self.compiler_rt_static_lib) |*crt_file| { |
| 886 | crt_file.deinit(gpa); |
| 887 | } |
| 888 | if (self.libc_static_lib) |*crt_file| { |
| 889 | crt_file.deinit(gpa); |
| 857 | 890 | } |
| 858 | 891 | |
| 859 | 892 | for (self.c_object_table.items()) |entry| { |
| ... | ... | @@ -889,41 +922,46 @@ pub fn update(self: *Compilation) !void { |
| 889 | 922 | self.work_queue.writeItemAssumeCapacity(.{ .c_object = entry.key }); |
| 890 | 923 | } |
| 891 | 924 | |
| 892 | | if (self.bin_file.options.module) |module| { |
| 893 | | module.generation += 1; |
| 894 | | |
| 895 | | // TODO Detect which source files changed. |
| 896 | | // Until then we simulate a full cache miss. Source files could have been loaded for any reason; |
| 897 | | // to force a refresh we unload now. |
| 898 | | if (module.root_scope.cast(Module.Scope.File)) |zig_file| { |
| 899 | | zig_file.unload(module.gpa); |
| 900 | | module.analyzeContainer(&zig_file.root_container) catch |err| switch (err) { |
| 901 | | error.AnalysisFail => { |
| 902 | | assert(self.totalErrorCount() != 0); |
| 903 | | }, |
| 904 | | else => |e| return e, |
| 905 | | }; |
| 906 | | } else if (module.root_scope.cast(Module.Scope.ZIRModule)) |zir_module| { |
| 907 | | zir_module.unload(module.gpa); |
| 908 | | module.analyzeRootZIRModule(zir_module) catch |err| switch (err) { |
| 909 | | error.AnalysisFail => { |
| 910 | | assert(self.totalErrorCount() != 0); |
| 911 | | }, |
| 912 | | else => |e| return e, |
| 913 | | }; |
| 925 | const use_stage1 = build_options.is_stage1 and self.bin_file.options.use_llvm; |
| 926 | if (!use_stage1) { |
| 927 | if (self.bin_file.options.module) |module| { |
| 928 | module.generation += 1; |
| 929 | |
| 930 | // TODO Detect which source files changed. |
| 931 | // Until then we simulate a full cache miss. Source files could have been loaded for any reason; |
| 932 | // to force a refresh we unload now. |
| 933 | if (module.root_scope.cast(Module.Scope.File)) |zig_file| { |
| 934 | zig_file.unload(module.gpa); |
| 935 | module.analyzeContainer(&zig_file.root_container) catch |err| switch (err) { |
| 936 | error.AnalysisFail => { |
| 937 | assert(self.totalErrorCount() != 0); |
| 938 | }, |
| 939 | else => |e| return e, |
| 940 | }; |
| 941 | } else if (module.root_scope.cast(Module.Scope.ZIRModule)) |zir_module| { |
| 942 | zir_module.unload(module.gpa); |
| 943 | module.analyzeRootZIRModule(zir_module) catch |err| switch (err) { |
| 944 | error.AnalysisFail => { |
| 945 | assert(self.totalErrorCount() != 0); |
| 946 | }, |
| 947 | else => |e| return e, |
| 948 | }; |
| 949 | } |
| 914 | 950 | } |
| 915 | 951 | } |
| 916 | 952 | |
| 917 | 953 | try self.performAllTheWork(); |
| 918 | 954 | |
| 919 | | if (self.bin_file.options.module) |module| { |
| 920 | | // Process the deletion set. |
| 921 | | while (module.deletion_set.popOrNull()) |decl| { |
| 922 | | if (decl.dependants.items().len != 0) { |
| 923 | | decl.deletion_flag = false; |
| 924 | | continue; |
| 955 | if (!use_stage1) { |
| 956 | if (self.bin_file.options.module) |module| { |
| 957 | // Process the deletion set. |
| 958 | while (module.deletion_set.popOrNull()) |decl| { |
| 959 | if (decl.dependants.items().len != 0) { |
| 960 | decl.deletion_flag = false; |
| 961 | continue; |
| 962 | } |
| 963 | try module.deleteDecl(decl); |
| 925 | 964 | } |
| 926 | | try module.deleteDecl(decl); |
| 927 | 965 | } |
| 928 | 966 | } |
| 929 | 967 | |
| ... | ... | @@ -1142,6 +1180,18 @@ pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void { |
| 1142 | 1180 | fatal("unable to build libunwind: {}", .{@errorName(err)}); |
| 1143 | 1181 | }; |
| 1144 | 1182 | }, |
| 1183 | .libcompiler_rt => { |
| 1184 | self.buildStaticLibFromZig("compiler_rt.zig", &self.compiler_rt_static_lib) catch |err| { |
| 1185 | // TODO Expose this as a normal compile error rather than crashing here. |
| 1186 | fatal("unable to build compiler_rt: {}", .{@errorName(err)}); |
| 1187 | }; |
| 1188 | }, |
| 1189 | .zig_libc => { |
| 1190 | self.buildStaticLibFromZig("c.zig", &self.libc_static_lib) catch |err| { |
| 1191 | // TODO Expose this as a normal compile error rather than crashing here. |
| 1192 | fatal("unable to build zig's multitarget libc: {}", .{@errorName(err)}); |
| 1193 | }; |
| 1194 | }, |
| 1145 | 1195 | .generate_builtin_zig => { |
| 1146 | 1196 | // This Job is only queued up if there is a zig module. |
| 1147 | 1197 | self.updateBuiltinZigFile(self.bin_file.options.module.?) catch |err| { |
| ... | ... | @@ -1691,7 +1741,7 @@ pub fn classifyFileExt(filename: []const u8) FileExt { |
| 1691 | 1741 | } else if (mem.endsWith(u8, filename, ".zig")) { |
| 1692 | 1742 | return .zig; |
| 1693 | 1743 | } else if (mem.endsWith(u8, filename, ".zir")) { |
| 1694 | | return .zig; |
| 1744 | return .zir; |
| 1695 | 1745 | } else if (hasSharedLibraryExt(filename)) { |
| 1696 | 1746 | return .shared_library; |
| 1697 | 1747 | } else if (hasStaticLibraryExt(filename)) { |
| ... | ... | @@ -2030,3 +2080,97 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 |
| 2030 | 2080 | }); |
| 2031 | 2081 | return buffer.toOwnedSlice(); |
| 2032 | 2082 | } |
| 2083 | |
| 2084 | pub fn updateSubCompilation(sub_compilation: *Compilation) !void { |
| 2085 | try sub_compilation.update(); |
| 2086 | |
| 2087 | // Look for compilation errors in this sub_compilation |
| 2088 | var errors = try sub_compilation.getAllErrorsAlloc(); |
| 2089 | defer errors.deinit(sub_compilation.gpa); |
| 2090 | |
| 2091 | if (errors.list.len != 0) { |
| 2092 | for (errors.list) |full_err_msg| { |
| 2093 | std.log.err("{}:{}:{}: {}\n", .{ |
| 2094 | full_err_msg.src_path, |
| 2095 | full_err_msg.line + 1, |
| 2096 | full_err_msg.column + 1, |
| 2097 | full_err_msg.msg, |
| 2098 | }); |
| 2099 | } |
| 2100 | return error.BuildingLibCObjectFailed; |
| 2101 | } |
| 2102 | } |
| 2103 | |
| 2104 | fn buildStaticLibFromZig(comp: *Compilation, basename: []const u8, out: *?CRTFile) !void { |
| 2105 | const tracy = trace(@src()); |
| 2106 | defer tracy.end(); |
| 2107 | |
| 2108 | const special_sub = "std" ++ std.fs.path.sep_str ++ "special"; |
| 2109 | const special_path = try comp.zig_lib_directory.join(comp.gpa, &[_][]const u8{special_sub}); |
| 2110 | defer comp.gpa.free(special_path); |
| 2111 | |
| 2112 | var special_dir = try comp.zig_lib_directory.handle.openDir(special_sub, .{}); |
| 2113 | defer special_dir.close(); |
| 2114 | |
| 2115 | var root_pkg: Package = .{ |
| 2116 | .root_src_directory = .{ |
| 2117 | .path = special_path, |
| 2118 | .handle = special_dir, |
| 2119 | }, |
| 2120 | .root_src_path = basename, |
| 2121 | }; |
| 2122 | |
| 2123 | const emit_bin = Compilation.EmitLoc{ |
| 2124 | .directory = null, // Put it in the cache directory. |
| 2125 | .basename = basename, |
| 2126 | }; |
| 2127 | const optimize_mode: std.builtin.Mode = blk: { |
| 2128 | if (comp.is_test) |
| 2129 | break :blk comp.bin_file.options.optimize_mode; |
| 2130 | switch (comp.bin_file.options.optimize_mode) { |
| 2131 | .Debug, .ReleaseFast, .ReleaseSafe => break :blk .ReleaseFast, |
| 2132 | .ReleaseSmall => break :blk .ReleaseSmall, |
| 2133 | } |
| 2134 | }; |
| 2135 | const sub_compilation = try Compilation.create(comp.gpa, .{ |
| 2136 | // TODO use the global cache directory here |
| 2137 | .zig_cache_directory = comp.zig_cache_directory, |
| 2138 | .zig_lib_directory = comp.zig_lib_directory, |
| 2139 | .target = comp.getTarget(), |
| 2140 | .root_name = mem.split(basename, ".").next().?, |
| 2141 | .root_pkg = &root_pkg, |
| 2142 | .output_mode = .Lib, |
| 2143 | .rand = comp.rand, |
| 2144 | .libc_installation = comp.bin_file.options.libc_installation, |
| 2145 | .emit_bin = emit_bin, |
| 2146 | .optimize_mode = optimize_mode, |
| 2147 | .link_mode = .Static, |
| 2148 | .function_sections = true, |
| 2149 | .want_sanitize_c = false, |
| 2150 | .want_stack_check = false, |
| 2151 | .want_valgrind = false, |
| 2152 | .want_pic = comp.bin_file.options.pic, |
| 2153 | .emit_h = null, |
| 2154 | .strip = comp.bin_file.options.strip, |
| 2155 | .is_native_os = comp.bin_file.options.is_native_os, |
| 2156 | .self_exe_path = comp.self_exe_path, |
| 2157 | .verbose_cc = comp.verbose_cc, |
| 2158 | .verbose_link = comp.bin_file.options.verbose_link, |
| 2159 | .verbose_tokenize = comp.verbose_tokenize, |
| 2160 | .verbose_ast = comp.verbose_ast, |
| 2161 | .verbose_ir = comp.verbose_ir, |
| 2162 | .verbose_llvm_ir = comp.verbose_llvm_ir, |
| 2163 | .verbose_cimport = comp.verbose_cimport, |
| 2164 | .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, |
| 2165 | .clang_passthrough_mode = comp.clang_passthrough_mode, |
| 2166 | }); |
| 2167 | defer sub_compilation.destroy(); |
| 2168 | |
| 2169 | try sub_compilation.updateSubCompilation(); |
| 2170 | |
| 2171 | assert(out.* == null); |
| 2172 | out.* = Compilation.CRTFile{ |
| 2173 | .full_object_path = try sub_compilation.bin_file.options.directory.join(comp.gpa, &[_][]const u8{basename}), |
| 2174 | .lock = sub_compilation.bin_file.toOwnedLock(), |
| 2175 | }; |
| 2176 | } |