authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-11-28 22:47:34-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-01 17:51:18-07:00
logc20ad51c621ba18d2c90cc96d1b550831dc5d7a3
tree41786dd2be23e90fb13c3c867ad3881117b09b0f
parent134e8cf76a6664ebd028fbcbfbd7a1b85ad031f5

introduce std.Build.Module and extract some logic into it

This moves many settings from `std.Build.Step.Compile` and into `std.Build.Module`, and then makes them transitive. In other words, it adds support for exposing Zig modules in packages, which are configured in various ways, such as depending on other link objects, include paths, or even a different optimization mode. Now, transitive dependencies will be included in the compilation, so you can, for example, make a Zig module depend on some C source code, and expose that Zig module in a package. Currently, the compiler frontend autogenerates only one `@import("builtin")` module for the entire compilation, however, a future enhancement will be to make it honor the differences in modules, so that modules can be compiled with different optimization modes, code model, valgrind integration, or even target CPU feature set. closes #14719

4 files changed, 991 insertions(+), 950 deletions(-)

lib/std/Build.zig+44-120
...@@ -29,36 +29,7 @@ pub const Builder = Build;...@@ -29,36 +29,7 @@ pub const Builder = Build;
29pub const InstallDirectoryOptions = Step.InstallDir.Options;29pub const InstallDirectoryOptions = Step.InstallDir.Options;
3030
31pub const Step = @import("Build/Step.zig");31pub const Step = @import("Build/Step.zig");
32/// deprecated: use `Step.CheckFile`.32pub const Module = @import("Build/Module.zig");
33pub const CheckFileStep = @import("Build/Step/CheckFile.zig");
34/// deprecated: use `Step.CheckObject`.
35pub const CheckObjectStep = @import("Build/Step/CheckObject.zig");
36/// deprecated: use `Step.ConfigHeader`.
37pub const ConfigHeaderStep = @import("Build/Step/ConfigHeader.zig");
38/// deprecated: use `Step.Fmt`.
39pub const FmtStep = @import("Build/Step/Fmt.zig");
40/// deprecated: use `Step.InstallArtifact`.
41pub const InstallArtifactStep = @import("Build/Step/InstallArtifact.zig");
42/// deprecated: use `Step.InstallDir`.
43pub const InstallDirStep = @import("Build/Step/InstallDir.zig");
44/// deprecated: use `Step.InstallFile`.
45pub const InstallFileStep = @import("Build/Step/InstallFile.zig");
46/// deprecated: use `Step.ObjCopy`.
47pub const ObjCopyStep = @import("Build/Step/ObjCopy.zig");
48/// deprecated: use `Step.Compile`.
49pub const CompileStep = @import("Build/Step/Compile.zig");
50/// deprecated: use `Step.Options`.
51pub const OptionsStep = @import("Build/Step/Options.zig");
52/// deprecated: use `Step.RemoveDir`.
53pub const RemoveDirStep = @import("Build/Step/RemoveDir.zig");
54/// deprecated: use `Step.Run`.
55pub const RunStep = @import("Build/Step/Run.zig");
56/// deprecated: use `Step.TranslateC`.
57pub const TranslateCStep = @import("Build/Step/TranslateC.zig");
58/// deprecated: use `Step.WriteFile`.
59pub const WriteFileStep = @import("Build/Step/WriteFile.zig");
60/// deprecated: use `LazyPath`.
61pub const FileSource = LazyPath;
6233
63install_tls: TopLevelStep,34install_tls: TopLevelStep,
64uninstall_tls: TopLevelStep,35uninstall_tls: TopLevelStep,
...@@ -634,34 +605,31 @@ pub const ExecutableOptions = struct {...@@ -634,34 +605,31 @@ pub const ExecutableOptions = struct {
634 use_llvm: ?bool = null,605 use_llvm: ?bool = null,
635 use_lld: ?bool = null,606 use_lld: ?bool = null,
636 zig_lib_dir: ?LazyPath = null,607 zig_lib_dir: ?LazyPath = null,
637 main_mod_path: ?LazyPath = null,
638 /// Embed a `.manifest` file in the compilation if the object format supports it.608 /// Embed a `.manifest` file in the compilation if the object format supports it.
639 /// https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-files-reference609 /// https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-files-reference
640 /// Manifest files must have the extension `.manifest`.610 /// Manifest files must have the extension `.manifest`.
641 /// Can be set regardless of target. The `.manifest` file will be ignored611 /// Can be set regardless of target. The `.manifest` file will be ignored
642 /// if the target object format does not support embedded manifests.612 /// if the target object format does not support embedded manifests.
643 win32_manifest: ?LazyPath = null,613 win32_manifest: ?LazyPath = null,
644
645 /// Deprecated; use `main_mod_path`.
646 main_pkg_path: ?LazyPath = null,
647};614};
648615
649pub fn addExecutable(b: *Build, options: ExecutableOptions) *Step.Compile {616pub fn addExecutable(b: *Build, options: ExecutableOptions) *Step.Compile {
650 return Step.Compile.create(b, .{617 return Step.Compile.create(b, .{
651 .name = options.name,618 .name = options.name,
652 .root_source_file = options.root_source_file,619 .root_module = .{
620 .root_source_file = options.root_source_file,
621 .target = options.target,
622 .optimize = options.optimize,
623 .link_libc = options.link_libc,
624 .single_threaded = options.single_threaded,
625 },
653 .version = options.version,626 .version = options.version,
654 .target = options.target,
655 .optimize = options.optimize,
656 .kind = .exe,627 .kind = .exe,
657 .linkage = options.linkage,628 .linkage = options.linkage,
658 .max_rss = options.max_rss,629 .max_rss = options.max_rss,
659 .link_libc = options.link_libc,
660 .single_threaded = options.single_threaded,
661 .use_llvm = options.use_llvm,630 .use_llvm = options.use_llvm,
662 .use_lld = options.use_lld,631 .use_lld = options.use_lld,
663 .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir,632 .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir,
664 .main_mod_path = options.main_mod_path orelse options.main_pkg_path,
665 .win32_manifest = options.win32_manifest,633 .win32_manifest = options.win32_manifest,
666 });634 });
667}635}
...@@ -677,26 +645,23 @@ pub const ObjectOptions = struct {...@@ -677,26 +645,23 @@ pub const ObjectOptions = struct {
677 use_llvm: ?bool = null,645 use_llvm: ?bool = null,
678 use_lld: ?bool = null,646 use_lld: ?bool = null,
679 zig_lib_dir: ?LazyPath = null,647 zig_lib_dir: ?LazyPath = null,
680 main_mod_path: ?LazyPath = null,
681
682 /// Deprecated; use `main_mod_path`.
683 main_pkg_path: ?LazyPath = null,
684};648};
685649
686pub fn addObject(b: *Build, options: ObjectOptions) *Step.Compile {650pub fn addObject(b: *Build, options: ObjectOptions) *Step.Compile {
687 return Step.Compile.create(b, .{651 return Step.Compile.create(b, .{
688 .name = options.name,652 .name = options.name,
689 .root_source_file = options.root_source_file,653 .root_module = .{
690 .target = options.target,654 .root_source_file = options.root_source_file,
691 .optimize = options.optimize,655 .target = options.target,
656 .optimize = options.optimize,
657 .link_libc = options.link_libc,
658 .single_threaded = options.single_threaded,
659 },
692 .kind = .obj,660 .kind = .obj,
693 .max_rss = options.max_rss,661 .max_rss = options.max_rss,
694 .link_libc = options.link_libc,
695 .single_threaded = options.single_threaded,
696 .use_llvm = options.use_llvm,662 .use_llvm = options.use_llvm,
697 .use_lld = options.use_lld,663 .use_lld = options.use_lld,
698 .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir,664 .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir,
699 .main_mod_path = options.main_mod_path orelse options.main_pkg_path,
700 });665 });
701}666}
702667
...@@ -712,34 +677,31 @@ pub const SharedLibraryOptions = struct {...@@ -712,34 +677,31 @@ pub const SharedLibraryOptions = struct {
712 use_llvm: ?bool = null,677 use_llvm: ?bool = null,
713 use_lld: ?bool = null,678 use_lld: ?bool = null,
714 zig_lib_dir: ?LazyPath = null,679 zig_lib_dir: ?LazyPath = null,
715 main_mod_path: ?LazyPath = null,
716 /// Embed a `.manifest` file in the compilation if the object format supports it.680 /// Embed a `.manifest` file in the compilation if the object format supports it.
717 /// https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-files-reference681 /// https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-files-reference
718 /// Manifest files must have the extension `.manifest`.682 /// Manifest files must have the extension `.manifest`.
719 /// Can be set regardless of target. The `.manifest` file will be ignored683 /// Can be set regardless of target. The `.manifest` file will be ignored
720 /// if the target object format does not support embedded manifests.684 /// if the target object format does not support embedded manifests.
721 win32_manifest: ?LazyPath = null,685 win32_manifest: ?LazyPath = null,
722
723 /// Deprecated; use `main_mod_path`.
724 main_pkg_path: ?LazyPath = null,
725};686};
726687
727pub fn addSharedLibrary(b: *Build, options: SharedLibraryOptions) *Step.Compile {688pub fn addSharedLibrary(b: *Build, options: SharedLibraryOptions) *Step.Compile {
728 return Step.Compile.create(b, .{689 return Step.Compile.create(b, .{
729 .name = options.name,690 .name = options.name,
730 .root_source_file = options.root_source_file,691 .root_module = .{
692 .target = options.target,
693 .optimize = options.optimize,
694 .root_source_file = options.root_source_file,
695 .link_libc = options.link_libc,
696 .single_threaded = options.single_threaded,
697 },
731 .kind = .lib,698 .kind = .lib,
732 .linkage = .dynamic,699 .linkage = .dynamic,
733 .version = options.version,700 .version = options.version,
734 .target = options.target,
735 .optimize = options.optimize,
736 .max_rss = options.max_rss,701 .max_rss = options.max_rss,
737 .link_libc = options.link_libc,
738 .single_threaded = options.single_threaded,
739 .use_llvm = options.use_llvm,702 .use_llvm = options.use_llvm,
740 .use_lld = options.use_lld,703 .use_lld = options.use_lld,
741 .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir,704 .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir,
742 .main_mod_path = options.main_mod_path orelse options.main_pkg_path,
743 .win32_manifest = options.win32_manifest,705 .win32_manifest = options.win32_manifest,
744 });706 });
745}707}
...@@ -756,28 +718,25 @@ pub const StaticLibraryOptions = struct {...@@ -756,28 +718,25 @@ pub const StaticLibraryOptions = struct {
756 use_llvm: ?bool = null,718 use_llvm: ?bool = null,
757 use_lld: ?bool = null,719 use_lld: ?bool = null,
758 zig_lib_dir: ?LazyPath = null,720 zig_lib_dir: ?LazyPath = null,
759 main_mod_path: ?LazyPath = null,
760
761 /// Deprecated; use `main_mod_path`.
762 main_pkg_path: ?LazyPath = null,
763};721};
764722
765pub fn addStaticLibrary(b: *Build, options: StaticLibraryOptions) *Step.Compile {723pub fn addStaticLibrary(b: *Build, options: StaticLibraryOptions) *Step.Compile {
766 return Step.Compile.create(b, .{724 return Step.Compile.create(b, .{
767 .name = options.name,725 .name = options.name,
768 .root_source_file = options.root_source_file,726 .root_module = .{
727 .target = options.target,
728 .optimize = options.optimize,
729 .root_source_file = options.root_source_file,
730 .link_libc = options.link_libc,
731 .single_threaded = options.single_threaded,
732 },
769 .kind = .lib,733 .kind = .lib,
770 .linkage = .static,734 .linkage = .static,
771 .version = options.version,735 .version = options.version,
772 .target = options.target,
773 .optimize = options.optimize,
774 .max_rss = options.max_rss,736 .max_rss = options.max_rss,
775 .link_libc = options.link_libc,
776 .single_threaded = options.single_threaded,
777 .use_llvm = options.use_llvm,737 .use_llvm = options.use_llvm,
778 .use_lld = options.use_lld,738 .use_lld = options.use_lld,
779 .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir,739 .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir,
780 .main_mod_path = options.main_mod_path orelse options.main_pkg_path,
781 });740 });
782}741}
783742
...@@ -795,28 +754,25 @@ pub const TestOptions = struct {...@@ -795,28 +754,25 @@ pub const TestOptions = struct {
795 use_llvm: ?bool = null,754 use_llvm: ?bool = null,
796 use_lld: ?bool = null,755 use_lld: ?bool = null,
797 zig_lib_dir: ?LazyPath = null,756 zig_lib_dir: ?LazyPath = null,
798 main_mod_path: ?LazyPath = null,
799
800 /// Deprecated; use `main_mod_path`.
801 main_pkg_path: ?LazyPath = null,
802};757};
803758
804pub fn addTest(b: *Build, options: TestOptions) *Step.Compile {759pub fn addTest(b: *Build, options: TestOptions) *Step.Compile {
805 return Step.Compile.create(b, .{760 return Step.Compile.create(b, .{
806 .name = options.name,761 .name = options.name,
807 .kind = .@"test",762 .kind = .@"test",
808 .root_source_file = options.root_source_file,763 .root_module = .{
809 .target = options.target,764 .root_source_file = options.root_source_file,
810 .optimize = options.optimize,765 .target = options.target,
766 .optimize = options.optimize,
767 .link_libc = options.link_libc,
768 .single_threaded = options.single_threaded,
769 },
811 .max_rss = options.max_rss,770 .max_rss = options.max_rss,
812 .filter = options.filter,771 .filter = options.filter,
813 .test_runner = options.test_runner,772 .test_runner = options.test_runner,
814 .link_libc = options.link_libc,
815 .single_threaded = options.single_threaded,
816 .use_llvm = options.use_llvm,773 .use_llvm = options.use_llvm,
817 .use_lld = options.use_lld,774 .use_lld = options.use_lld,
818 .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir,775 .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir,
819 .main_mod_path = options.main_mod_path orelse options.main_pkg_path,
820 });776 });
821}777}
822778
...@@ -833,9 +789,10 @@ pub fn addAssembly(b: *Build, options: AssemblyOptions) *Step.Compile {...@@ -833,9 +789,10 @@ pub fn addAssembly(b: *Build, options: AssemblyOptions) *Step.Compile {
833 const obj_step = Step.Compile.create(b, .{789 const obj_step = Step.Compile.create(b, .{
834 .name = options.name,790 .name = options.name,
835 .kind = .obj,791 .kind = .obj,
836 .root_source_file = null,792 .root_module = .{
837 .target = options.target,793 .target = options.target,
838 .optimize = options.optimize,794 .optimize = options.optimize,
795 },
839 .max_rss = options.max_rss,796 .max_rss = options.max_rss,
840 .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir,797 .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir,
841 });798 });
...@@ -846,41 +803,17 @@ pub fn addAssembly(b: *Build, options: AssemblyOptions) *Step.Compile {...@@ -846,41 +803,17 @@ pub fn addAssembly(b: *Build, options: AssemblyOptions) *Step.Compile {
846/// This function creates a module and adds it to the package's module set, making803/// This function creates a module and adds it to the package's module set, making
847/// it available to other packages which depend on this one.804/// it available to other packages which depend on this one.
848/// `createModule` can be used instead to create a private module.805/// `createModule` can be used instead to create a private module.
849pub fn addModule(b: *Build, name: []const u8, options: CreateModuleOptions) *Module {806pub fn addModule(b: *Build, name: []const u8, options: Module.CreateOptions) *Module {
850 const module = b.createModule(options);807 const module = Module.create(b, options);
851 b.modules.put(b.dupe(name), module) catch @panic("OOM");808 b.modules.put(b.dupe(name), module) catch @panic("OOM");
852 return module;809 return module;
853}810}
854811
855pub const ModuleDependency = struct {
856 name: []const u8,
857 module: *Module,
858};
859
860pub const CreateModuleOptions = struct {
861 source_file: LazyPath,
862 dependencies: []const ModuleDependency = &.{},
863};
864
865/// This function creates a private module, to be used by the current package,812/// This function creates a private module, to be used by the current package,
866/// but not exposed to other packages depending on this one.813/// but not exposed to other packages depending on this one.
867/// `addModule` can be used instead to create a public module.814/// `addModule` can be used instead to create a public module.
868pub fn createModule(b: *Build, options: CreateModuleOptions) *Module {815pub fn createModule(b: *Build, options: Module.CreateOptions) *Module {
869 const module = b.allocator.create(Module) catch @panic("OOM");816 return Module.create(b, options);
870 module.* = .{
871 .builder = b,
872 .source_file = options.source_file.dupe(b),
873 .dependencies = moduleDependenciesToArrayHashMap(b.allocator, options.dependencies),
874 };
875 return module;
876}
877
878fn moduleDependenciesToArrayHashMap(arena: Allocator, deps: []const ModuleDependency) std.StringArrayHashMap(*Module) {
879 var result = std.StringArrayHashMap(*Module).init(arena);
880 for (deps) |dep| {
881 result.put(dep.name, dep.module) catch @panic("OOM");
882 }
883 return result;
884}817}
885818
886/// Initializes a `Step.Run` with argv, which must at least have the path to the819/// Initializes a `Step.Run` with argv, which must at least have the path to the
...@@ -1885,15 +1818,6 @@ pub fn runBuild(b: *Build, build_zig: anytype) anyerror!void {...@@ -1885,15 +1818,6 @@ pub fn runBuild(b: *Build, build_zig: anytype) anyerror!void {
1885 }1818 }
1886}1819}
18871820
1888pub const Module = struct {
1889 builder: *Build,
1890 /// This could either be a generated file, in which case the module
1891 /// contains exactly one file, or it could be a path to the root source
1892 /// file of directory of files which constitute the module.
1893 source_file: LazyPath,
1894 dependencies: std.StringArrayHashMap(*Module),
1895};
1896
1897/// A file that is generated by a build step.1821/// A file that is generated by a build step.
1898/// This struct is an interface that is meant to be used with `@fieldParentPtr` to implement the actual path logic.1822/// This struct is an interface that is meant to be used with `@fieldParentPtr` to implement the actual path logic.
1899pub const GeneratedFile = struct {1823pub const GeneratedFile = struct {
lib/std/Build/Module.zig created+616
...@@ -0,0 +1,616 @@
1/// The one responsible for creating this module.
2owner: *std.Build,
3/// Tracks the set of steps that depend on this `Module`. This ensures that
4/// when making this `Module` depend on other `Module` objects and `Step`
5/// objects, respective `Step` dependencies can be added.
6depending_steps: std.AutoArrayHashMapUnmanaged(*std.Build.Step.Compile, void),
7/// This could either be a generated file, in which case the module
8/// contains exactly one file, or it could be a path to the root source
9/// file of directory of files which constitute the module.
10/// If `null`, it means this module is made up of only `link_objects`.
11root_source_file: ?LazyPath,
12/// The modules that are mapped into this module's import table.
13import_table: std.StringArrayHashMap(*Module),
14
15target: std.zig.CrossTarget,
16target_info: NativeTargetInfo,
17optimize: std.builtin.OptimizeMode,
18dwarf_format: ?std.dwarf.Format,
19
20c_macros: std.ArrayList([]const u8),
21include_dirs: std.ArrayList(IncludeDir),
22lib_paths: std.ArrayList(LazyPath),
23rpaths: std.ArrayList(LazyPath),
24frameworks: std.StringArrayHashMapUnmanaged(FrameworkLinkInfo),
25c_std: std.Build.CStd,
26link_objects: std.ArrayList(LinkObject),
27
28strip: ?bool,
29unwind_tables: ?bool,
30single_threaded: ?bool,
31stack_protector: ?bool,
32stack_check: ?bool,
33sanitize_c: ?bool,
34sanitize_thread: ?bool,
35code_model: std.builtin.CodeModel,
36/// Whether to emit machine code that integrates with Valgrind.
37valgrind: ?bool,
38/// Position Independent Code
39pic: ?bool,
40red_zone: ?bool,
41/// Whether to omit the stack frame pointer. Frees up a register and makes it
42/// more more difficiult to obtain stack traces. Has target-dependent effects.
43omit_frame_pointer: ?bool,
44/// `true` requires a compilation that includes this Module to link libc.
45/// `false` causes a build failure if a compilation that includes this Module would link libc.
46/// `null` neither requires nor prevents libc from being linked.
47link_libc: ?bool,
48/// `true` requires a compilation that includes this Module to link libc++.
49/// `false` causes a build failure if a compilation that includes this Module would link libc++.
50/// `null` neither requires nor prevents libc++ from being linked.
51link_libcpp: ?bool,
52
53/// Symbols to be exported when compiling to WebAssembly.
54export_symbol_names: []const []const u8 = &.{},
55
56pub const LinkObject = union(enum) {
57 static_path: LazyPath,
58 other_step: *std.Build.Step.Compile,
59 system_lib: SystemLib,
60 assembly_file: LazyPath,
61 c_source_file: *CSourceFile,
62 c_source_files: *CSourceFiles,
63 win32_resource_file: *RcSourceFile,
64};
65
66pub const SystemLib = struct {
67 name: []const u8,
68 needed: bool,
69 weak: bool,
70 use_pkg_config: UsePkgConfig,
71 preferred_link_mode: std.builtin.LinkMode,
72 search_strategy: SystemLib.SearchStrategy,
73
74 pub const UsePkgConfig = enum {
75 /// Don't use pkg-config, just pass -lfoo where foo is name.
76 no,
77 /// Try to get information on how to link the library from pkg-config.
78 /// If that fails, fall back to passing -lfoo where foo is name.
79 yes,
80 /// Try to get information on how to link the library from pkg-config.
81 /// If that fails, error out.
82 force,
83 };
84
85 pub const SearchStrategy = enum { paths_first, mode_first, no_fallback };
86};
87
88pub const CSourceFiles = struct {
89 dependency: ?*std.Build.Dependency,
90 /// If `dependency` is not null relative to it,
91 /// else relative to the build root.
92 files: []const []const u8,
93 flags: []const []const u8,
94};
95
96pub const CSourceFile = struct {
97 file: LazyPath,
98 flags: []const []const u8,
99
100 pub fn dupe(self: CSourceFile, b: *std.Build) CSourceFile {
101 return .{
102 .file = self.file.dupe(b),
103 .flags = b.dupeStrings(self.flags),
104 };
105 }
106};
107
108pub const RcSourceFile = struct {
109 file: LazyPath,
110 /// Any option that rc.exe accepts will work here, with the exception of:
111 /// - `/fo`: The output filename is set by the build system
112 /// - `/p`: Only running the preprocessor is not supported in this context
113 /// - `/:no-preprocess` (non-standard option): Not supported in this context
114 /// - Any MUI-related option
115 /// https://learn.microsoft.com/en-us/windows/win32/menurc/using-rc-the-rc-command-line-
116 ///
117 /// Implicitly defined options:
118 /// /x (ignore the INCLUDE environment variable)
119 /// /D_DEBUG or /DNDEBUG depending on the optimization mode
120 flags: []const []const u8 = &.{},
121
122 pub fn dupe(self: RcSourceFile, b: *std.Build) RcSourceFile {
123 return .{
124 .file = self.file.dupe(b),
125 .flags = b.dupeStrings(self.flags),
126 };
127 }
128};
129
130pub const IncludeDir = union(enum) {
131 path: LazyPath,
132 path_system: LazyPath,
133 path_after: LazyPath,
134 framework_path: LazyPath,
135 framework_path_system: LazyPath,
136 other_step: *std.Build.Step.Compile,
137 config_header_step: *std.Build.Step.ConfigHeader,
138};
139
140pub const FrameworkLinkInfo = struct {
141 needed: bool = false,
142 weak: bool = false,
143};
144
145pub const CreateOptions = struct {
146 target: std.zig.CrossTarget,
147 target_info: ?NativeTargetInfo = null,
148 optimize: std.builtin.OptimizeMode,
149 root_source_file: ?LazyPath = null,
150 import_table: []const Import = &.{},
151 link_libc: ?bool = null,
152 link_libcpp: ?bool = null,
153 single_threaded: ?bool = null,
154 strip: ?bool = null,
155 unwind_tables: ?bool = null,
156 dwarf_format: ?std.dwarf.Format = null,
157 c_std: std.Build.CStd = .C99,
158 code_model: std.builtin.CodeModel = .default,
159 stack_protector: ?bool = null,
160 stack_check: ?bool = null,
161 sanitize_c: ?bool = null,
162 sanitize_thread: ?bool = null,
163 valgrind: ?bool = null,
164 pic: ?bool = null,
165 red_zone: ?bool = null,
166 /// Whether to omit the stack frame pointer. Frees up a register and makes it
167 /// more more difficiult to obtain stack traces. Has target-dependent effects.
168 omit_frame_pointer: ?bool = null,
169};
170
171pub const Import = struct {
172 name: []const u8,
173 module: *Module,
174};
175
176pub fn init(owner: *std.Build, options: CreateOptions, compile: ?*std.Build.Step.Compile) Module {
177 var m: Module = .{
178 .owner = owner,
179 .depending_steps = .{},
180 .root_source_file = if (options.root_source_file) |lp| lp.dupe(owner) else null,
181 .import_table = std.StringArrayHashMap(*Module).init(owner.allocator),
182 .target = options.target,
183 .target_info = options.target_info orelse
184 NativeTargetInfo.detect(options.target) catch @panic("unhandled error"),
185 .optimize = options.optimize,
186 .link_libc = options.link_libc,
187 .link_libcpp = options.link_libcpp,
188 .dwarf_format = options.dwarf_format,
189 .c_macros = std.ArrayList([]const u8).init(owner.allocator),
190 .include_dirs = std.ArrayList(IncludeDir).init(owner.allocator),
191 .lib_paths = std.ArrayList(LazyPath).init(owner.allocator),
192 .rpaths = std.ArrayList(LazyPath).init(owner.allocator),
193 .frameworks = .{},
194 .c_std = options.c_std,
195 .link_objects = std.ArrayList(LinkObject).init(owner.allocator),
196 .strip = options.strip,
197 .unwind_tables = options.unwind_tables,
198 .single_threaded = options.single_threaded,
199 .stack_protector = options.stack_protector,
200 .stack_check = options.stack_check,
201 .sanitize_c = options.sanitize_c,
202 .sanitize_thread = options.sanitize_thread,
203 .code_model = options.code_model,
204 .valgrind = options.valgrind,
205 .pic = options.pic,
206 .red_zone = options.red_zone,
207 .omit_frame_pointer = options.omit_frame_pointer,
208 .export_symbol_names = &.{},
209 };
210
211 if (compile) |c| {
212 m.depending_steps.put(owner.allocator, c, {}) catch @panic("OOM");
213 }
214
215 m.import_table.ensureUnusedCapacity(options.import_table.len) catch @panic("OOM");
216 for (options.import_table) |dep| {
217 m.import_table.putAssumeCapacity(dep.name, dep.module);
218 }
219
220 var it = m.iterateDependencies(null);
221 while (it.next()) |item| addShallowDependencies(&m, item.module);
222
223 return m;
224}
225
226pub fn create(owner: *std.Build, options: CreateOptions) *Module {
227 const m = owner.allocator.create(Module) catch @panic("OOM");
228 m.* = init(owner, options, null);
229 return m;
230}
231
232/// Adds an existing module to be used with `@import`.
233pub fn addImport(m: *Module, name: []const u8, module: *Module) void {
234 const b = m.owner;
235 m.import_table.put(b.dupe(name), module) catch @panic("OOM");
236
237 var it = module.iterateDependencies(null);
238 while (it.next()) |item| addShallowDependencies(m, item.module);
239}
240
241/// Creates step dependencies and updates `depending_steps` of `dependee` so that
242/// subsequent calls to `addImport` on `dependee` will additionally create step
243/// dependencies on `m`'s `depending_steps`.
244fn addShallowDependencies(m: *Module, dependee: *Module) void {
245 if (dependee.root_source_file) |lazy_path| addLazyPathDependencies(m, dependee, lazy_path);
246 for (dependee.lib_paths.items) |lib_path| addLazyPathDependencies(m, dependee, lib_path);
247 for (dependee.rpaths.items) |rpath| addLazyPathDependencies(m, dependee, rpath);
248
249 for (dependee.link_objects.items) |link_object| switch (link_object) {
250 .other_step => |compile| addStepDependencies(m, dependee, &compile.step),
251
252 .static_path,
253 .assembly_file,
254 => |lp| addLazyPathDependencies(m, dependee, lp),
255
256 .c_source_file => |x| addLazyPathDependencies(m, dependee, x.file),
257 .win32_resource_file => |x| addLazyPathDependencies(m, dependee, x.file),
258
259 .c_source_files,
260 .system_lib,
261 => {},
262 };
263}
264
265fn addLazyPathDependencies(m: *Module, module: *Module, lazy_path: LazyPath) void {
266 addLazyPathDependenciesOnly(m, lazy_path);
267 if (m != module) {
268 for (m.depending_steps.keys()) |compile| {
269 module.depending_steps.put(m.owner.allocator, compile, {}) catch @panic("OOM");
270 }
271 }
272}
273
274fn addLazyPathDependenciesOnly(m: *Module, lazy_path: LazyPath) void {
275 for (m.depending_steps.keys()) |compile| {
276 lazy_path.addStepDependencies(&compile.step);
277 }
278}
279
280fn addStepDependencies(m: *Module, module: *Module, dependee: *std.Build.Step) void {
281 addStepDependenciesOnly(m, dependee);
282 if (m != module) {
283 for (m.depending_steps.keys()) |compile| {
284 module.depending_steps.put(m.owner.allocator, compile, {}) catch @panic("OOM");
285 }
286 }
287}
288
289fn addStepDependenciesOnly(m: *Module, dependee: *std.Build.Step) void {
290 for (m.depending_steps.keys()) |compile| {
291 compile.step.dependOn(dependee);
292 }
293}
294
295/// Creates a new module and adds it to be used with `@import`.
296pub fn addAnonymousImport(m: *Module, name: []const u8, options: std.Build.CreateModuleOptions) void {
297 const b = m.step.owner;
298 const module = b.createModule(options);
299 return addImport(m, name, module);
300}
301
302pub fn addOptions(m: *Module, module_name: []const u8, options: *std.Build.Step.Options) void {
303 addImport(m, module_name, options.createModule());
304}
305
306pub const DependencyIterator = struct {
307 allocator: std.mem.Allocator,
308 index: usize,
309 set: std.AutoArrayHashMapUnmanaged(Key, []const u8),
310
311 pub const Key = struct {
312 /// The compilation that contains the `Module`. Note that a `Module` might be
313 /// used by more than one compilation.
314 compile: ?*std.Build.Step.Compile,
315 module: *Module,
316 };
317
318 pub const Item = struct {
319 /// The compilation that contains the `Module`. Note that a `Module` might be
320 /// used by more than one compilation.
321 compile: ?*std.Build.Step.Compile,
322 module: *Module,
323 name: []const u8,
324 };
325
326 pub fn deinit(it: *DependencyIterator) void {
327 it.set.deinit(it.allocator);
328 it.* = undefined;
329 }
330
331 pub fn next(it: *DependencyIterator) ?Item {
332 if (it.index >= it.set.count()) {
333 it.set.clearAndFree(it.allocator);
334 return null;
335 }
336 const key = it.set.keys()[it.index];
337 const name = it.set.values()[it.index];
338 it.index += 1;
339 const module = key.module;
340 it.set.ensureUnusedCapacity(it.allocator, module.import_table.count()) catch
341 @panic("OOM");
342 for (module.import_table.keys(), module.import_table.values()) |dep_name, dep| {
343 it.set.putAssumeCapacity(.{
344 .module = dep,
345 .compile = key.compile,
346 }, dep_name);
347 }
348
349 if (key.compile != null) {
350 for (module.link_objects.items) |link_object| switch (link_object) {
351 .other_step => |compile| {
352 it.set.put(it.allocator, .{
353 .module = &compile.root_module,
354 .compile = compile,
355 }, "root") catch @panic("OOM");
356 },
357 else => {},
358 };
359 }
360
361 return .{
362 .compile = key.compile,
363 .module = key.module,
364 .name = name,
365 };
366 }
367};
368
369pub fn iterateDependencies(
370 m: *Module,
371 chase_steps: ?*std.Build.Step.Compile,
372) DependencyIterator {
373 var it: DependencyIterator = .{
374 .allocator = m.owner.allocator,
375 .index = 0,
376 .set = .{},
377 };
378 it.set.ensureUnusedCapacity(m.owner.allocator, m.import_table.count() + 1) catch @panic("OOM");
379 it.set.putAssumeCapacity(.{
380 .module = m,
381 .compile = chase_steps,
382 }, "root");
383 return it;
384}
385
386pub const LinkSystemLibraryOptions = struct {
387 needed: bool = false,
388 weak: bool = false,
389 use_pkg_config: SystemLib.UsePkgConfig = .yes,
390 preferred_link_mode: std.builtin.LinkMode = .Dynamic,
391 search_strategy: SystemLib.SearchStrategy = .paths_first,
392};
393
394pub fn linkSystemLibrary(
395 m: *Module,
396 name: []const u8,
397 options: LinkSystemLibraryOptions,
398) void {
399 const b = m.owner;
400 if (m.target_info.target.is_libc_lib_name(name)) {
401 m.link_libc = true;
402 return;
403 }
404 if (m.target_info.target.is_libcpp_lib_name(name)) {
405 m.link_libcpp = true;
406 return;
407 }
408
409 m.link_objects.append(.{
410 .system_lib = .{
411 .name = b.dupe(name),
412 .needed = options.needed,
413 .weak = options.weak,
414 .use_pkg_config = options.use_pkg_config,
415 .preferred_link_mode = options.preferred_link_mode,
416 .search_strategy = options.search_strategy,
417 },
418 }) catch @panic("OOM");
419}
420
421pub const AddCSourceFilesOptions = struct {
422 /// When provided, `files` are relative to `dependency` rather than the
423 /// package that owns the `Compile` step.
424 dependency: ?*std.Build.Dependency = null,
425 files: []const []const u8,
426 flags: []const []const u8 = &.{},
427};
428
429/// Handy when you have many C/C++ source files and want them all to have the same flags.
430pub fn addCSourceFiles(m: *Module, options: AddCSourceFilesOptions) void {
431 const c_source_files = m.owner.allocator.create(CSourceFiles) catch @panic("OOM");
432 c_source_files.* = .{
433 .dependency = options.dependency,
434 .files = m.owner.dupeStrings(options.files),
435 .flags = m.owner.dupeStrings(options.flags),
436 };
437 m.link_objects.append(.{ .c_source_files = c_source_files }) catch @panic("OOM");
438}
439
440pub fn addCSourceFile(m: *Module, source: CSourceFile) void {
441 const c_source_file = m.owner.allocator.create(CSourceFile) catch @panic("OOM");
442 c_source_file.* = source.dupe(m.owner);
443 m.link_objects.append(.{ .c_source_file = c_source_file }) catch @panic("OOM");
444 addLazyPathDependenciesOnly(m, source.file);
445}
446
447/// Resource files must have the extension `.rc`.
448/// Can be called regardless of target. The .rc file will be ignored
449/// if the target object format does not support embedded resources.
450pub fn addWin32ResourceFile(m: *Module, source: RcSourceFile) void {
451 // Only the PE/COFF format has a Resource Table, so for any other target
452 // the resource file is ignored.
453 if (m.target_info.target.ofmt != .coff) return;
454
455 const rc_source_file = m.owner.allocator.create(RcSourceFile) catch @panic("OOM");
456 rc_source_file.* = source.dupe(m.owner);
457 m.link_objects.append(.{ .win32_resource_file = rc_source_file }) catch @panic("OOM");
458 addLazyPathDependenciesOnly(m, source.file);
459}
460
461pub fn addAssemblyFile(m: *Module, source: LazyPath) void {
462 m.link_objects.append(.{ .assembly_file = source.dupe(m.owner) }) catch @panic("OOM");
463 addLazyPathDependenciesOnly(m, source);
464}
465
466pub fn addObjectFile(m: *Module, source: LazyPath) void {
467 m.link_objects.append(.{ .static_path = source.dupe(m.owner) }) catch @panic("OOM");
468 addLazyPathDependencies(m, source);
469}
470
471pub fn appendZigProcessFlags(
472 m: *Module,
473 zig_args: *std.ArrayList([]const u8),
474 asking_step: ?*std.Build.Step,
475) !void {
476 const b = m.owner;
477
478 try addFlag(zig_args, m.strip, "-fstrip", "-fno-strip");
479 try addFlag(zig_args, m.unwind_tables, "-funwind-tables", "-fno-unwind-tables");
480 try addFlag(zig_args, m.single_threaded, "-fsingle-threaded", "-fno-single-threaded");
481 try addFlag(zig_args, m.stack_check, "-fstack-check", "-fno-stack-check");
482 try addFlag(zig_args, m.stack_protector, "-fstack-protector", "-fno-stack-protector");
483 try addFlag(zig_args, m.omit_frame_pointer, "-fomit-frame-pointer", "-fno-omit-frame-pointer");
484 try addFlag(zig_args, m.sanitize_c, "-fsanitize-c", "-fno-sanitize-c");
485 try addFlag(zig_args, m.sanitize_thread, "-fsanitize-thread", "-fno-sanitize-thread");
486 try addFlag(zig_args, m.valgrind, "-fvalgrind", "-fno-valgrind");
487 try addFlag(zig_args, m.pic, "-fPIC", "-fno-PIC");
488 try addFlag(zig_args, m.red_zone, "-mred-zone", "-mno-red-zone");
489
490 if (m.dwarf_format) |dwarf_format| {
491 try zig_args.append(switch (dwarf_format) {
492 .@"32" => "-gdwarf32",
493 .@"64" => "-gdwarf64",
494 });
495 }
496
497 try zig_args.ensureUnusedCapacity(1);
498 switch (m.optimize) {
499 .Debug => {}, // Skip since it's the default.
500 .ReleaseSmall => zig_args.appendAssumeCapacity("-OReleaseSmall"),
501 .ReleaseFast => zig_args.appendAssumeCapacity("-OReleaseFast"),
502 .ReleaseSafe => zig_args.appendAssumeCapacity("-OReleaseSafe"),
503 }
504
505 if (m.code_model != .default) {
506 try zig_args.append("-mcmodel");
507 try zig_args.append(@tagName(m.code_model));
508 }
509
510 if (!m.target.isNative()) {
511 try zig_args.appendSlice(&.{
512 "-target", try m.target.zigTriple(b.allocator),
513 "-mcpu", try std.Build.serializeCpu(b.allocator, m.target.getCpu()),
514 });
515
516 if (m.target.dynamic_linker.get()) |dynamic_linker| {
517 try zig_args.append("--dynamic-linker");
518 try zig_args.append(dynamic_linker);
519 }
520 }
521
522 for (m.export_symbol_names) |symbol_name| {
523 try zig_args.append(b.fmt("--export={s}", .{symbol_name}));
524 }
525
526 for (m.include_dirs.items) |include_dir| {
527 switch (include_dir) {
528 .path => |include_path| {
529 try zig_args.append("-I");
530 try zig_args.append(include_path.getPath(b));
531 },
532 .path_system => |include_path| {
533 try zig_args.append("-isystem");
534 try zig_args.append(include_path.getPath(b));
535 },
536 .path_after => |include_path| {
537 try zig_args.append("-idirafter");
538 try zig_args.append(include_path.getPath(b));
539 },
540 .framework_path => |include_path| {
541 try zig_args.append("-F");
542 try zig_args.append(include_path.getPath2(b, asking_step));
543 },
544 .framework_path_system => |include_path| {
545 try zig_args.append("-iframework");
546 try zig_args.append(include_path.getPath2(b, asking_step));
547 },
548 .other_step => |other| {
549 if (other.generated_h) |header| {
550 try zig_args.append("-isystem");
551 try zig_args.append(std.fs.path.dirname(header.path.?).?);
552 }
553 if (other.installed_headers.items.len > 0) {
554 try zig_args.append("-I");
555 try zig_args.append(b.pathJoin(&.{
556 other.step.owner.install_prefix, "include",
557 }));
558 }
559 },
560 .config_header_step => |config_header| {
561 const full_file_path = config_header.output_file.path.?;
562 const header_dir_path = full_file_path[0 .. full_file_path.len - config_header.include_path.len];
563 try zig_args.appendSlice(&.{ "-I", header_dir_path });
564 },
565 }
566 }
567
568 for (m.c_macros.items) |c_macro| {
569 try zig_args.append("-D");
570 try zig_args.append(c_macro);
571 }
572
573 try zig_args.ensureUnusedCapacity(2 * m.lib_paths.items.len);
574 for (m.lib_paths.items) |lib_path| {
575 zig_args.appendAssumeCapacity("-L");
576 zig_args.appendAssumeCapacity(lib_path.getPath2(b, asking_step));
577 }
578
579 try zig_args.ensureUnusedCapacity(2 * m.rpaths.items.len);
580 for (m.rpaths.items) |rpath| {
581 zig_args.appendAssumeCapacity("-rpath");
582
583 if (m.target_info.target.isDarwin()) switch (rpath) {
584 .path, .cwd_relative => |path| {
585 // On Darwin, we should not try to expand special runtime paths such as
586 // * @executable_path
587 // * @loader_path
588 if (std.mem.startsWith(u8, path, "@executable_path") or
589 std.mem.startsWith(u8, path, "@loader_path"))
590 {
591 zig_args.appendAssumeCapacity(path);
592 continue;
593 }
594 },
595 .generated, .dependency => {},
596 };
597
598 zig_args.appendAssumeCapacity(rpath.getPath2(b, asking_step));
599 }
600}
601
602fn addFlag(
603 args: *std.ArrayList([]const u8),
604 opt: ?bool,
605 then_name: []const u8,
606 else_name: []const u8,
607) !void {
608 const cond = opt orelse return;
609 return args.append(if (cond) then_name else else_name);
610}
611
612const Module = @This();
613const std = @import("std");
614const assert = std.debug.assert;
615const LazyPath = std.Build.LazyPath;
616const NativeTargetInfo = std.zig.system.NativeTargetInfo;
lib/std/Build/Step/Compile.zig+313-812
...@@ -24,36 +24,24 @@ const Compile = @This();...@@ -24,36 +24,24 @@ const Compile = @This();
24pub const base_id: Step.Id = .compile;24pub const base_id: Step.Id = .compile;
2525
26step: Step,26step: Step,
27root_module: Module,
28
27name: []const u8,29name: []const u8,
28target: CrossTarget,
29target_info: NativeTargetInfo,
30optimize: std.builtin.OptimizeMode,
31linker_script: ?LazyPath = null,30linker_script: ?LazyPath = null,
32version_script: ?[]const u8 = null,31version_script: ?[]const u8 = null,
33out_filename: []const u8,32out_filename: []const u8,
33out_lib_filename: []const u8,
34linkage: ?Linkage = null,34linkage: ?Linkage = null,
35version: ?std.SemanticVersion,35version: ?std.SemanticVersion,
36kind: Kind,36kind: Kind,
37major_only_filename: ?[]const u8,37major_only_filename: ?[]const u8,
38name_only_filename: ?[]const u8,38name_only_filename: ?[]const u8,
39strip: ?bool,
40formatted_panics: ?bool = null,
41unwind_tables: ?bool,
42// keep in sync with src/link.zig:CompressDebugSections39// keep in sync with src/link.zig:CompressDebugSections
43compress_debug_sections: enum { none, zlib, zstd } = .none,40compress_debug_sections: enum { none, zlib, zstd } = .none,
44lib_paths: ArrayList(LazyPath),
45rpaths: ArrayList(LazyPath),
46frameworks: StringHashMap(FrameworkLinkInfo),
47verbose_link: bool,41verbose_link: bool,
48verbose_cc: bool,42verbose_cc: bool,
49bundle_compiler_rt: ?bool = null,43bundle_compiler_rt: ?bool = null,
50single_threaded: ?bool,
51stack_protector: ?bool = null,
52disable_stack_probing: bool,
53disable_sanitize_c: bool,
54sanitize_thread: bool,
55rdynamic: bool,44rdynamic: bool,
56dwarf_format: ?std.dwarf.Format = null,
57import_memory: bool = false,45import_memory: bool = false,
58export_memory: bool = false,46export_memory: bool = false,
59/// For WebAssembly targets, this will allow for undefined symbols to47/// For WebAssembly targets, this will allow for undefined symbols to
...@@ -65,31 +53,16 @@ initial_memory: ?u64 = null,...@@ -65,31 +53,16 @@ initial_memory: ?u64 = null,
65max_memory: ?u64 = null,53max_memory: ?u64 = null,
66shared_memory: bool = false,54shared_memory: bool = false,
67global_base: ?u64 = null,55global_base: ?u64 = null,
68c_std: std.Build.CStd,
69/// Set via options; intended to be read-only after that.56/// Set via options; intended to be read-only after that.
70zig_lib_dir: ?LazyPath,57zig_lib_dir: ?LazyPath,
71/// Set via options; intended to be read-only after that.
72main_mod_path: ?LazyPath,
73exec_cmd_args: ?[]const ?[]const u8,58exec_cmd_args: ?[]const ?[]const u8,
74filter: ?[]const u8,59filter: ?[]const u8,
75test_evented_io: bool = false,60test_evented_io: bool = false,
76test_runner: ?[]const u8,61test_runner: ?[]const u8,
77test_server_mode: bool,62test_server_mode: bool,
78code_model: std.builtin.CodeModel = .default,
79wasi_exec_model: ?std.builtin.WasiExecModel = null,63wasi_exec_model: ?std.builtin.WasiExecModel = null,
80/// Symbols to be exported when compiling to wasm
81export_symbol_names: []const []const u8 = &.{},
82
83root_src: ?LazyPath,
84out_lib_filename: []const u8,
85modules: std.StringArrayHashMap(*Module),
8664
87link_objects: ArrayList(LinkObject),
88include_dirs: ArrayList(IncludeDir),
89c_macros: ArrayList([]const u8),
90installed_headers: ArrayList(*Step),65installed_headers: ArrayList(*Step),
91is_linking_libc: bool,
92is_linking_libcpp: bool,
93vcpkg_bin_path: ?[]const u8 = null,66vcpkg_bin_path: ?[]const u8 = null,
9467
95// keep in sync with src/Compilation.zig:RcIncludes68// keep in sync with src/Compilation.zig:RcIncludes
...@@ -111,7 +84,6 @@ image_base: ?u64 = null,...@@ -111,7 +84,6 @@ image_base: ?u64 = null,
11184
112libc_file: ?LazyPath = null,85libc_file: ?LazyPath = null,
11386
114valgrind_support: ?bool = null,
115each_lib_rpath: ?bool = null,87each_lib_rpath: ?bool = null,
116/// On ELF targets, this will emit a link section called ".note.gnu.build-id"88/// On ELF targets, this will emit a link section called ".note.gnu.build-id"
117/// which can be used to coordinate a stripped binary with its debug symbols.89/// which can be used to coordinate a stripped binary with its debug symbols.
...@@ -177,15 +149,9 @@ headerpad_max_install_names: bool = false,...@@ -177,15 +149,9 @@ headerpad_max_install_names: bool = false,
177/// (Darwin) Remove dylibs that are unreachable by the entry point or exported symbols.149/// (Darwin) Remove dylibs that are unreachable by the entry point or exported symbols.
178dead_strip_dylibs: bool = false,150dead_strip_dylibs: bool = false,
179151
180/// Position Independent Code
181force_pic: ?bool = null,
182
183/// Position Independent Executable152/// Position Independent Executable
184pie: ?bool = null,153pie: ?bool = null,
185154
186red_zone: ?bool = null,
187
188omit_frame_pointer: ?bool = null,
189dll_export_fns: ?bool = null,155dll_export_fns: ?bool = null,
190156
191subsystem: ?std.Target.SubSystem = null,157subsystem: ?std.Target.SubSystem = null,
...@@ -226,90 +192,16 @@ generated_h: ?*GeneratedFile,...@@ -226,90 +192,16 @@ generated_h: ?*GeneratedFile,
226/// Defaults to `std.math.maxInt(u16)`192/// Defaults to `std.math.maxInt(u16)`
227error_limit: ?u32 = null,193error_limit: ?u32 = null,
228194
195/// Computed during make().
196is_linking_libc: bool = false,
197/// Computed during make().
198is_linking_libcpp: bool = false,
199
229pub const ExpectedCompileErrors = union(enum) {200pub const ExpectedCompileErrors = union(enum) {
230 contains: []const u8,201 contains: []const u8,
231 exact: []const []const u8,202 exact: []const []const u8,
232};203};
233204
234pub const CSourceFiles = struct {
235 dependency: ?*std.Build.Dependency,
236 /// If `dependency` is not null relative to it,
237 /// else relative to the build root.
238 files: []const []const u8,
239 flags: []const []const u8,
240};
241
242pub const CSourceFile = struct {
243 file: LazyPath,
244 flags: []const []const u8,
245
246 pub fn dupe(self: CSourceFile, b: *std.Build) CSourceFile {
247 return .{
248 .file = self.file.dupe(b),
249 .flags = b.dupeStrings(self.flags),
250 };
251 }
252};
253
254pub const RcSourceFile = struct {
255 file: LazyPath,
256 /// Any option that rc.exe accepts will work here, with the exception of:
257 /// - `/fo`: The output filename is set by the build system
258 /// - `/p`: Only running the preprocessor is not supported in this context
259 /// - `/:no-preprocess` (non-standard option): Not supported in this context
260 /// - Any MUI-related option
261 /// https://learn.microsoft.com/en-us/windows/win32/menurc/using-rc-the-rc-command-line-
262 ///
263 /// Implicitly defined options:
264 /// /x (ignore the INCLUDE environment variable)
265 /// /D_DEBUG or /DNDEBUG depending on the optimization mode
266 flags: []const []const u8 = &.{},
267
268 pub fn dupe(self: RcSourceFile, b: *std.Build) RcSourceFile {
269 return .{
270 .file = self.file.dupe(b),
271 .flags = b.dupeStrings(self.flags),
272 };
273 }
274};
275
276pub const LinkObject = union(enum) {
277 static_path: LazyPath,
278 other_step: *Compile,
279 system_lib: SystemLib,
280 assembly_file: LazyPath,
281 c_source_file: *CSourceFile,
282 c_source_files: *CSourceFiles,
283 win32_resource_file: *RcSourceFile,
284};
285
286pub const SystemLib = struct {
287 name: []const u8,
288 needed: bool,
289 weak: bool,
290 use_pkg_config: UsePkgConfig,
291 preferred_link_mode: std.builtin.LinkMode,
292 search_strategy: SystemLib.SearchStrategy,
293
294 pub const UsePkgConfig = enum {
295 /// Don't use pkg-config, just pass -lfoo where foo is name.
296 no,
297 /// Try to get information on how to link the library from pkg-config.
298 /// If that fails, fall back to passing -lfoo where foo is name.
299 yes,
300 /// Try to get information on how to link the library from pkg-config.
301 /// If that fails, error out.
302 force,
303 };
304
305 pub const SearchStrategy = enum { paths_first, mode_first, no_fallback };
306};
307
308const FrameworkLinkInfo = struct {
309 needed: bool = false,
310 weak: bool = false,
311};
312
313const Entry = union(enum) {205const Entry = union(enum) {
314 /// Let the compiler decide whether to make an entry point and what to name206 /// Let the compiler decide whether to make an entry point and what to name
315 /// it.207 /// it.
...@@ -322,42 +214,24 @@ const Entry = union(enum) {...@@ -322,42 +214,24 @@ const Entry = union(enum) {
322 symbol_name: []const u8,214 symbol_name: []const u8,
323};215};
324216
325pub const IncludeDir = union(enum) {
326 path: LazyPath,
327 path_system: LazyPath,
328 path_after: LazyPath,
329 framework_path: LazyPath,
330 framework_path_system: LazyPath,
331 other_step: *Compile,
332 config_header_step: *Step.ConfigHeader,
333};
334
335pub const Options = struct {217pub const Options = struct {
336 name: []const u8,218 name: []const u8,
337 root_source_file: ?LazyPath = null,219 root_module: Module.CreateOptions,
338 target: CrossTarget,
339 optimize: std.builtin.OptimizeMode,
340 kind: Kind,220 kind: Kind,
341 linkage: ?Linkage = null,221 linkage: ?Linkage = null,
342 version: ?std.SemanticVersion = null,222 version: ?std.SemanticVersion = null,
343 max_rss: usize = 0,223 max_rss: usize = 0,
344 filter: ?[]const u8 = null,224 filter: ?[]const u8 = null,
345 test_runner: ?[]const u8 = null,225 test_runner: ?[]const u8 = null,
346 link_libc: ?bool = null,
347 single_threaded: ?bool = null,
348 use_llvm: ?bool = null,226 use_llvm: ?bool = null,
349 use_lld: ?bool = null,227 use_lld: ?bool = null,
350 zig_lib_dir: ?LazyPath = null,228 zig_lib_dir: ?LazyPath = null,
351 main_mod_path: ?LazyPath = null,
352 /// Embed a `.manifest` file in the compilation if the object format supports it.229 /// Embed a `.manifest` file in the compilation if the object format supports it.
353 /// https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-files-reference230 /// https://learn.microsoft.com/en-us/windows/win32/sbscs/manifest-files-reference
354 /// Manifest files must have the extension `.manifest`.231 /// Manifest files must have the extension `.manifest`.
355 /// Can be set regardless of target. The `.manifest` file will be ignored232 /// Can be set regardless of target. The `.manifest` file will be ignored
356 /// if the target object format does not support embedded manifests.233 /// if the target object format does not support embedded manifests.
357 win32_manifest: ?LazyPath = null,234 win32_manifest: ?LazyPath = null,
358
359 /// deprecated; use `main_mod_path`.
360 main_pkg_path: ?LazyPath = null,
361};235};
362236
363pub const BuildId = union(enum) {237pub const BuildId = union(enum) {
...@@ -447,7 +321,6 @@ pub const Linkage = enum { dynamic, static };...@@ -447,7 +321,6 @@ pub const Linkage = enum { dynamic, static };
447321
448pub fn create(owner: *std.Build, options: Options) *Compile {322pub fn create(owner: *std.Build, options: Options) *Compile {
449 const name = owner.dupe(options.name);323 const name = owner.dupe(options.name);
450 const root_src: ?LazyPath = if (options.root_source_file) |rsrc| rsrc.dupe(owner) else null;
451 if (mem.indexOf(u8, name, "/") != null or mem.indexOf(u8, name, "\\") != null) {324 if (mem.indexOf(u8, name, "/") != null or mem.indexOf(u8, name, "\\") != null) {
452 panic("invalid name: '{s}'. It looks like a file path, but it is supposed to be the library or application name.", .{name});325 panic("invalid name: '{s}'. It looks like a file path, but it is supposed to be the library or application name.", .{name});
453 }326 }
...@@ -466,11 +339,12 @@ pub fn create(owner: *std.Build, options: Options) *Compile {...@@ -466,11 +339,12 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
466 .@"test" => "zig test",339 .@"test" => "zig test",
467 },340 },
468 name_adjusted,341 name_adjusted,
469 @tagName(options.optimize),342 @tagName(options.root_module.optimize),
470 options.target.zigTriple(owner.allocator) catch @panic("OOM"),343 options.root_module.target.zigTriple(owner.allocator) catch @panic("OOM"),
471 });344 });
472345
473 const target_info = NativeTargetInfo.detect(options.target) catch @panic("unhandled error");346 const target_info = NativeTargetInfo.detect(options.root_module.target) catch
347 @panic("unhandled error");
474348
475 const out_filename = std.zig.binNameAlloc(owner.allocator, .{349 const out_filename = std.zig.binNameAlloc(owner.allocator, .{
476 .root_name = name,350 .root_name = name,
...@@ -489,17 +363,12 @@ pub fn create(owner: *std.Build, options: Options) *Compile {...@@ -489,17 +363,12 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
489363
490 const self = owner.allocator.create(Compile) catch @panic("OOM");364 const self = owner.allocator.create(Compile) catch @panic("OOM");
491 self.* = .{365 self.* = .{
492 .strip = null,366 .root_module = Module.init(owner, options.root_module, self),
493 .unwind_tables = null,
494 .verbose_link = false,367 .verbose_link = false,
495 .verbose_cc = false,368 .verbose_cc = false,
496 .optimize = options.optimize,
497 .target = options.target,
498 .linkage = options.linkage,369 .linkage = options.linkage,
499 .kind = options.kind,370 .kind = options.kind,
500 .root_src = root_src,
501 .name = name,371 .name = name,
502 .frameworks = StringHashMap(FrameworkLinkInfo).init(owner.allocator),
503 .step = Step.init(.{372 .step = Step.init(.{
504 .id = base_id,373 .id = base_id,
505 .name = step_name,374 .name = step_name,
...@@ -512,23 +381,12 @@ pub fn create(owner: *std.Build, options: Options) *Compile {...@@ -512,23 +381,12 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
512 .out_lib_filename = undefined,381 .out_lib_filename = undefined,
513 .major_only_filename = null,382 .major_only_filename = null,
514 .name_only_filename = null,383 .name_only_filename = null,
515 .modules = std.StringArrayHashMap(*Module).init(owner.allocator),
516 .include_dirs = ArrayList(IncludeDir).init(owner.allocator),
517 .link_objects = ArrayList(LinkObject).init(owner.allocator),
518 .c_macros = ArrayList([]const u8).init(owner.allocator),
519 .lib_paths = ArrayList(LazyPath).init(owner.allocator),
520 .rpaths = ArrayList(LazyPath).init(owner.allocator),
521 .installed_headers = ArrayList(*Step).init(owner.allocator),384 .installed_headers = ArrayList(*Step).init(owner.allocator),
522 .c_std = std.Build.CStd.C99,
523 .zig_lib_dir = null,385 .zig_lib_dir = null,
524 .main_mod_path = null,
525 .exec_cmd_args = null,386 .exec_cmd_args = null,
526 .filter = options.filter,387 .filter = options.filter,
527 .test_runner = options.test_runner,388 .test_runner = options.test_runner,
528 .test_server_mode = options.test_runner == null,389 .test_server_mode = options.test_runner == null,
529 .disable_stack_probing = false,
530 .disable_sanitize_c = false,
531 .sanitize_thread = false,
532 .rdynamic = false,390 .rdynamic = false,
533 .installed_path = null,391 .installed_path = null,
534 .force_undefined_symbols = StringHashMap(void).init(owner.allocator),392 .force_undefined_symbols = StringHashMap(void).init(owner.allocator),
...@@ -543,11 +401,6 @@ pub fn create(owner: *std.Build, options: Options) *Compile {...@@ -543,11 +401,6 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
543 .generated_llvm_ir = null,401 .generated_llvm_ir = null,
544 .generated_h = null,402 .generated_h = null,
545403
546 .target_info = target_info,
547
548 .is_linking_libc = options.link_libc orelse false,
549 .is_linking_libcpp = false,
550 .single_threaded = options.single_threaded,
551 .use_llvm = options.use_llvm,404 .use_llvm = options.use_llvm,
552 .use_lld = options.use_lld,405 .use_lld = options.use_lld,
553 };406 };
...@@ -557,14 +410,9 @@ pub fn create(owner: *std.Build, options: Options) *Compile {...@@ -557,14 +410,9 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
557 lp.addStepDependencies(&self.step);410 lp.addStepDependencies(&self.step);
558 }411 }
559412
560 if (options.main_mod_path orelse options.main_pkg_path) |lp| {
561 self.main_mod_path = lp.dupe(self.step.owner);
562 lp.addStepDependencies(&self.step);
563 }
564
565 // Only the PE/COFF format has a Resource Table which is where the manifest413 // Only the PE/COFF format has a Resource Table which is where the manifest
566 // gets embedded, so for any other target the manifest file is just ignored.414 // gets embedded, so for any other target the manifest file is just ignored.
567 if (self.target.getObjectFormat() == .coff) {415 if (target_info.target.ofmt == .coff) {
568 if (options.win32_manifest) |lp| {416 if (options.win32_manifest) |lp| {
569 self.win32_manifest = lp.dupe(self.step.owner);417 self.win32_manifest = lp.dupe(self.step.owner);
570 lp.addStepDependencies(&self.step);418 lp.addStepDependencies(&self.step);
...@@ -600,8 +448,6 @@ pub fn create(owner: *std.Build, options: Options) *Compile {...@@ -600,8 +448,6 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
600 }448 }
601 }449 }
602450
603 if (root_src) |rs| rs.addStepDependencies(&self.step);
604
605 return self;451 return self;
606}452}
607453
...@@ -738,19 +584,30 @@ pub fn linkFrameworkWeak(self: *Compile, framework_name: []const u8) void {...@@ -738,19 +584,30 @@ pub fn linkFrameworkWeak(self: *Compile, framework_name: []const u8) void {
738}584}
739585
740/// Returns whether the library, executable, or object depends on a particular system library.586/// Returns whether the library, executable, or object depends on a particular system library.
741pub fn dependsOnSystemLibrary(self: Compile, name: []const u8) bool {587pub fn dependsOnSystemLibrary(self: *const Compile, name: []const u8) bool {
742 if (isLibCLibrary(name)) {588 var is_linking_libc = false;
743 return self.is_linking_libc;589 var is_linking_libcpp = false;
590
591 var it = self.root_module.iterateDependencies(self);
592 while (it.next()) |module| {
593 for (module.link_objects.items) |link_object| {
594 switch (link_object) {
595 .system_lib => |lib| if (mem.eql(u8, lib.name, name)) return true,
596 else => continue,
597 }
598 }
599 is_linking_libc = is_linking_libc or module.link_libcpp == true;
600 is_linking_libcpp = is_linking_libcpp or module.link_libcpp == true;
744 }601 }
745 if (isLibCppLibrary(name)) {602
746 return self.is_linking_libcpp;603 if (self.root_module.target_info.target.is_libc_lib_name(name)) {
604 return is_linking_libc;
747 }605 }
748 for (self.link_objects.items) |link_object| {606
749 switch (link_object) {607 if (self.root_module.target_info.target.is_libcpp_lib_name(name)) {
750 .system_lib => |lib| if (mem.eql(u8, lib.name, name)) return true,608 return is_linking_libcpp;
751 else => continue,
752 }
753 }609 }
610
754 return false;611 return false;
755}612}
756613
...@@ -759,11 +616,11 @@ pub fn linkLibrary(self: *Compile, lib: *Compile) void {...@@ -759,11 +616,11 @@ pub fn linkLibrary(self: *Compile, lib: *Compile) void {
759 self.linkLibraryOrObject(lib);616 self.linkLibraryOrObject(lib);
760}617}
761618
762pub fn isDynamicLibrary(self: *Compile) bool {619pub fn isDynamicLibrary(self: *const Compile) bool {
763 return self.kind == .lib and self.linkage == Linkage.dynamic;620 return self.kind == .lib and self.linkage == Linkage.dynamic;
764}621}
765622
766pub fn isStaticLibrary(self: *Compile) bool {623pub fn isStaticLibrary(self: *const Compile) bool {
767 return self.kind == .lib and self.linkage != Linkage.dynamic;624 return self.kind == .lib and self.linkage != Linkage.dynamic;
768}625}
769626
...@@ -777,15 +634,15 @@ pub fn producesPdbFile(self: *Compile) bool {...@@ -777,15 +634,15 @@ pub fn producesPdbFile(self: *Compile) bool {
777}634}
778635
779pub fn producesImplib(self: *Compile) bool {636pub fn producesImplib(self: *Compile) bool {
780 return self.isDynamicLibrary() and self.target.isWindows();637 return self.isDynamicLibrary() and self.root_module.target_info.target.os.tag == .windows;
781}638}
782639
783pub fn linkLibC(self: *Compile) void {640pub fn linkLibC(self: *Compile) void {
784 self.is_linking_libc = true;641 self.root_module.link_libc = true;
785}642}
786643
787pub fn linkLibCpp(self: *Compile) void {644pub fn linkLibCpp(self: *Compile) void {
788 self.is_linking_libcpp = true;645 self.root_module.link_libcpp = true;
789}646}
790647
791/// If the value is omitted, it is set to 1.648/// If the value is omitted, it is set to 1.
...@@ -802,31 +659,6 @@ pub fn defineCMacroRaw(self: *Compile, name_and_value: []const u8) void {...@@ -802,31 +659,6 @@ pub fn defineCMacroRaw(self: *Compile, name_and_value: []const u8) void {
802 self.c_macros.append(b.dupe(name_and_value)) catch @panic("OOM");659 self.c_macros.append(b.dupe(name_and_value)) catch @panic("OOM");
803}660}
804661
805/// deprecated: use linkSystemLibrary2
806pub fn linkSystemLibraryName(self: *Compile, name: []const u8) void {
807 return linkSystemLibrary2(self, name, .{ .use_pkg_config = .no });
808}
809
810/// deprecated: use linkSystemLibrary2
811pub fn linkSystemLibraryNeededName(self: *Compile, name: []const u8) void {
812 return linkSystemLibrary2(self, name, .{ .needed = true, .use_pkg_config = .no });
813}
814
815/// deprecated: use linkSystemLibrary2
816pub fn linkSystemLibraryWeakName(self: *Compile, name: []const u8) void {
817 return linkSystemLibrary2(self, name, .{ .weak = true, .use_pkg_config = .no });
818}
819
820/// deprecated: use linkSystemLibrary2
821pub fn linkSystemLibraryPkgConfigOnly(self: *Compile, lib_name: []const u8) void {
822 return linkSystemLibrary2(self, lib_name, .{ .use_pkg_config = .force });
823}
824
825/// deprecated: use linkSystemLibrary2
826pub fn linkSystemLibraryNeededPkgConfigOnly(self: *Compile, lib_name: []const u8) void {
827 return linkSystemLibrary2(self, lib_name, .{ .needed = true, .use_pkg_config = .force });
828}
829
830/// Run pkg-config for the given library name and parse the output, returning the arguments662/// Run pkg-config for the given library name and parse the output, returning the arguments
831/// that should be passed to zig to link the given library.663/// that should be passed to zig to link the given library.
832fn runPkgConfig(self: *Compile, lib_name: []const u8) ![]const []const u8 {664fn runPkgConfig(self: *Compile, lib_name: []const u8) ![]const []const u8 {
...@@ -924,98 +756,31 @@ fn runPkgConfig(self: *Compile, lib_name: []const u8) ![]const []const u8 {...@@ -924,98 +756,31 @@ fn runPkgConfig(self: *Compile, lib_name: []const u8) ![]const []const u8 {
924}756}
925757
926pub fn linkSystemLibrary(self: *Compile, name: []const u8) void {758pub fn linkSystemLibrary(self: *Compile, name: []const u8) void {
927 self.linkSystemLibrary2(name, .{});759 return self.root_module.linkSystemLibrary(name, .{});
928}
929
930/// deprecated: use linkSystemLibrary2
931pub fn linkSystemLibraryNeeded(self: *Compile, name: []const u8) void {
932 return linkSystemLibrary2(self, name, .{ .needed = true });
933}760}
934761
935/// deprecated: use linkSystemLibrary2
936pub fn linkSystemLibraryWeak(self: *Compile, name: []const u8) void {
937 return linkSystemLibrary2(self, name, .{ .weak = true });
938}
939
940pub const LinkSystemLibraryOptions = struct {
941 needed: bool = false,
942 weak: bool = false,
943 use_pkg_config: SystemLib.UsePkgConfig = .yes,
944 preferred_link_mode: std.builtin.LinkMode = .Dynamic,
945 search_strategy: SystemLib.SearchStrategy = .paths_first,
946};
947
948pub fn linkSystemLibrary2(762pub fn linkSystemLibrary2(
949 self: *Compile,763 self: *Compile,
950 name: []const u8,764 name: []const u8,
951 options: LinkSystemLibraryOptions,765 options: Module.LinkSystemLibraryOptions,
952) void {766) void {
953 const b = self.step.owner;767 return self.root_module.linkSystemLibrary(name, options);
954 if (isLibCLibrary(name)) {
955 self.linkLibC();
956 return;
957 }
958 if (isLibCppLibrary(name)) {
959 self.linkLibCpp();
960 return;
961 }
962
963 self.link_objects.append(.{
964 .system_lib = .{
965 .name = b.dupe(name),
966 .needed = options.needed,
967 .weak = options.weak,
968 .use_pkg_config = options.use_pkg_config,
969 .preferred_link_mode = options.preferred_link_mode,
970 .search_strategy = options.search_strategy,
971 },
972 }) catch @panic("OOM");
973}768}
974769
975pub const AddCSourceFilesOptions = struct {
976 /// When provided, `files` are relative to `dependency` rather than the package that owns the `Compile` step.
977 dependency: ?*std.Build.Dependency = null,
978 files: []const []const u8,
979 flags: []const []const u8 = &.{},
980};
981
982/// Handy when you have many C/C++ source files and want them all to have the same flags.770/// Handy when you have many C/C++ source files and want them all to have the same flags.
983pub fn addCSourceFiles(self: *Compile, options: AddCSourceFilesOptions) void {771pub fn addCSourceFiles(self: *Compile, options: Module.AddCSourceFilesOptions) void {
984 const b = self.step.owner;772 self.root_module.addCSourceFiles(options);
985 const c_source_files = b.allocator.create(CSourceFiles) catch @panic("OOM");
986
987 const files_copy = b.dupeStrings(options.files);
988 const flags_copy = b.dupeStrings(options.flags);
989
990 c_source_files.* = .{
991 .dependency = options.dependency,
992 .files = files_copy,
993 .flags = flags_copy,
994 };
995 self.link_objects.append(.{ .c_source_files = c_source_files }) catch @panic("OOM");
996}773}
997774
998pub fn addCSourceFile(self: *Compile, source: CSourceFile) void {775pub fn addCSourceFile(self: *Compile, source: Module.CSourceFile) void {
999 const b = self.step.owner;776 self.root_module.addCSourceFile(source);
1000 const c_source_file = b.allocator.create(CSourceFile) catch @panic("OOM");
1001 c_source_file.* = source.dupe(b);
1002 self.link_objects.append(.{ .c_source_file = c_source_file }) catch @panic("OOM");
1003 source.file.addStepDependencies(&self.step);
1004}777}
1005778
1006/// Resource files must have the extension `.rc`.779/// Resource files must have the extension `.rc`.
1007/// Can be called regardless of target. The .rc file will be ignored780/// Can be called regardless of target. The .rc file will be ignored
1008/// if the target object format does not support embedded resources.781/// if the target object format does not support embedded resources.
1009pub fn addWin32ResourceFile(self: *Compile, source: RcSourceFile) void {782pub fn addWin32ResourceFile(self: *Compile, source: Module.RcSourceFile) void {
1010 // Only the PE/COFF format has a Resource Table, so for any other target783 self.root_module.addWin32ResourceFile(source);
1011 // the resource file is just ignored.
1012 if (self.target.getObjectFormat() != .coff) return;
1013
1014 const b = self.step.owner;
1015 const rc_source_file = b.allocator.create(RcSourceFile) catch @panic("OOM");
1016 rc_source_file.* = source.dupe(b);
1017 self.link_objects.append(.{ .win32_resource_file = rc_source_file }) catch @panic("OOM");
1018 source.file.addStepDependencies(&self.step);
1019}784}
1020785
1021pub fn setVerboseLink(self: *Compile, value: bool) void {786pub fn setVerboseLink(self: *Compile, value: bool) void {
...@@ -1112,16 +877,11 @@ pub fn getEmittedLlvmBc(self: *Compile) LazyPath {...@@ -1112,16 +877,11 @@ pub fn getEmittedLlvmBc(self: *Compile) LazyPath {
1112}877}
1113878
1114pub fn addAssemblyFile(self: *Compile, source: LazyPath) void {879pub fn addAssemblyFile(self: *Compile, source: LazyPath) void {
1115 const b = self.step.owner;880 self.root_module.addAssemblyFile(source);
1116 const source_duped = source.dupe(b);
1117 self.link_objects.append(.{ .assembly_file = source_duped }) catch @panic("OOM");
1118 source_duped.addStepDependencies(&self.step);
1119}881}
1120882
1121pub fn addObjectFile(self: *Compile, source: LazyPath) void {883pub fn addObjectFile(self: *Compile, source: LazyPath) void {
1122 const b = self.step.owner;884 self.root_module.addObjectFile(source);
1123 self.link_objects.append(.{ .static_path = source.dupe(b) }) catch @panic("OOM");
1124 source.addStepDependencies(&self.step);
1125}885}
1126886
1127pub fn addObject(self: *Compile, obj: *Compile) void {887pub fn addObject(self: *Compile, obj: *Compile) void {
...@@ -1131,19 +891,19 @@ pub fn addObject(self: *Compile, obj: *Compile) void {...@@ -1131,19 +891,19 @@ pub fn addObject(self: *Compile, obj: *Compile) void {
1131891
1132pub fn addAfterIncludePath(self: *Compile, path: LazyPath) void {892pub fn addAfterIncludePath(self: *Compile, path: LazyPath) void {
1133 const b = self.step.owner;893 const b = self.step.owner;
1134 self.include_dirs.append(IncludeDir{ .path_after = path.dupe(b) }) catch @panic("OOM");894 self.include_dirs.append(.{ .path_after = path.dupe(b) }) catch @panic("OOM");
1135 path.addStepDependencies(&self.step);895 path.addStepDependencies(&self.step);
1136}896}
1137897
1138pub fn addSystemIncludePath(self: *Compile, path: LazyPath) void {898pub fn addSystemIncludePath(self: *Compile, path: LazyPath) void {
1139 const b = self.step.owner;899 const b = self.step.owner;
1140 self.include_dirs.append(IncludeDir{ .path_system = path.dupe(b) }) catch @panic("OOM");900 self.include_dirs.append(.{ .path_system = path.dupe(b) }) catch @panic("OOM");
1141 path.addStepDependencies(&self.step);901 path.addStepDependencies(&self.step);
1142}902}
1143903
1144pub fn addIncludePath(self: *Compile, path: LazyPath) void {904pub fn addIncludePath(self: *Compile, path: LazyPath) void {
1145 const b = self.step.owner;905 const b = self.step.owner;
1146 self.include_dirs.append(IncludeDir{ .path = path.dupe(b) }) catch @panic("OOM");906 self.include_dirs.append(.{ .path = path.dupe(b) }) catch @panic("OOM");
1147 path.addStepDependencies(&self.step);907 path.addStepDependencies(&self.step);
1148}908}
1149909
...@@ -1166,48 +926,16 @@ pub fn addRPath(self: *Compile, directory_source: LazyPath) void {...@@ -1166,48 +926,16 @@ pub fn addRPath(self: *Compile, directory_source: LazyPath) void {
1166926
1167pub fn addSystemFrameworkPath(self: *Compile, directory_source: LazyPath) void {927pub fn addSystemFrameworkPath(self: *Compile, directory_source: LazyPath) void {
1168 const b = self.step.owner;928 const b = self.step.owner;
1169 self.include_dirs.append(IncludeDir{ .framework_path_system = directory_source.dupe(b) }) catch @panic("OOM");929 self.include_dirs.append(.{ .framework_path_system = directory_source.dupe(b) }) catch @panic("OOM");
1170 directory_source.addStepDependencies(&self.step);930 directory_source.addStepDependencies(&self.step);
1171}931}
1172932
1173pub fn addFrameworkPath(self: *Compile, directory_source: LazyPath) void {933pub fn addFrameworkPath(self: *Compile, directory_source: LazyPath) void {
1174 const b = self.step.owner;934 const b = self.step.owner;
1175 self.include_dirs.append(IncludeDir{ .framework_path = directory_source.dupe(b) }) catch @panic("OOM");935 self.include_dirs.append(.{ .framework_path = directory_source.dupe(b) }) catch @panic("OOM");
1176 directory_source.addStepDependencies(&self.step);936 directory_source.addStepDependencies(&self.step);
1177}937}
1178938
1179/// Adds a module to be used with `@import` and exposing it in the current
1180/// package's module table using `name`.
1181pub fn addModule(cs: *Compile, name: []const u8, module: *Module) void {
1182 const b = cs.step.owner;
1183 cs.modules.put(b.dupe(name), module) catch @panic("OOM");
1184
1185 var done = std.AutoHashMap(*Module, void).init(b.allocator);
1186 defer done.deinit();
1187 cs.addRecursiveBuildDeps(module, &done) catch @panic("OOM");
1188}
1189
1190/// Adds a module to be used with `@import` without exposing it in the current
1191/// package's module table.
1192pub fn addAnonymousModule(cs: *Compile, name: []const u8, options: std.Build.CreateModuleOptions) void {
1193 const b = cs.step.owner;
1194 const module = b.createModule(options);
1195 return addModule(cs, name, module);
1196}
1197
1198pub fn addOptions(cs: *Compile, module_name: []const u8, options: *Step.Options) void {
1199 addModule(cs, module_name, options.createModule());
1200}
1201
1202fn addRecursiveBuildDeps(cs: *Compile, module: *Module, done: *std.AutoHashMap(*Module, void)) !void {
1203 if (done.contains(module)) return;
1204 try done.put(module, {});
1205 module.source_file.addStepDependencies(&cs.step);
1206 for (module.dependencies.values()) |dep| {
1207 try cs.addRecursiveBuildDeps(dep, done);
1208 }
1209}
1210
1211/// If Vcpkg was found on the system, it will be added to include and lib939/// If Vcpkg was found on the system, it will be added to include and lib
1212/// paths for the specified target.940/// paths for the specified target.
1213pub fn addVcpkgPaths(self: *Compile, linkage: Compile.Linkage) !void {941pub fn addVcpkgPaths(self: *Compile, linkage: Compile.Linkage) !void {
...@@ -1236,7 +964,7 @@ pub fn addVcpkgPaths(self: *Compile, linkage: Compile.Linkage) !void {...@@ -1236,7 +964,7 @@ pub fn addVcpkgPaths(self: *Compile, linkage: Compile.Linkage) !void {
1236964
1237 const include_path = b.pathJoin(&.{ root, "installed", triplet, "include" });965 const include_path = b.pathJoin(&.{ root, "installed", triplet, "include" });
1238 errdefer allocator.free(include_path);966 errdefer allocator.free(include_path);
1239 try self.include_dirs.append(IncludeDir{ .path = .{ .path = include_path } });967 try self.include_dirs.append(.{ .path = .{ .path = include_path } });
1240968
1241 const lib_path = b.pathJoin(&.{ root, "installed", triplet, "lib" });969 const lib_path = b.pathJoin(&.{ root, "installed", triplet, "lib" });
1242 try self.lib_paths.append(.{ .path = lib_path });970 try self.lib_paths.append(.{ .path = lib_path });
...@@ -1270,87 +998,53 @@ fn linkLibraryOrObject(self: *Compile, other: *Compile) void {...@@ -1270,87 +998,53 @@ fn linkLibraryOrObject(self: *Compile, other: *Compile) void {
1270 }998 }
1271}999}
12721000
1273fn appendModuleArgs(1001fn appendModuleArgs(cs: *Compile, zig_args: *ArrayList([]const u8)) !void {
1274 cs: *Compile,
1275 zig_args: *ArrayList([]const u8),
1276) error{OutOfMemory}!void {
1277 const b = cs.step.owner;1002 const b = cs.step.owner;
1278 // First, traverse the whole dependency graph and give every module a unique name, ideally one1003 // First, traverse the whole dependency graph and give every module a
1279 // named after what it's called somewhere in the graph. It will help here to have both a mapping1004 // unique name, ideally one named after what it's called somewhere in the
1280 // from module to name and a set of all the currently-used names.1005 // graph. It will help here to have both a mapping from module to name and
1281 var mod_names = std.AutoHashMap(*Module, []const u8).init(b.allocator);1006 // a set of all the currently-used names.
1007 var mod_names: std.AutoArrayHashMapUnmanaged(*Module, []const u8) = .{};
1282 var names = std.StringHashMap(void).init(b.allocator);1008 var names = std.StringHashMap(void).init(b.allocator);
12831009
1284 var to_name = std.ArrayList(struct {
1285 name: []const u8,
1286 mod: *Module,
1287 }).init(b.allocator);
1288 {1010 {
1289 var it = cs.modules.iterator();1011 var it = cs.root_module.iterateDependencies(null);
1290 while (it.next()) |kv| {1012 _ = it.next(); // Skip over the root module.
1013 while (it.next()) |item| {
1291 // While we're traversing the root dependencies, let's make sure that no module names1014 // While we're traversing the root dependencies, let's make sure that no module names
1292 // have colons in them, since the CLI forbids it. We handle this for transitive1015 // have colons in them, since the CLI forbids it. We handle this for transitive
1293 // dependencies further down.1016 // dependencies further down.
1294 if (std.mem.indexOfScalar(u8, kv.key_ptr.*, ':') != null) {1017 if (std.mem.indexOfScalar(u8, item.name, ':') != null) {
1295 @panic("Module names cannot contain colons");1018 return cs.step.fail("module '{s}' contains a colon", .{item.name});
1296 }1019 }
1297 try to_name.append(.{
1298 .name = kv.key_ptr.*,
1299 .mod = kv.value_ptr.*,
1300 });
1301 }
1302 }
1303
1304 while (to_name.popOrNull()) |dep| {
1305 if (mod_names.contains(dep.mod)) continue;
13061020
1307 // We'll use this buffer to store the name we decide on1021 var name = item.name;
1308 var buf = try b.allocator.alloc(u8, dep.name.len + 32);1022 var n: usize = 0;
1309 // First, try just the exposed dependency name1023 while (names.contains(name)) {
1310 @memcpy(buf[0..dep.name.len], dep.name);1024 name = b.fmt("{s}{d}", .{ item.name, n });
1311 var name = buf[0..dep.name.len];1025 n += 1;
1312 var n: usize = 0;
1313 while (names.contains(name)) {
1314 // If that failed, append an incrementing number to the end
1315 name = std.fmt.bufPrint(buf, "{s}{}", .{ dep.name, n }) catch unreachable;
1316 n += 1;
1317 }
1318
1319 try mod_names.put(dep.mod, name);
1320 try names.put(name, {});
1321
1322 var it = dep.mod.dependencies.iterator();
1323 while (it.next()) |kv| {
1324 // Same colon-in-name check as above, but for transitive dependencies.
1325 if (std.mem.indexOfScalar(u8, kv.key_ptr.*, ':') != null) {
1326 @panic("Module names cannot contain colons");
1327 }1026 }
1328 try to_name.append(.{1027
1329 .name = kv.key_ptr.*,1028 try mod_names.put(b.allocator, item.module, name);
1330 .mod = kv.value_ptr.*,1029 try names.put(name, {});
1331 });
1332 }1030 }
1333 }1031 }
13341032
1335 // Since the module names given to the CLI are based off of the exposed names, we already know1033 // Since the module names given to the CLI are based off of the exposed
1336 // that none of the CLI names have colons in them, so there's no need to check that explicitly.1034 // names, we already know that none of the CLI names have colons in them,
1035 // so there's no need to check that explicitly.
13371036
1338 // Every module in the graph is now named; output their definitions1037 // Every module in the graph is now named; output their definitions
1339 {1038 for (mod_names.keys(), mod_names.values()) |mod, name| {
1340 var it = mod_names.iterator();1039 const root_src = mod.root_source_file orelse continue;
1341 while (it.next()) |kv| {1040 const deps_str = try constructDepString(b.allocator, mod_names, mod.import_table);
1342 const mod = kv.key_ptr.*;1041 const src = root_src.getPath2(mod.owner, &cs.step);
1343 const name = kv.value_ptr.*;1042 try zig_args.append("--mod");
13441043 try zig_args.append(b.fmt("{s}:{s}:{s}", .{ name, deps_str, src }));
1345 const deps_str = try constructDepString(b.allocator, mod_names, mod.dependencies);
1346 const src = mod.source_file.getPath(mod.builder);
1347 try zig_args.append("--mod");
1348 try zig_args.append(try std.fmt.allocPrint(b.allocator, "{s}:{s}:{s}", .{ name, deps_str, src }));
1349 }
1350 }1044 }
13511045
1352 // Lastly, output the root dependencies1046 // Lastly, output the root dependencies
1353 const deps_str = try constructDepString(b.allocator, mod_names, cs.modules);1047 const deps_str = try constructDepString(b.allocator, mod_names, cs.root_module.import_table);
1354 if (deps_str.len > 0) {1048 if (deps_str.len > 0) {
1355 try zig_args.append("--deps");1049 try zig_args.append("--deps");
1356 try zig_args.append(deps_str);1050 try zig_args.append(deps_str);
...@@ -1359,7 +1053,7 @@ fn appendModuleArgs(...@@ -1359,7 +1053,7 @@ fn appendModuleArgs(
13591053
1360fn constructDepString(1054fn constructDepString(
1361 allocator: std.mem.Allocator,1055 allocator: std.mem.Allocator,
1362 mod_names: std.AutoHashMap(*Module, []const u8),1056 mod_names: std.AutoArrayHashMapUnmanaged(*Module, []const u8),
1363 deps: std.StringArrayHashMap(*Module),1057 deps: std.StringArrayHashMap(*Module),
1364) ![]const u8 {1058) ![]const u8 {
1365 var deps_str = std.ArrayList(u8).init(allocator);1059 var deps_str = std.ArrayList(u8).init(allocator);
...@@ -1408,10 +1102,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -1408,10 +1102,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
1408 const b = step.owner;1102 const b = step.owner;
1409 const self = @fieldParentPtr(Compile, "step", step);1103 const self = @fieldParentPtr(Compile, "step", step);
14101104
1411 if (self.root_src == null and self.link_objects.items.len == 0) {
1412 return step.fail("the linker needs one or more objects to link", .{});
1413 }
1414
1415 var zig_args = ArrayList([]const u8).init(b.allocator);1105 var zig_args = ArrayList([]const u8).init(b.allocator);
1416 defer zig_args.deinit();1106 defer zig_args.deinit();
14171107
...@@ -1432,7 +1122,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -1432,7 +1122,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
1432 try addFlag(&zig_args, "llvm", self.use_llvm);1122 try addFlag(&zig_args, "llvm", self.use_llvm);
1433 try addFlag(&zig_args, "lld", self.use_lld);1123 try addFlag(&zig_args, "lld", self.use_lld);
14341124
1435 if (self.target.ofmt) |ofmt| {1125 if (self.root_module.target.ofmt) |ofmt| {
1436 try zig_args.append(try std.fmt.allocPrint(b.allocator, "-ofmt={s}", .{@tagName(ofmt)}));1126 try zig_args.append(try std.fmt.allocPrint(b.allocator, "-ofmt={s}", .{@tagName(ofmt)}));
1437 }1127 }
14381128
...@@ -1458,204 +1148,248 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -1458,204 +1148,248 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
1458 try zig_args.append(try std.fmt.allocPrint(b.allocator, "{}", .{stack_size}));1148 try zig_args.append(try std.fmt.allocPrint(b.allocator, "{}", .{stack_size}));
1459 }1149 }
14601150
1461 if (self.root_src) |root_src| try zig_args.append(root_src.getPath(b));1151 {
1152 var seen_system_libs: std.StringHashMapUnmanaged(void) = .{};
1153 var frameworks: std.StringArrayHashMapUnmanaged(Module.FrameworkLinkInfo) = .{};
1154
1155 var prev_has_cflags = false;
1156 var prev_has_rcflags = false;
1157 var prev_search_strategy: Module.SystemLib.SearchStrategy = .paths_first;
1158 var prev_preferred_link_mode: std.builtin.LinkMode = .Dynamic;
1159 // Track the number of positional arguments so that a nice error can be
1160 // emitted if there is nothing to link.
1161 var total_linker_objects: usize = 0;
1162
1163 if (self.root_module.root_source_file) |lp| {
1164 try zig_args.append(lp.getPath(b));
1165 total_linker_objects += 1;
1166 }
14621167
1463 // We will add link objects from transitive dependencies, but we want to keep1168 try self.root_module.appendZigProcessFlags(&zig_args, step);
1464 // all link objects in the same order provided.
1465 // This array is used to keep self.link_objects immutable.
1466 var transitive_deps: TransitiveDeps = .{
1467 .link_objects = ArrayList(LinkObject).init(b.allocator),
1468 .seen_system_libs = StringHashMap(void).init(b.allocator),
1469 .seen_steps = std.AutoHashMap(*const Step, void).init(b.allocator),
1470 .is_linking_libcpp = self.is_linking_libcpp,
1471 .is_linking_libc = self.is_linking_libc,
1472 .frameworks = &self.frameworks,
1473 };
14741169
1475 try transitive_deps.seen_steps.put(&self.step, {});1170 var it = self.root_module.iterateDependencies(self);
1476 try transitive_deps.add(self.link_objects.items);1171 while (it.next()) |key| {
14771172 const module = key.module;
1478 var prev_has_cflags = false;1173 const compile = key.compile.?;
1479 var prev_has_rcflags = false;1174 const dyn = compile.isDynamicLibrary();
1480 var prev_search_strategy: SystemLib.SearchStrategy = .paths_first;
1481 var prev_preferred_link_mode: std.builtin.LinkMode = .Dynamic;
1482
1483 for (transitive_deps.link_objects.items) |link_object| {
1484 switch (link_object) {
1485 .static_path => |static_path| try zig_args.append(static_path.getPath(b)),
1486
1487 .other_step => |other| switch (other.kind) {
1488 .exe => @panic("Cannot link with an executable build artifact"),
1489 .@"test" => @panic("Cannot link with a test"),
1490 .obj => {
1491 try zig_args.append(other.getEmittedBin().getPath(b));
1492 },
1493 .lib => l: {
1494 if (self.isStaticLibrary() and other.isStaticLibrary()) {
1495 // Avoid putting a static library inside a static library.
1496 break :l;
1497 }
14981175
1499 // For DLLs, we gotta link against the implib. For1176 // Inherit dependency on libc and libc++.
1500 // everything else, we directly link against the library file.1177 if (module.link_libc == true) self.is_linking_libc = true;
1501 const full_path_lib = if (other.producesImplib())1178 if (module.link_libcpp == true) self.is_linking_libcpp = true;
1502 other.getGeneratedFilePath("generated_implib", &self.step)
1503 else
1504 other.getGeneratedFilePath("generated_bin", &self.step);
1505 try zig_args.append(full_path_lib);
1506
1507 if (other.linkage == Linkage.dynamic and !self.target.isWindows()) {
1508 if (fs.path.dirname(full_path_lib)) |dirname| {
1509 try zig_args.append("-rpath");
1510 try zig_args.append(dirname);
1511 }
1512 }
1513 },
1514 },
15151179
1516 .system_lib => |system_lib| {1180 // Inherit dependencies on darwin frameworks.
1517 if ((system_lib.search_strategy != prev_search_strategy or1181 if (!dyn) {
1518 system_lib.preferred_link_mode != prev_preferred_link_mode) and1182 for (module.frameworks.keys(), module.frameworks.values()) |name, info| {
1519 self.linkage != .static)1183 try frameworks.put(b.allocator, name, info);
1520 {
1521 switch (system_lib.search_strategy) {
1522 .no_fallback => switch (system_lib.preferred_link_mode) {
1523 .Dynamic => try zig_args.append("-search_dylibs_only"),
1524 .Static => try zig_args.append("-search_static_only"),
1525 },
1526 .paths_first => switch (system_lib.preferred_link_mode) {
1527 .Dynamic => try zig_args.append("-search_paths_first"),
1528 .Static => try zig_args.append("-search_paths_first_static"),
1529 },
1530 .mode_first => switch (system_lib.preferred_link_mode) {
1531 .Dynamic => try zig_args.append("-search_dylibs_first"),
1532 .Static => try zig_args.append("-search_static_first"),
1533 },
1534 }
1535 prev_search_strategy = system_lib.search_strategy;
1536 prev_preferred_link_mode = system_lib.preferred_link_mode;
1537 }1184 }
1185 }
15381186
1539 const prefix: []const u8 = prefix: {1187 // Inherit dependencies on system libraries and static libraries.
1540 if (system_lib.needed) break :prefix "-needed-l";1188 total_linker_objects += module.link_objects.items.len;
1541 if (system_lib.weak) break :prefix "-weak-l";1189 for (module.link_objects.items) |link_object| {
1542 break :prefix "-l";1190 switch (link_object) {
1543 };1191 .static_path => |static_path| try zig_args.append(static_path.getPath(b)),
1544 switch (system_lib.use_pkg_config) {1192 .system_lib => |system_lib| {
1545 .no => try zig_args.append(b.fmt("{s}{s}", .{ prefix, system_lib.name })),1193 if ((try seen_system_libs.fetchPut(b.allocator, system_lib.name, {})) != null)
1546 .yes, .force => {1194 continue;
1547 if (self.runPkgConfig(system_lib.name)) |args| {1195
1548 try zig_args.appendSlice(args);1196 if (dyn)
1549 } else |err| switch (err) {1197 continue;
1550 error.PkgConfigInvalidOutput,1198
1551 error.PkgConfigCrashed,1199 if ((system_lib.search_strategy != prev_search_strategy or
1552 error.PkgConfigFailed,1200 system_lib.preferred_link_mode != prev_preferred_link_mode) and
1553 error.PkgConfigNotInstalled,1201 self.linkage != .static)
1554 error.PackageNotFound,1202 {
1555 => switch (system_lib.use_pkg_config) {1203 switch (system_lib.search_strategy) {
1556 .yes => {1204 .no_fallback => switch (system_lib.preferred_link_mode) {
1557 // pkg-config failed, so fall back to linking the library1205 .Dynamic => try zig_args.append("-search_dylibs_only"),
1558 // by name directly.1206 .Static => try zig_args.append("-search_static_only"),
1559 try zig_args.append(b.fmt("{s}{s}", .{1207 },
1560 prefix,1208 .paths_first => switch (system_lib.preferred_link_mode) {
1561 system_lib.name,1209 .Dynamic => try zig_args.append("-search_paths_first"),
1562 }));1210 .Static => try zig_args.append("-search_paths_first_static"),
1563 },1211 },
1564 .force => {1212 .mode_first => switch (system_lib.preferred_link_mode) {
1565 panic("pkg-config failed for library {s}", .{system_lib.name});1213 .Dynamic => try zig_args.append("-search_dylibs_first"),
1214 .Static => try zig_args.append("-search_static_first"),
1566 },1215 },
1567 .no => unreachable,1216 }
1217 prev_search_strategy = system_lib.search_strategy;
1218 prev_preferred_link_mode = system_lib.preferred_link_mode;
1219 }
1220
1221 const prefix: []const u8 = prefix: {
1222 if (system_lib.needed) break :prefix "-needed-l";
1223 if (system_lib.weak) break :prefix "-weak-l";
1224 break :prefix "-l";
1225 };
1226 switch (system_lib.use_pkg_config) {
1227 .no => try zig_args.append(b.fmt("{s}{s}", .{ prefix, system_lib.name })),
1228 .yes, .force => {
1229 if (self.runPkgConfig(system_lib.name)) |args| {
1230 try zig_args.appendSlice(args);
1231 } else |err| switch (err) {
1232 error.PkgConfigInvalidOutput,
1233 error.PkgConfigCrashed,
1234 error.PkgConfigFailed,
1235 error.PkgConfigNotInstalled,
1236 error.PackageNotFound,
1237 => switch (system_lib.use_pkg_config) {
1238 .yes => {
1239 // pkg-config failed, so fall back to linking the library
1240 // by name directly.
1241 try zig_args.append(b.fmt("{s}{s}", .{
1242 prefix,
1243 system_lib.name,
1244 }));
1245 },
1246 .force => {
1247 panic("pkg-config failed for library {s}", .{system_lib.name});
1248 },
1249 .no => unreachable,
1250 },
1251
1252 else => |e| return e,
1253 }
1254 },
1255 }
1256 },
1257 .other_step => |other| {
1258 const included_in_lib = (compile.kind == .lib and other.kind == .obj);
1259 if (dyn or included_in_lib)
1260 continue;
1261
1262 switch (other.kind) {
1263 .exe => return step.fail("cannot link with an executable build artifact", .{}),
1264 .@"test" => return step.fail("cannot link with a test", .{}),
1265 .obj => {
1266 try zig_args.append(other.getEmittedBin().getPath(b));
1267 },
1268 .lib => l: {
1269 if (self.isStaticLibrary() and other.isStaticLibrary()) {
1270 // Avoid putting a static library inside a static library.
1271 break :l;
1272 }
1273
1274 // For DLLs, we gotta link against the implib. For
1275 // everything else, we directly link against the library file.
1276 const full_path_lib = if (other.producesImplib())
1277 other.getGeneratedFilePath("generated_implib", &self.step)
1278 else
1279 other.getGeneratedFilePath("generated_bin", &self.step);
1280 try zig_args.append(full_path_lib);
1281
1282 if (other.linkage == Linkage.dynamic and
1283 self.root_module.target_info.target.os.tag != .windows)
1284 {
1285 if (fs.path.dirname(full_path_lib)) |dirname| {
1286 try zig_args.append("-rpath");
1287 try zig_args.append(dirname);
1288 }
1289 }
1568 },1290 },
1291 }
1292 },
1293 .assembly_file => |asm_file| {
1294 if (prev_has_cflags) {
1295 try zig_args.append("-cflags");
1296 try zig_args.append("--");
1297 prev_has_cflags = false;
1298 }
1299 try zig_args.append(asm_file.getPath(b));
1300 },
15691301
1570 else => |e| return e,1302 .c_source_file => |c_source_file| {
1303 if (c_source_file.flags.len == 0) {
1304 if (prev_has_cflags) {
1305 try zig_args.append("-cflags");
1306 try zig_args.append("--");
1307 prev_has_cflags = false;
1308 }
1309 } else {
1310 try zig_args.append("-cflags");
1311 for (c_source_file.flags) |arg| {
1312 try zig_args.append(arg);
1313 }
1314 try zig_args.append("--");
1315 prev_has_cflags = true;
1571 }1316 }
1317 try zig_args.append(c_source_file.file.getPath(b));
1572 },1318 },
1573 }
1574 },
15751319
1576 .assembly_file => |asm_file| {1320 .c_source_files => |c_source_files| {
1577 if (prev_has_cflags) {1321 if (c_source_files.flags.len == 0) {
1578 try zig_args.append("-cflags");1322 if (prev_has_cflags) {
1579 try zig_args.append("--");1323 try zig_args.append("-cflags");
1580 prev_has_cflags = false;1324 try zig_args.append("--");
1581 }1325 prev_has_cflags = false;
1582 try zig_args.append(asm_file.getPath(b));1326 }
1583 },1327 } else {
1328 try zig_args.append("-cflags");
1329 for (c_source_files.flags) |flag| {
1330 try zig_args.append(flag);
1331 }
1332 try zig_args.append("--");
1333 prev_has_cflags = true;
1334 }
1335 if (c_source_files.dependency) |dep| {
1336 for (c_source_files.files) |file| {
1337 try zig_args.append(dep.builder.pathFromRoot(file));
1338 }
1339 } else {
1340 for (c_source_files.files) |file| {
1341 try zig_args.append(b.pathFromRoot(file));
1342 }
1343 }
1344 },
15841345
1585 .c_source_file => |c_source_file| {1346 .win32_resource_file => |rc_source_file| {
1586 if (c_source_file.flags.len == 0) {1347 if (rc_source_file.flags.len == 0) {
1587 if (prev_has_cflags) {1348 if (prev_has_rcflags) {
1588 try zig_args.append("-cflags");1349 try zig_args.append("-rcflags");
1589 try zig_args.append("--");1350 try zig_args.append("--");
1590 prev_has_cflags = false;1351 prev_has_rcflags = false;
1591 }1352 }
1592 } else {1353 } else {
1593 try zig_args.append("-cflags");1354 try zig_args.append("-rcflags");
1594 for (c_source_file.flags) |arg| {1355 for (rc_source_file.flags) |arg| {
1595 try zig_args.append(arg);1356 try zig_args.append(arg);
1596 }1357 }
1597 try zig_args.append("--");1358 try zig_args.append("--");
1598 prev_has_cflags = true;1359 prev_has_rcflags = true;
1360 }
1361 try zig_args.append(rc_source_file.file.getPath(b));
1362 },
1599 }1363 }
1600 try zig_args.append(c_source_file.file.getPath(b));1364 }
1601 },1365 }
16021366
1603 .c_source_files => |c_source_files| {1367 if (total_linker_objects == 0) {
1604 if (c_source_files.flags.len == 0) {1368 return step.fail("the linker needs one or more objects to link", .{});
1605 if (prev_has_cflags) {1369 }
1606 try zig_args.append("-cflags");
1607 try zig_args.append("--");
1608 prev_has_cflags = false;
1609 }
1610 } else {
1611 try zig_args.append("-cflags");
1612 for (c_source_files.flags) |flag| {
1613 try zig_args.append(flag);
1614 }
1615 try zig_args.append("--");
1616 prev_has_cflags = true;
1617 }
1618 if (c_source_files.dependency) |dep| {
1619 for (c_source_files.files) |file| {
1620 try zig_args.append(dep.builder.pathFromRoot(file));
1621 }
1622 } else {
1623 for (c_source_files.files) |file| {
1624 try zig_args.append(b.pathFromRoot(file));
1625 }
1626 }
1627 },
16281370
1629 .win32_resource_file => |rc_source_file| {1371 for (frameworks.keys(), frameworks.values()) |name, info| {
1630 if (rc_source_file.flags.len == 0) {1372 if (info.needed) {
1631 if (prev_has_rcflags) {1373 try zig_args.append("-needed_framework");
1632 try zig_args.append("-rcflags");1374 } else if (info.weak) {
1633 try zig_args.append("--");1375 try zig_args.append("-weak_framework");
1634 prev_has_rcflags = false;1376 } else {
1635 }1377 try zig_args.append("-framework");
1636 } else {1378 }
1637 try zig_args.append("-rcflags");1379 try zig_args.append(name);
1638 for (rc_source_file.flags) |arg| {
1639 try zig_args.append(arg);
1640 }
1641 try zig_args.append("--");
1642 prev_has_rcflags = true;
1643 }
1644 try zig_args.append(rc_source_file.file.getPath(b));
1645 },
1646 }1380 }
1647 }
16481381
1649 if (self.win32_manifest) |manifest_file| {1382 if (self.is_linking_libcpp) {
1650 try zig_args.append(manifest_file.getPath(b));1383 try zig_args.append("-lc++");
1651 }1384 }
16521385
1653 if (transitive_deps.is_linking_libcpp) {1386 if (self.is_linking_libc) {
1654 try zig_args.append("-lc++");1387 try zig_args.append("-lc");
1388 }
1655 }1389 }
16561390
1657 if (transitive_deps.is_linking_libc) {1391 if (self.win32_manifest) |manifest_file| {
1658 try zig_args.append("-lc");1392 try zig_args.append(manifest_file.getPath(b));
1659 }1393 }
16601394
1661 if (self.image_base) |image_base| {1395 if (self.image_base) |image_base| {
...@@ -1702,17 +1436,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -1702,17 +1436,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
1702 if (self.generated_llvm_ir != null) try zig_args.append("-femit-llvm-ir");1436 if (self.generated_llvm_ir != null) try zig_args.append("-femit-llvm-ir");
1703 if (self.generated_h != null) try zig_args.append("-femit-h");1437 if (self.generated_h != null) try zig_args.append("-femit-h");
17041438
1705 try addFlag(&zig_args, "strip", self.strip);
1706 try addFlag(&zig_args, "formatted-panics", self.formatted_panics);
1707 try addFlag(&zig_args, "unwind-tables", self.unwind_tables);
1708
1709 if (self.dwarf_format) |dwarf_format| {
1710 try zig_args.append(switch (dwarf_format) {
1711 .@"32" => "-gdwarf32",
1712 .@"64" => "-gdwarf64",
1713 });
1714 }
1715
1716 switch (self.compress_debug_sections) {1439 switch (self.compress_debug_sections) {
1717 .none => {},1440 .none => {},
1718 .zlib => try zig_args.append("--compress-debug-sections=zlib"),1441 .zlib => try zig_args.append("--compress-debug-sections=zlib"),
...@@ -1769,11 +1492,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -1769,11 +1492,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
1769 try zig_args.append(libc_file);1492 try zig_args.append(libc_file);
1770 }1493 }
17711494
1772 switch (self.optimize) {
1773 .Debug => {}, // Skip since it's the default.
1774 else => try zig_args.append(b.fmt("-O{s}", .{@tagName(self.optimize)})),
1775 }
1776
1777 try zig_args.append("--cache-dir");1495 try zig_args.append("--cache-dir");
1778 try zig_args.append(b.cache_root.path orelse ".");1496 try zig_args.append(b.cache_root.path orelse ".");
17791497
...@@ -1793,11 +1511,11 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -1793,11 +1511,11 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
1793 try zig_args.append(b.fmt("{}", .{version}));1511 try zig_args.append(b.fmt("{}", .{version}));
1794 }1512 }
17951513
1796 if (self.target.isDarwin()) {1514 if (self.root_module.target_info.target.isDarwin()) {
1797 const install_name = self.install_name orelse b.fmt("@rpath/{s}{s}{s}", .{1515 const install_name = self.install_name orelse b.fmt("@rpath/{s}{s}{s}", .{
1798 self.target.libPrefix(),1516 self.root_module.target_info.target.libPrefix(),
1799 self.name,1517 self.name,
1800 self.target.dynamicLibSuffix(),1518 self.root_module.target_info.target.dynamicLibSuffix(),
1801 });1519 });
1802 try zig_args.append("-install_name");1520 try zig_args.append("-install_name");
1803 try zig_args.append(install_name);1521 try zig_args.append(install_name);
...@@ -1823,27 +1541,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -1823,27 +1541,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
1823 }1541 }
18241542
1825 try addFlag(&zig_args, "compiler-rt", self.bundle_compiler_rt);1543 try addFlag(&zig_args, "compiler-rt", self.bundle_compiler_rt);
1826 try addFlag(&zig_args, "single-threaded", self.single_threaded);
1827 if (self.disable_stack_probing) {
1828 try zig_args.append("-fno-stack-check");
1829 }
1830 try addFlag(&zig_args, "stack-protector", self.stack_protector);
1831 if (self.red_zone) |red_zone| {
1832 if (red_zone) {
1833 try zig_args.append("-mred-zone");
1834 } else {
1835 try zig_args.append("-mno-red-zone");
1836 }
1837 }
1838 try addFlag(&zig_args, "omit-frame-pointer", self.omit_frame_pointer);
1839 try addFlag(&zig_args, "dll-export-fns", self.dll_export_fns);1544 try addFlag(&zig_args, "dll-export-fns", self.dll_export_fns);
1840
1841 if (self.disable_sanitize_c) {
1842 try zig_args.append("-fno-sanitize-c");
1843 }
1844 if (self.sanitize_thread) {
1845 try zig_args.append("-fsanitize-thread");
1846 }
1847 if (self.rdynamic) {1545 if (self.rdynamic) {
1848 try zig_args.append("-rdynamic");1546 try zig_args.append("-rdynamic");
1849 }1547 }
...@@ -1875,29 +1573,9 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -1875,29 +1573,9 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
1875 try zig_args.append(b.fmt("--global-base={d}", .{global_base}));1573 try zig_args.append(b.fmt("--global-base={d}", .{global_base}));
1876 }1574 }
18771575
1878 if (self.code_model != .default) {
1879 try zig_args.append("-mcmodel");
1880 try zig_args.append(@tagName(self.code_model));
1881 }
1882 if (self.wasi_exec_model) |model| {1576 if (self.wasi_exec_model) |model| {
1883 try zig_args.append(b.fmt("-mexec-model={s}", .{@tagName(model)}));1577 try zig_args.append(b.fmt("-mexec-model={s}", .{@tagName(model)}));
1884 }1578 }
1885 for (self.export_symbol_names) |symbol_name| {
1886 try zig_args.append(b.fmt("--export={s}", .{symbol_name}));
1887 }
1888
1889 if (!self.target.isNative()) {
1890 try zig_args.appendSlice(&.{
1891 "-target", try self.target.zigTriple(b.allocator),
1892 "-mcpu", try std.Build.serializeCpu(b.allocator, self.target.getCpu()),
1893 });
1894
1895 if (self.target.dynamic_linker.get()) |dynamic_linker| {
1896 try zig_args.append("--dynamic-linker");
1897 try zig_args.append(dynamic_linker);
1898 }
1899 }
1900
1901 if (self.linker_script) |linker_script| {1579 if (self.linker_script) |linker_script| {
1902 try zig_args.append("--script");1580 try zig_args.append("--script");
1903 try zig_args.append(linker_script.getPath(b));1581 try zig_args.append(linker_script.getPath(b));
...@@ -1923,97 +1601,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -1923,97 +1601,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
19231601
1924 try self.appendModuleArgs(&zig_args);1602 try self.appendModuleArgs(&zig_args);
19251603
1926 for (self.include_dirs.items) |include_dir| {
1927 switch (include_dir) {
1928 .path => |include_path| {
1929 try zig_args.append("-I");
1930 try zig_args.append(include_path.getPath(b));
1931 },
1932 .path_system => |include_path| {
1933 try zig_args.append("-isystem");
1934 try zig_args.append(include_path.getPath(b));
1935 },
1936 .path_after => |include_path| {
1937 try zig_args.append("-idirafter");
1938 try zig_args.append(include_path.getPath(b));
1939 },
1940 .framework_path => |include_path| {
1941 try zig_args.append("-F");
1942 try zig_args.append(include_path.getPath2(b, step));
1943 },
1944 .framework_path_system => |include_path| {
1945 try zig_args.append("-iframework");
1946 try zig_args.append(include_path.getPath2(b, step));
1947 },
1948 .other_step => |other| {
1949 if (other.generated_h) |header| {
1950 try zig_args.append("-isystem");
1951 try zig_args.append(fs.path.dirname(header.path.?).?);
1952 }
1953 if (other.installed_headers.items.len > 0) {
1954 try zig_args.append("-I");
1955 try zig_args.append(b.pathJoin(&.{
1956 other.step.owner.install_prefix, "include",
1957 }));
1958 }
1959 },
1960 .config_header_step => |config_header| {
1961 const full_file_path = config_header.output_file.path.?;
1962 const header_dir_path = full_file_path[0 .. full_file_path.len - config_header.include_path.len];
1963 try zig_args.appendSlice(&.{ "-I", header_dir_path });
1964 },
1965 }
1966 }
1967
1968 for (self.c_macros.items) |c_macro| {
1969 try zig_args.append("-D");
1970 try zig_args.append(c_macro);
1971 }
1972
1973 try zig_args.ensureUnusedCapacity(2 * self.lib_paths.items.len);
1974 for (self.lib_paths.items) |lib_path| {
1975 zig_args.appendAssumeCapacity("-L");
1976 zig_args.appendAssumeCapacity(lib_path.getPath2(b, step));
1977 }
1978
1979 try zig_args.ensureUnusedCapacity(2 * self.rpaths.items.len);
1980 for (self.rpaths.items) |rpath| {
1981 zig_args.appendAssumeCapacity("-rpath");
1982
1983 if (self.target_info.target.isDarwin()) switch (rpath) {
1984 .path, .cwd_relative => |path| {
1985 // On Darwin, we should not try to expand special runtime paths such as
1986 // * @executable_path
1987 // * @loader_path
1988 if (mem.startsWith(u8, path, "@executable_path") or
1989 mem.startsWith(u8, path, "@loader_path"))
1990 {
1991 zig_args.appendAssumeCapacity(path);
1992 continue;
1993 }
1994 },
1995 .generated, .dependency => {},
1996 };
1997
1998 zig_args.appendAssumeCapacity(rpath.getPath2(b, step));
1999 }
2000
2001 {
2002 var it = self.frameworks.iterator();
2003 while (it.next()) |entry| {
2004 const name = entry.key_ptr.*;
2005 const info = entry.value_ptr.*;
2006 if (info.needed) {
2007 try zig_args.append("-needed_framework");
2008 } else if (info.weak) {
2009 try zig_args.append("-weak_framework");
2010 } else {
2011 try zig_args.append("-framework");
2012 }
2013 try zig_args.append(name);
2014 }
2015 }
2016
2017 if (b.sysroot) |sysroot| {1604 if (b.sysroot) |sysroot| {
2018 try zig_args.appendSlice(&[_][]const u8{ "--sysroot", sysroot });1605 try zig_args.appendSlice(&[_][]const u8{ "--sysroot", sysroot });
2019 }1606 }
...@@ -2058,7 +1645,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -2058,7 +1645,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
2058 try zig_args.append(@tagName(self.rc_includes));1645 try zig_args.append(@tagName(self.rc_includes));
2059 }1646 }
20601647
2061 try addFlag(&zig_args, "valgrind", self.valgrind_support);
2062 try addFlag(&zig_args, "each-lib-rpath", self.each_lib_rpath);1648 try addFlag(&zig_args, "each-lib-rpath", self.each_lib_rpath);
20631649
2064 if (self.build_id) |build_id| {1650 if (self.build_id) |build_id| {
...@@ -2075,12 +1661,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -2075,12 +1661,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
2075 try zig_args.append(dir.getPath(b));1661 try zig_args.append(dir.getPath(b));
2076 }1662 }
20771663
2078 if (self.main_mod_path) |dir| {
2079 try zig_args.append("--main-mod-path");
2080 try zig_args.append(dir.getPath(b));
2081 }
2082
2083 try addFlag(&zig_args, "PIC", self.force_pic);
2084 try addFlag(&zig_args, "PIE", self.pie);1664 try addFlag(&zig_args, "PIE", self.pie);
2085 try addFlag(&zig_args, "lto", self.want_lto);1665 try addFlag(&zig_args, "lto", self.want_lto);
20861666
...@@ -2223,7 +1803,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -2223,7 +1803,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
2223 }1803 }
22241804
2225 if (self.kind == .lib and self.linkage != null and self.linkage.? == .dynamic and1805 if (self.kind == .lib and self.linkage != null and self.linkage.? == .dynamic and
2226 self.version != null and self.target.wantSharedLibSymLinks())1806 self.version != null and self.root_module.target.wantSharedLibSymLinks())
2227 {1807 {
2228 try doAtomicSymLinks(1808 try doAtomicSymLinks(
2229 step,1809 step,
...@@ -2234,24 +1814,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -2234,24 +1814,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
2234 }1814 }
2235}1815}
22361816
2237fn isLibCLibrary(name: []const u8) bool {
2238 const libc_libraries = [_][]const u8{ "c", "m", "dl", "rt", "pthread" };
2239 for (libc_libraries) |libc_lib_name| {
2240 if (mem.eql(u8, name, libc_lib_name))
2241 return true;
2242 }
2243 return false;
2244}
2245
2246fn isLibCppLibrary(name: []const u8) bool {
2247 const libcpp_libraries = [_][]const u8{ "c++", "stdc++" };
2248 for (libcpp_libraries) |libcpp_lib_name| {
2249 if (mem.eql(u8, name, libcpp_lib_name))
2250 return true;
2251 }
2252 return false;
2253}
2254
2255/// Returned slice must be freed by the caller.1817/// Returned slice must be freed by the caller.
2256fn findVcpkgRoot(allocator: Allocator) !?[]const u8 {1818fn findVcpkgRoot(allocator: Allocator) !?[]const u8 {
2257 const appdata_path = try fs.getAppDataDir(allocator, "vcpkg");1819 const appdata_path = try fs.getAppDataDir(allocator, "vcpkg");
...@@ -2345,67 +1907,6 @@ fn addFlag(args: *ArrayList([]const u8), comptime name: []const u8, opt: ?bool)...@@ -2345,67 +1907,6 @@ fn addFlag(args: *ArrayList([]const u8), comptime name: []const u8, opt: ?bool)
2345 }1907 }
2346}1908}
23471909
2348const TransitiveDeps = struct {
2349 link_objects: ArrayList(LinkObject),
2350 seen_system_libs: StringHashMap(void),
2351 seen_steps: std.AutoHashMap(*const Step, void),
2352 is_linking_libcpp: bool,
2353 is_linking_libc: bool,
2354 frameworks: *StringHashMap(FrameworkLinkInfo),
2355
2356 fn add(td: *TransitiveDeps, link_objects: []const LinkObject) !void {
2357 try td.link_objects.ensureUnusedCapacity(link_objects.len);
2358
2359 for (link_objects) |link_object| {
2360 try td.link_objects.append(link_object);
2361 switch (link_object) {
2362 .other_step => |other| try addInner(td, other, other.isDynamicLibrary()),
2363 else => {},
2364 }
2365 }
2366 }
2367
2368 fn addInner(td: *TransitiveDeps, other: *Compile, dyn: bool) !void {
2369 // Inherit dependency on libc and libc++
2370 td.is_linking_libcpp = td.is_linking_libcpp or other.is_linking_libcpp;
2371 td.is_linking_libc = td.is_linking_libc or other.is_linking_libc;
2372
2373 // Inherit dependencies on darwin frameworks
2374 if (!dyn) {
2375 var it = other.frameworks.iterator();
2376 while (it.next()) |framework| {
2377 try td.frameworks.put(framework.key_ptr.*, framework.value_ptr.*);
2378 }
2379 }
2380
2381 // Inherit dependencies on system libraries and static libraries.
2382 for (other.link_objects.items) |other_link_object| {
2383 switch (other_link_object) {
2384 .system_lib => |system_lib| {
2385 if ((try td.seen_system_libs.fetchPut(system_lib.name, {})) != null)
2386 continue;
2387
2388 if (dyn)
2389 continue;
2390
2391 try td.link_objects.append(other_link_object);
2392 },
2393 .other_step => |inner_other| {
2394 if ((try td.seen_steps.fetchPut(&inner_other.step, {})) != null)
2395 continue;
2396
2397 const included_in_lib = (other.kind == .lib and inner_other.kind == .obj);
2398 if (!dyn and !included_in_lib)
2399 try td.link_objects.append(other_link_object);
2400
2401 try addInner(td, inner_other, dyn or inner_other.isDynamicLibrary());
2402 },
2403 else => continue,
2404 }
2405 }
2406 }
2407};
2408
2409fn checkCompileErrors(self: *Compile) !void {1910fn checkCompileErrors(self: *Compile) !void {
2410 // Clear this field so that it does not get printed by the build runner.1911 // Clear this field so that it does not get printed by the build runner.
2411 const actual_eb = self.step.result_error_bundle;1912 const actual_eb = self.step.result_error_bundle;
lib/std/Build/Step/Run.zig+18-18
...@@ -488,7 +488,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -488,7 +488,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
488 man.hash.addBytes(file_path);488 man.hash.addBytes(file_path);
489 },489 },
490 .artifact => |artifact| {490 .artifact => |artifact| {
491 if (artifact.target.isWindows()) {491 if (artifact.root_module.target_info.target.os.tag == .windows) {
492 // On Windows we don't have rpaths so we have to add .dll search paths to PATH492 // On Windows we don't have rpaths so we have to add .dll search paths to PATH
493 self.addPathForDynLibs(artifact);493 self.addPathForDynLibs(artifact);
494 }494 }
...@@ -682,8 +682,9 @@ fn runCommand(...@@ -682,8 +682,9 @@ fn runCommand(
682 else => break :interpret,682 else => break :interpret,
683 }683 }
684684
685 const need_cross_glibc = exe.target.isGnuLibC() and exe.is_linking_libc;685 const need_cross_glibc = exe.root_module.target_info.target.isGnuLibC() and
686 switch (b.host.getExternalExecutor(&exe.target_info, .{686 exe.is_linking_libc;
687 switch (b.host.getExternalExecutor(&exe.root_module.target_info, .{
687 .qemu_fixes_dl = need_cross_glibc and b.glibc_runtimes_dir != null,688 .qemu_fixes_dl = need_cross_glibc and b.glibc_runtimes_dir != null,
688 .link_libc = exe.is_linking_libc,689 .link_libc = exe.is_linking_libc,
689 })) {690 })) {
...@@ -714,9 +715,9 @@ fn runCommand(...@@ -714,9 +715,9 @@ fn runCommand(
714 // needs the directory to be called "i686" rather than715 // needs the directory to be called "i686" rather than
715 // "x86" which is why we do it manually here.716 // "x86" which is why we do it manually here.
716 const fmt_str = "{s}" ++ fs.path.sep_str ++ "{s}-{s}-{s}";717 const fmt_str = "{s}" ++ fs.path.sep_str ++ "{s}-{s}-{s}";
717 const cpu_arch = exe.target.getCpuArch();718 const cpu_arch = exe.root_module.target_info.target.cpu.arch;
718 const os_tag = exe.target.getOsTag();719 const os_tag = exe.root_module.target_info.target.os.tag;
719 const abi = exe.target.getAbi();720 const abi = exe.root_module.target_info.target.abi;
720 const cpu_arch_name: []const u8 = if (cpu_arch == .x86)721 const cpu_arch_name: []const u8 = if (cpu_arch == .x86)
721 "i686"722 "i686"
722 else723 else
...@@ -769,7 +770,7 @@ fn runCommand(...@@ -769,7 +770,7 @@ fn runCommand(
769 if (allow_skip) return error.MakeSkipped;770 if (allow_skip) return error.MakeSkipped;
770771
771 const host_name = try b.host.target.zigTriple(b.allocator);772 const host_name = try b.host.target.zigTriple(b.allocator);
772 const foreign_name = try exe.target.zigTriple(b.allocator);773 const foreign_name = try exe.root_module.target_info.target.zigTriple(b.allocator);
773774
774 return step.fail("the host system ({s}) is unable to execute binaries from the target ({s})", .{775 return step.fail("the host system ({s}) is unable to execute binaries from the target ({s})", .{
775 host_name, foreign_name,776 host_name, foreign_name,
...@@ -777,7 +778,7 @@ fn runCommand(...@@ -777,7 +778,7 @@ fn runCommand(
777 },778 },
778 }779 }
779780
780 if (exe.target.isWindows()) {781 if (exe.root_module.target_info.target.os.tag == .windows) {
781 // On Windows we don't have rpaths so we have to add .dll search paths to PATH782 // On Windows we don't have rpaths so we have to add .dll search paths to PATH
782 self.addPathForDynLibs(exe);783 self.addPathForDynLibs(exe);
783 }784 }
...@@ -1295,15 +1296,14 @@ fn evalGeneric(self: *Run, child: *std.process.Child) !StdIoResult {...@@ -1295,15 +1296,14 @@ fn evalGeneric(self: *Run, child: *std.process.Child) !StdIoResult {
12951296
1296fn addPathForDynLibs(self: *Run, artifact: *Step.Compile) void {1297fn addPathForDynLibs(self: *Run, artifact: *Step.Compile) void {
1297 const b = self.step.owner;1298 const b = self.step.owner;
1298 for (artifact.link_objects.items) |link_object| {1299 var it = artifact.root_module.iterateDependencies(artifact);
1299 switch (link_object) {1300 while (it.next()) |item| {
1300 .other_step => |other| {1301 const other = item.compile.?;
1301 if (other.target.isWindows() and other.isDynamicLibrary()) {1302 if (item.module == &other.root_module) {
1302 addPathDir(self, fs.path.dirname(other.getEmittedBin().getPath(b)).?);1303 if (item.module.target_info.target.os.tag == .windows and other.isDynamicLibrary()) {
1303 addPathForDynLibs(self, other);1304 addPathDir(self, fs.path.dirname(other.getEmittedBin().getPath(b)).?);
1304 }1305 addPathForDynLibs(self, other);
1305 },1306 }
1306 else => {},
1307 }1307 }
1308 }1308 }
1309}1309}
...@@ -1321,7 +1321,7 @@ fn failForeign(...@@ -1321,7 +1321,7 @@ fn failForeign(
13211321
1322 const b = self.step.owner;1322 const b = self.step.owner;
1323 const host_name = try b.host.target.zigTriple(b.allocator);1323 const host_name = try b.host.target.zigTriple(b.allocator);
1324 const foreign_name = try exe.target.zigTriple(b.allocator);1324 const foreign_name = try exe.root_module.target_info.target.zigTriple(b.allocator);
13251325
1326 return self.step.fail(1326 return self.step.fail(
1327 \\unable to spawn foreign binary '{s}' ({s}) on host system ({s})1327 \\unable to spawn foreign binary '{s}' ({s}) on host system ({s})