diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2023-12-02 21:51:34 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2024-01-01 17:51:18 -0700 |
| commit | 142471fcc46070326526e3976f0150fe734df0b6 (patch) | |
| tree | 67d4dec7968cf6d6765cd3bc66524721cf0554d2 /lib/std/Build/Module.zig | |
| parent | 579f572cf203eda11da7e4e919fdfc12e15f03e2 (diff) | |
| download | zig-142471fcc46070326526e3976f0150fe734df0b6.tar.gz zig-142471fcc46070326526e3976f0150fe734df0b6.zip | |
zig build system: change target, compilation, and module APIs
Introduce the concept of "target query" and "resolved target". A target
query is what the user specifies, with some things left to default. A
resolved target has the default things discovered and populated.
In the future, std.zig.CrossTarget will be rename to std.Target.Query.
Introduces `std.Build.resolveTargetQuery` to get from one to the other.
The concept of `main_mod_path` is gone, no longer supported. You have to
put the root source file at the module root now.
* remove deprecated API
* update build.zig for the breaking API changes in this branch
* move std.Build.Step.Compile.BuildId to std.zig.BuildId
* add more options to std.Build.ExecutableOptions, std.Build.ObjectOptions,
std.Build.SharedLibraryOptions, std.Build.StaticLibraryOptions, and
std.Build.TestOptions.
* remove `std.Build.constructCMacro`. There is no use for this API.
* deprecate `std.Build.Step.Compile.defineCMacro`. Instead,
`std.Build.Module.addCMacro` is provided.
- remove `std.Build.Step.Compile.defineCMacroRaw`.
* deprecate `std.Build.Step.Compile.linkFrameworkNeeded`
- use `std.Build.Module.linkFramework`
* deprecate `std.Build.Step.Compile.linkFrameworkWeak`
- use `std.Build.Module.linkFramework`
* move more logic into `std.Build.Module`
* allow `target` and `optimize` to be `null` when creating a Module.
Along with other fields, those unspecified options will be inherited
from parent `Module` when inserted into an import table.
* the `target` field of `addExecutable` is now required. pass `b.host`
to get the host target.
Diffstat (limited to 'lib/std/Build/Module.zig')
| -rw-r--r-- | lib/std/Build/Module.zig | 347 |
1 files changed, 239 insertions, 108 deletions
diff --git a/lib/std/Build/Module.zig b/lib/std/Build/Module.zig index 31db0ad689..c672ae6c2e 100644 --- a/lib/std/Build/Module.zig +++ b/lib/std/Build/Module.zig @@ -3,27 +3,24 @@ owner: *std.Build, /// Tracks the set of steps that depend on this `Module`. This ensures that /// when making this `Module` depend on other `Module` objects and `Step` /// objects, respective `Step` dependencies can be added. -depending_steps: std.AutoArrayHashMapUnmanaged(*std.Build.Step.Compile, void), -/// This could either be a generated file, in which case the module -/// contains exactly one file, or it could be a path to the root source -/// file of directory of files which constitute the module. -/// If `null`, it means this module is made up of only `link_objects`. +depending_steps: std.AutoArrayHashMapUnmanaged(*Step.Compile, void), root_source_file: ?LazyPath, /// The modules that are mapped into this module's import table. -import_table: std.StringArrayHashMap(*Module), +/// Use `addImport` rather than modifying this field directly in order to +/// maintain step dependency edges. +import_table: std.StringArrayHashMapUnmanaged(*Module), -target: std.zig.CrossTarget, -target_info: NativeTargetInfo, -optimize: std.builtin.OptimizeMode, +target: ?std.Build.ResolvedTarget = null, +optimize: ?std.builtin.OptimizeMode = null, dwarf_format: ?std.dwarf.Format, -c_macros: std.ArrayList([]const u8), -include_dirs: std.ArrayList(IncludeDir), -lib_paths: std.ArrayList(LazyPath), -rpaths: std.ArrayList(LazyPath), -frameworks: std.StringArrayHashMapUnmanaged(FrameworkLinkInfo), +c_macros: std.ArrayListUnmanaged([]const u8), +include_dirs: std.ArrayListUnmanaged(IncludeDir), +lib_paths: std.ArrayListUnmanaged(LazyPath), +rpaths: std.ArrayListUnmanaged(RPath), +frameworks: std.StringArrayHashMapUnmanaged(LinkFrameworkOptions), c_std: std.Build.CStd, -link_objects: std.ArrayList(LinkObject), +link_objects: std.ArrayListUnmanaged(LinkObject), strip: ?bool, unwind_tables: ?bool, @@ -53,9 +50,14 @@ link_libcpp: ?bool, /// Symbols to be exported when compiling to WebAssembly. export_symbol_names: []const []const u8 = &.{}, +pub const RPath = union(enum) { + lazy_path: LazyPath, + special: []const u8, +}; + pub const LinkObject = union(enum) { static_path: LazyPath, - other_step: *std.Build.Step.Compile, + other_step: *Step.Compile, system_lib: SystemLib, assembly_file: LazyPath, c_source_file: *CSourceFile, @@ -133,21 +135,32 @@ pub const IncludeDir = union(enum) { path_after: LazyPath, framework_path: LazyPath, framework_path_system: LazyPath, - other_step: *std.Build.Step.Compile, - config_header_step: *std.Build.Step.ConfigHeader, + other_step: *Step.Compile, + config_header_step: *Step.ConfigHeader, }; -pub const FrameworkLinkInfo = struct { +pub const LinkFrameworkOptions = struct { needed: bool = false, weak: bool = false, }; +/// Unspecified options here will be inherited from parent `Module` when +/// inserted into an import table. pub const CreateOptions = struct { - target: std.zig.CrossTarget, - target_info: ?NativeTargetInfo = null, - optimize: std.builtin.OptimizeMode, + /// This could either be a generated file, in which case the module + /// contains exactly one file, or it could be a path to the root source + /// file of directory of files which constitute the module. + /// If `null`, it means this module is made up of only `link_objects`. root_source_file: ?LazyPath = null, - import_table: []const Import = &.{}, + + /// The table of other modules that this module can access via `@import`. + /// Imports are allowed to be cyclical, so this table can be added to after + /// the `Module` is created via `addImport`. + imports: []const Import = &.{}, + + target: ?std.Build.ResolvedTarget = null, + optimize: ?std.builtin.OptimizeMode = null, + link_libc: ?bool = null, link_libcpp: ?bool = null, single_threaded: ?bool = null, @@ -173,26 +186,26 @@ pub const Import = struct { module: *Module, }; -pub fn init(owner: *std.Build, options: CreateOptions, compile: ?*std.Build.Step.Compile) Module { - var m: Module = .{ +pub fn init(m: *Module, owner: *std.Build, options: CreateOptions, compile: ?*Step.Compile) void { + const allocator = owner.allocator; + + m.* = .{ .owner = owner, .depending_steps = .{}, .root_source_file = if (options.root_source_file) |lp| lp.dupe(owner) else null, - .import_table = std.StringArrayHashMap(*Module).init(owner.allocator), + .import_table = .{}, .target = options.target, - .target_info = options.target_info orelse - NativeTargetInfo.detect(options.target) catch @panic("unhandled error"), .optimize = options.optimize, .link_libc = options.link_libc, .link_libcpp = options.link_libcpp, .dwarf_format = options.dwarf_format, - .c_macros = std.ArrayList([]const u8).init(owner.allocator), - .include_dirs = std.ArrayList(IncludeDir).init(owner.allocator), - .lib_paths = std.ArrayList(LazyPath).init(owner.allocator), - .rpaths = std.ArrayList(LazyPath).init(owner.allocator), + .c_macros = .{}, + .include_dirs = .{}, + .lib_paths = .{}, + .rpaths = .{}, .frameworks = .{}, .c_std = options.c_std, - .link_objects = std.ArrayList(LinkObject).init(owner.allocator), + .link_objects = .{}, .strip = options.strip, .unwind_tables = options.unwind_tables, .single_threaded = options.single_threaded, @@ -208,31 +221,30 @@ pub fn init(owner: *std.Build, options: CreateOptions, compile: ?*std.Build.Step .export_symbol_names = &.{}, }; - if (compile) |c| { - m.depending_steps.put(owner.allocator, c, {}) catch @panic("OOM"); + m.import_table.ensureUnusedCapacity(allocator, options.imports.len) catch @panic("OOM"); + for (options.imports) |dep| { + m.import_table.putAssumeCapacity(dep.name, dep.module); } - m.import_table.ensureUnusedCapacity(options.import_table.len) catch @panic("OOM"); - for (options.import_table) |dep| { - m.import_table.putAssumeCapacity(dep.name, dep.module); + if (compile) |c| { + m.depending_steps.put(allocator, c, {}) catch @panic("OOM"); } + // This logic accesses `depending_steps` which was just modified above. var it = m.iterateDependencies(null); - while (it.next()) |item| addShallowDependencies(&m, item.module); - - return m; + while (it.next()) |item| addShallowDependencies(m, item.module); } pub fn create(owner: *std.Build, options: CreateOptions) *Module { const m = owner.allocator.create(Module) catch @panic("OOM"); - m.* = init(owner, options, null); + m.init(owner, options, null); return m; } /// Adds an existing module to be used with `@import`. pub fn addImport(m: *Module, name: []const u8, module: *Module) void { const b = m.owner; - m.import_table.put(b.dupe(name), module) catch @panic("OOM"); + m.import_table.put(b.allocator, b.dupe(name), module) catch @panic("OOM"); var it = module.iterateDependencies(null); while (it.next()) |item| addShallowDependencies(m, item.module); @@ -244,7 +256,10 @@ pub fn addImport(m: *Module, name: []const u8, module: *Module) void { fn addShallowDependencies(m: *Module, dependee: *Module) void { if (dependee.root_source_file) |lazy_path| addLazyPathDependencies(m, dependee, lazy_path); for (dependee.lib_paths.items) |lib_path| addLazyPathDependencies(m, dependee, lib_path); - for (dependee.rpaths.items) |rpath| addLazyPathDependencies(m, dependee, rpath); + for (dependee.rpaths.items) |rpath| switch (rpath) { + .lazy_path => |lp| addLazyPathDependencies(m, dependee, lp), + .special => {}, + }; for (dependee.link_objects.items) |link_object| switch (link_object) { .other_step => |compile| addStepDependencies(m, dependee, &compile.step), @@ -277,7 +292,7 @@ fn addLazyPathDependenciesOnly(m: *Module, lazy_path: LazyPath) void { } } -fn addStepDependencies(m: *Module, module: *Module, dependee: *std.Build.Step) void { +fn addStepDependencies(m: *Module, module: *Module, dependee: *Step) void { addStepDependenciesOnly(m, dependee); if (m != module) { for (m.depending_steps.keys()) |compile| { @@ -286,20 +301,19 @@ fn addStepDependencies(m: *Module, module: *Module, dependee: *std.Build.Step) v } } -fn addStepDependenciesOnly(m: *Module, dependee: *std.Build.Step) void { +fn addStepDependenciesOnly(m: *Module, dependee: *Step) void { for (m.depending_steps.keys()) |compile| { compile.step.dependOn(dependee); } } /// Creates a new module and adds it to be used with `@import`. -pub fn addAnonymousImport(m: *Module, name: []const u8, options: std.Build.CreateModuleOptions) void { - const b = m.step.owner; - const module = b.createModule(options); +pub fn addAnonymousImport(m: *Module, name: []const u8, options: CreateOptions) void { + const module = create(m.owner, options); return addImport(m, name, module); } -pub fn addOptions(m: *Module, module_name: []const u8, options: *std.Build.Step.Options) void { +pub fn addOptions(m: *Module, module_name: []const u8, options: *Step.Options) void { addImport(m, module_name, options.createModule()); } @@ -311,14 +325,14 @@ pub const DependencyIterator = struct { pub const Key = struct { /// The compilation that contains the `Module`. Note that a `Module` might be /// used by more than one compilation. - compile: ?*std.Build.Step.Compile, + compile: ?*Step.Compile, module: *Module, }; pub const Item = struct { /// The compilation that contains the `Module`. Note that a `Module` might be /// used by more than one compilation. - compile: ?*std.Build.Step.Compile, + compile: ?*Step.Compile, module: *Module, name: []const u8, }; @@ -368,7 +382,7 @@ pub const DependencyIterator = struct { pub fn iterateDependencies( m: *Module, - chase_steps: ?*std.Build.Step.Compile, + chase_steps: ?*Step.Compile, ) DependencyIterator { var it: DependencyIterator = .{ .allocator = m.owner.allocator, @@ -397,16 +411,18 @@ pub fn linkSystemLibrary( options: LinkSystemLibraryOptions, ) void { const b = m.owner; - if (m.target_info.target.is_libc_lib_name(name)) { + + const target = m.requireKnownTarget(); + if (target.is_libc_lib_name(name)) { m.link_libc = true; return; } - if (m.target_info.target.is_libcpp_lib_name(name)) { + if (target.is_libcpp_lib_name(name)) { m.link_libcpp = true; return; } - m.link_objects.append(.{ + m.link_objects.append(b.allocator, .{ .system_lib = .{ .name = b.dupe(name), .needed = options.needed, @@ -418,6 +434,11 @@ pub fn linkSystemLibrary( }) catch @panic("OOM"); } +pub fn linkFramework(m: *Module, name: []const u8, options: LinkFrameworkOptions) void { + const b = m.owner; + m.frameworks.put(b.allocator, b.dupe(name), options) catch @panic("OOM"); +} + pub const AddCSourceFilesOptions = struct { /// When provided, `files` are relative to `dependency` rather than the /// package that owns the `Compile` step. @@ -428,19 +449,23 @@ pub const AddCSourceFilesOptions = struct { /// Handy when you have many C/C++ source files and want them all to have the same flags. pub fn addCSourceFiles(m: *Module, options: AddCSourceFilesOptions) void { - const c_source_files = m.owner.allocator.create(CSourceFiles) catch @panic("OOM"); + const b = m.owner; + const allocator = b.allocator; + const c_source_files = allocator.create(CSourceFiles) catch @panic("OOM"); c_source_files.* = .{ .dependency = options.dependency, - .files = m.owner.dupeStrings(options.files), - .flags = m.owner.dupeStrings(options.flags), + .files = b.dupeStrings(options.files), + .flags = b.dupeStrings(options.flags), }; - m.link_objects.append(.{ .c_source_files = c_source_files }) catch @panic("OOM"); + m.link_objects.append(allocator, .{ .c_source_files = c_source_files }) catch @panic("OOM"); } pub fn addCSourceFile(m: *Module, source: CSourceFile) void { - const c_source_file = m.owner.allocator.create(CSourceFile) catch @panic("OOM"); - c_source_file.* = source.dupe(m.owner); - m.link_objects.append(.{ .c_source_file = c_source_file }) catch @panic("OOM"); + const b = m.owner; + const allocator = b.allocator; + const c_source_file = allocator.create(CSourceFile) catch @panic("OOM"); + c_source_file.* = source.dupe(b); + m.link_objects.append(allocator, .{ .c_source_file = c_source_file }) catch @panic("OOM"); addLazyPathDependenciesOnly(m, source.file); } @@ -448,30 +473,122 @@ pub fn addCSourceFile(m: *Module, source: CSourceFile) void { /// Can be called regardless of target. The .rc file will be ignored /// if the target object format does not support embedded resources. pub fn addWin32ResourceFile(m: *Module, source: RcSourceFile) void { + const b = m.owner; + const allocator = b.allocator; + const target = m.requireKnownTarget(); // Only the PE/COFF format has a Resource Table, so for any other target // the resource file is ignored. - if (m.target_info.target.ofmt != .coff) return; + if (target.ofmt != .coff) return; - const rc_source_file = m.owner.allocator.create(RcSourceFile) catch @panic("OOM"); - rc_source_file.* = source.dupe(m.owner); - m.link_objects.append(.{ .win32_resource_file = rc_source_file }) catch @panic("OOM"); + const rc_source_file = allocator.create(RcSourceFile) catch @panic("OOM"); + rc_source_file.* = source.dupe(b); + m.link_objects.append(allocator, .{ .win32_resource_file = rc_source_file }) catch @panic("OOM"); addLazyPathDependenciesOnly(m, source.file); } pub fn addAssemblyFile(m: *Module, source: LazyPath) void { - m.link_objects.append(.{ .assembly_file = source.dupe(m.owner) }) catch @panic("OOM"); + const b = m.owner; + m.link_objects.append(b.allocator, .{ .assembly_file = source.dupe(b) }) catch @panic("OOM"); addLazyPathDependenciesOnly(m, source); } -pub fn addObjectFile(m: *Module, source: LazyPath) void { - m.link_objects.append(.{ .static_path = source.dupe(m.owner) }) catch @panic("OOM"); - addLazyPathDependencies(m, source); +pub fn addObjectFile(m: *Module, object: LazyPath) void { + const b = m.owner; + m.link_objects.append(b.allocator, .{ .static_path = object.dupe(b) }) catch @panic("OOM"); + addLazyPathDependenciesOnly(m, object); +} + +pub fn addObject(m: *Module, object: *Step.Compile) void { + assert(object.kind == .obj); + m.linkLibraryOrObject(object); +} + +pub fn linkLibrary(m: *Module, library: *Step.Compile) void { + assert(library.kind == .lib); + m.linkLibraryOrObject(library); +} + +pub fn addAfterIncludePath(m: *Module, lazy_path: LazyPath) void { + const b = m.owner; + m.include_dirs.append(b.allocator, .{ .path_after = lazy_path.dupe(b) }) catch @panic("OOM"); + addLazyPathDependenciesOnly(m, lazy_path); +} + +pub fn addSystemIncludePath(m: *Module, lazy_path: LazyPath) void { + const b = m.owner; + m.include_dirs.append(b.allocator, .{ .path_system = lazy_path.dupe(b) }) catch @panic("OOM"); + addLazyPathDependenciesOnly(m, lazy_path); +} + +pub fn addIncludePath(m: *Module, lazy_path: LazyPath) void { + const b = m.owner; + m.include_dirs.append(b.allocator, .{ .path = lazy_path.dupe(b) }) catch @panic("OOM"); + addLazyPathDependenciesOnly(m, lazy_path); +} + +pub fn addConfigHeader(m: *Module, config_header: *Step.ConfigHeader) void { + const allocator = m.owner.allocator; + m.include_dirs.append(allocator, .{ .config_header_step = config_header }) catch @panic("OOM"); + addStepDependenciesOnly(m, &config_header.step); +} + +pub fn addSystemFrameworkPath(m: *Module, directory_path: LazyPath) void { + const b = m.owner; + m.include_dirs.append(b.allocator, .{ .framework_path_system = directory_path.dupe(b) }) catch + @panic("OOM"); + addLazyPathDependenciesOnly(m, directory_path); +} + +pub fn addFrameworkPath(m: *Module, directory_path: LazyPath) void { + const b = m.owner; + m.include_dirs.append(b.allocator, .{ .framework_path = directory_path.dupe(b) }) catch + @panic("OOM"); + addLazyPathDependenciesOnly(m, directory_path); +} + +pub fn addLibraryPath(m: *Module, directory_path: LazyPath) void { + const b = m.owner; + m.lib_paths.append(b.allocator, directory_path.dupe(b)) catch @panic("OOM"); + addLazyPathDependenciesOnly(m, directory_path); +} + +pub fn addRPath(m: *Module, directory_path: LazyPath) void { + const b = m.owner; + switch (directory_path) { + .path, .cwd_relative => |path| { + // TODO: remove this check after people upgrade and stop expecting it to work + if (std.mem.startsWith(u8, path, "@executable_path") or + std.mem.startsWith(u8, path, "@loader_path")) + { + @panic("this function is for adding directory paths. It does not support special rpaths. use addRPathSpecial for that."); + } + }, + else => {}, + } + m.rpaths.append(b.allocator, .{ .lazy_path = directory_path.dupe(b) }) catch @panic("OOM"); + addLazyPathDependenciesOnly(m, directory_path); +} + +pub fn addRPathSpecial(m: *Module, bytes: []const u8) void { + const b = m.owner; + m.rpaths.append(b.allocator, .{ .special = b.dupe(bytes) }) catch @panic("OOM"); +} + +/// Equvialent to the following C code, applied to all C source files owned by +/// this `Module`: +/// ```c +/// #define name value +/// ``` +/// `name` and `value` need not live longer than the function call. +pub fn addCMacro(m: *Module, name: []const u8, value: []const u8) void { + const b = m.owner; + m.c_macros.append(b.allocator, b.fmt("-D{s}={s}", .{ name, value })) catch @panic("OOM"); } pub fn appendZigProcessFlags( m: *Module, zig_args: *std.ArrayList([]const u8), - asking_step: ?*std.Build.Step, + asking_step: ?*Step, ) !void { const b = m.owner; @@ -495,27 +612,30 @@ pub fn appendZigProcessFlags( } try zig_args.ensureUnusedCapacity(1); - switch (m.optimize) { - .Debug => {}, // Skip since it's the default. + if (m.optimize) |optimize| switch (optimize) { + .Debug => zig_args.appendAssumeCapacity("-ODebug"), .ReleaseSmall => zig_args.appendAssumeCapacity("-OReleaseSmall"), .ReleaseFast => zig_args.appendAssumeCapacity("-OReleaseFast"), .ReleaseSafe => zig_args.appendAssumeCapacity("-OReleaseSafe"), - } + }; if (m.code_model != .default) { try zig_args.append("-mcmodel"); try zig_args.append(@tagName(m.code_model)); } - if (!m.target.isNative()) { - try zig_args.appendSlice(&.{ - "-target", try m.target.zigTriple(b.allocator), - "-mcpu", try std.Build.serializeCpu(b.allocator, m.target.getCpu()), - }); - - if (m.target.dynamic_linker.get()) |dynamic_linker| { - try zig_args.append("--dynamic-linker"); - try zig_args.append(dynamic_linker); + if (m.target) |target| { + // Communicate the query via CLI since it's more compact. + if (!target.query.isNative()) { + try zig_args.appendSlice(&.{ + "-target", try target.query.zigTriple(b.allocator), + "-mcpu", try std.Build.serializeCpu(b.allocator, target.query.getCpu()), + }); + + if (target.query.dynamic_linker.get()) |dynamic_linker| { + try zig_args.append("--dynamic-linker"); + try zig_args.append(dynamic_linker); + } } } @@ -565,10 +685,7 @@ pub fn appendZigProcessFlags( } } - for (m.c_macros.items) |c_macro| { - try zig_args.append("-D"); - try zig_args.append(c_macro); - } + try zig_args.appendSlice(m.c_macros.items); try zig_args.ensureUnusedCapacity(2 * m.lib_paths.items.len); for (m.lib_paths.items) |lib_path| { @@ -577,26 +694,16 @@ pub fn appendZigProcessFlags( } try zig_args.ensureUnusedCapacity(2 * m.rpaths.items.len); - for (m.rpaths.items) |rpath| { - zig_args.appendAssumeCapacity("-rpath"); - - if (m.target_info.target.isDarwin()) switch (rpath) { - .path, .cwd_relative => |path| { - // On Darwin, we should not try to expand special runtime paths such as - // * @executable_path - // * @loader_path - if (std.mem.startsWith(u8, path, "@executable_path") or - std.mem.startsWith(u8, path, "@loader_path")) - { - zig_args.appendAssumeCapacity(path); - continue; - } - }, - .generated, .dependency => {}, - }; - - zig_args.appendAssumeCapacity(rpath.getPath2(b, asking_step)); - } + for (m.rpaths.items) |rpath| switch (rpath) { + .lazy_path => |lp| { + zig_args.appendAssumeCapacity("-rpath"); + zig_args.appendAssumeCapacity(lp.getPath2(b, asking_step)); + }, + .special => |bytes| { + zig_args.appendAssumeCapacity("-rpath"); + zig_args.appendAssumeCapacity(bytes); + }, + }; } fn addFlag( @@ -609,8 +716,32 @@ fn addFlag( return args.append(if (cond) then_name else else_name); } +fn linkLibraryOrObject(m: *Module, other: *Step.Compile) void { + const allocator = m.owner.allocator; + _ = other.getEmittedBin(); // Indicate there is a dependency on the outputted binary. + addStepDependenciesOnly(m, &other.step); + + if (other.rootModuleTarget().os.tag == .windows and other.isDynamicLibrary()) { + _ = other.getEmittedImplib(); // Indicate dependency on the outputted implib. + } + + m.link_objects.append(allocator, .{ .other_step = other }) catch @panic("OOM"); + m.include_dirs.append(allocator, .{ .other_step = other }) catch @panic("OOM"); + + for (other.installed_headers.items) |install_step| { + addStepDependenciesOnly(m, install_step); + } +} + +fn requireKnownTarget(m: *Module) std.Target { + const resolved_target = m.target orelse + @panic("this API requires the Module to be created with a known 'target' field"); + return resolved_target.target; +} + const Module = @This(); const std = @import("std"); const assert = std.debug.assert; const LazyPath = std.Build.LazyPath; const NativeTargetInfo = std.zig.system.NativeTargetInfo; +const Step = std.Build.Step; |
