mirror of
https://github.com/ziglang/zig.git
synced 2026-02-12 20:37:54 +00:00
stage2: building mingw-w64 and COFF LDD linking
still TODO is the task of creating import .lib files for DLLs on the fly both for -lfoo and for e.g. `extern "kernel32"`
This commit is contained in:
parent
a9082b4ec5
commit
91a73a177b
10
BRANCH_TODO
10
BRANCH_TODO
@ -1,14 +1,13 @@
|
||||
* COFF LLD linking
|
||||
* mingw-w64
|
||||
* add jobs to build import libs for windows DLLs for explicitly linked libs
|
||||
* add jobs to build import libs for windows DLLs for extern "foo" functions used
|
||||
* MachO LLD linking
|
||||
* WASM LLD linking
|
||||
* audit the CLI options for stage2
|
||||
* audit the base cache hash
|
||||
* On operating systems that support it, do an execve for `zig test` and `zig run` rather than child process.
|
||||
* windows CUSTOMBUILD : error : unable to build compiler_rt: FileNotFound [D:\a\1\s\build\zig_install_lib_files.vcxproj]
|
||||
* try building some software with zig cc to make sure it didn't regress
|
||||
* `-ftime-report`
|
||||
* -fstack-report print stack size diagnostics\n"
|
||||
* try building some software with zig cc to make sure it didn't regress
|
||||
|
||||
* implement proper parsing of clang stderr/stdout and exposing compile errors with the Compilation API
|
||||
* implement proper parsing of LLD stderr/stdout and exposing compile errors with the Compilation API
|
||||
@ -35,6 +34,7 @@
|
||||
* integrate target features into building assembly code
|
||||
* libc_installation.zig: make it look for msvc only if msvc abi is chosen
|
||||
* switch the default C ABI for windows to be mingw-w64
|
||||
- make it .obj instead of .o always for coff
|
||||
* change glibc log errors to normal exposed compile errors
|
||||
* improve Directory.join to only use 1 allocation in a clean way.
|
||||
* tracy builds with lc++
|
||||
@ -48,3 +48,5 @@
|
||||
* linking hello world with LLD, lld is silently calling exit(1) instead of reporting ok=false. when run standalone the error message is: ld.lld: error: section [index 3] has a sh_offset (0x57000) + sh_size (0x68) that is greater than the file size (0x57060)
|
||||
* submit PR to godbolt and update the CLI options (see changes to test/cli.zig)
|
||||
* make proposal about log levels
|
||||
* proposal for changing fs Z/W functions to be native paths and have a way to do native path string literals
|
||||
* proposal for block { break x; }
|
||||
|
||||
@ -93,7 +93,7 @@ pub fn binNameAlloc(allocator: *std.mem.Allocator, options: BinNameOptions) erro
|
||||
};
|
||||
return std.fmt.allocPrint(allocator, "{}{}{}", .{ target.libPrefix(), root_name, suffix });
|
||||
},
|
||||
.Obj => return std.fmt.allocPrint(allocator, "{}.obj", .{root_name}),
|
||||
.Obj => return std.fmt.allocPrint(allocator, "{}{}", .{ root_name, target.abi.oFileExt() }),
|
||||
},
|
||||
.elf => switch (options.output_mode) {
|
||||
.Exe => return allocator.dupe(u8, root_name),
|
||||
|
||||
@ -76,6 +76,14 @@ pub const HashHelper = struct {
|
||||
for (list_of_bytes) |bytes| hh.addBytes(bytes);
|
||||
}
|
||||
|
||||
pub fn addStringSet(hh: *HashHelper, hm: std.StringArrayHashMapUnmanaged(void)) void {
|
||||
const entries = hm.items();
|
||||
hh.add(entries.len);
|
||||
for (entries) |entry| {
|
||||
hh.addBytes(entry.key);
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert the input value into bytes and record it as a dependency of the process being cached.
|
||||
pub fn add(hh: *HashHelper, x: anytype) void {
|
||||
switch (@TypeOf(x)) {
|
||||
|
||||
@ -17,6 +17,7 @@ const build_options = @import("build_options");
|
||||
const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
|
||||
const glibc = @import("glibc.zig");
|
||||
const musl = @import("musl.zig");
|
||||
const mingw = @import("mingw.zig");
|
||||
const libunwind = @import("libunwind.zig");
|
||||
const libcxx = @import("libcxx.zig");
|
||||
const fatal = @import("main.zig").fatal;
|
||||
@ -59,7 +60,6 @@ verbose_llvm_ir: bool,
|
||||
verbose_cimport: bool,
|
||||
verbose_llvm_cpu_features: bool,
|
||||
disable_c_depfile: bool,
|
||||
is_test: bool,
|
||||
time_report: bool,
|
||||
|
||||
c_source_files: []const CSourceFile,
|
||||
@ -150,8 +150,10 @@ const Job = union(enum) {
|
||||
glibc_crt_file: glibc.CRTFile,
|
||||
/// all of the glibc shared objects
|
||||
glibc_shared_objects,
|
||||
/// one of the glibc static objects
|
||||
/// one of the musl static objects
|
||||
musl_crt_file: musl.CRTFile,
|
||||
/// one of the mingw-w64 static objects
|
||||
mingw_crt_file: mingw.CRTFile,
|
||||
/// libunwind.a, usually needed when linking libc
|
||||
libunwind: void,
|
||||
libcxx: void,
|
||||
@ -719,6 +721,13 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
||||
fatal("TODO implement support for -femit-h in the self-hosted backend", .{});
|
||||
}
|
||||
|
||||
var system_libs: std.StringArrayHashMapUnmanaged(void) = .{};
|
||||
errdefer system_libs.deinit(gpa);
|
||||
try system_libs.ensureCapacity(gpa, options.system_libs.len);
|
||||
for (options.system_libs) |lib_name| {
|
||||
system_libs.putAssumeCapacity(lib_name, {});
|
||||
}
|
||||
|
||||
const bin_file = try link.File.openPath(gpa, .{
|
||||
.emit = bin_file_emit,
|
||||
.root_name = root_name,
|
||||
@ -736,7 +745,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
||||
.objects = options.link_objects,
|
||||
.frameworks = options.frameworks,
|
||||
.framework_dirs = options.framework_dirs,
|
||||
.system_libs = options.system_libs,
|
||||
.system_libs = system_libs,
|
||||
.lib_dirs = options.lib_dirs,
|
||||
.rpath_list = options.rpath_list,
|
||||
.strip = options.strip,
|
||||
@ -769,6 +778,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
||||
.each_lib_rpath = options.each_lib_rpath orelse false,
|
||||
.disable_lld_caching = options.disable_lld_caching,
|
||||
.subsystem = options.subsystem,
|
||||
.is_test = options.is_test,
|
||||
});
|
||||
errdefer bin_file.destroy();
|
||||
comp.* = .{
|
||||
@ -804,7 +814,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
||||
.verbose_llvm_cpu_features = options.verbose_llvm_cpu_features,
|
||||
.disable_c_depfile = options.disable_c_depfile,
|
||||
.owned_link_dir = owned_link_dir,
|
||||
.is_test = options.is_test,
|
||||
.color = options.color,
|
||||
.time_report = options.time_report,
|
||||
.test_filter = options.test_filter,
|
||||
@ -847,8 +856,17 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
||||
.{ .musl_crt_file = .libc_a },
|
||||
});
|
||||
}
|
||||
if (comp.wantBuildMinGWW64FromSource()) {
|
||||
@panic("TODO");
|
||||
if (comp.wantBuildMinGWFromSource()) {
|
||||
const static_lib_jobs = [_]Job{
|
||||
.{ .mingw_crt_file = .mingw32_lib },
|
||||
.{ .mingw_crt_file = .msvcrt_os_lib },
|
||||
.{ .mingw_crt_file = .mingwex_lib },
|
||||
.{ .mingw_crt_file = .uuid_lib },
|
||||
};
|
||||
const crt_job: Job = .{ .mingw_crt_file = if (is_dyn_lib) .dllcrt2_o else .crt2_o };
|
||||
try comp.work_queue.ensureUnusedCapacity(static_lib_jobs.len + 1);
|
||||
comp.work_queue.writeAssumeCapacity(&static_lib_jobs);
|
||||
comp.work_queue.writeItemAssumeCapacity(crt_job);
|
||||
}
|
||||
if (comp.wantBuildLibUnwindFromSource()) {
|
||||
try comp.work_queue.writeItem(.{ .libunwind = {} });
|
||||
@ -1209,6 +1227,12 @@ pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void {
|
||||
fatal("unable to build musl CRT file: {}", .{@errorName(err)});
|
||||
};
|
||||
},
|
||||
.mingw_crt_file => |crt_file| {
|
||||
mingw.buildCRTFile(self, crt_file) catch |err| {
|
||||
// TODO Expose this as a normal compile error rather than crashing here.
|
||||
fatal("unable to build mingw-w64 CRT file: {}", .{@errorName(err)});
|
||||
};
|
||||
},
|
||||
.libunwind => {
|
||||
libunwind.buildStaticLib(self) catch |err| {
|
||||
// TODO Expose this as a normal compile error rather than crashing here.
|
||||
@ -2087,7 +2111,7 @@ fn detectLibCFromLibCInstallation(arena: *Allocator, target: Target, lci: *const
|
||||
pub fn get_libc_crt_file(comp: *Compilation, arena: *Allocator, basename: []const u8) ![]const u8 {
|
||||
if (comp.wantBuildGLibCFromSource() or
|
||||
comp.wantBuildMuslFromSource() or
|
||||
comp.wantBuildMinGWW64FromSource())
|
||||
comp.wantBuildMinGWFromSource())
|
||||
{
|
||||
return comp.crt_files.get(basename).?.full_object_path;
|
||||
}
|
||||
@ -2125,7 +2149,7 @@ fn wantBuildMuslFromSource(comp: Compilation) bool {
|
||||
return comp.wantBuildLibCFromSource() and comp.getTarget().isMusl();
|
||||
}
|
||||
|
||||
fn wantBuildMinGWW64FromSource(comp: Compilation) bool {
|
||||
fn wantBuildMinGWFromSource(comp: Compilation) bool {
|
||||
return comp.wantBuildLibCFromSource() and comp.getTarget().isMinGW();
|
||||
}
|
||||
|
||||
@ -2186,7 +2210,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8
|
||||
, .{
|
||||
@tagName(comp.bin_file.options.output_mode),
|
||||
@tagName(comp.bin_file.options.link_mode),
|
||||
comp.is_test,
|
||||
comp.bin_file.options.is_test,
|
||||
comp.bin_file.options.single_threaded,
|
||||
@tagName(target.abi),
|
||||
@tagName(target.cpu.arch),
|
||||
@ -2214,7 +2238,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8
|
||||
\\pub const os = Os{{
|
||||
\\ .tag = .{},
|
||||
\\ .version_range = .{{
|
||||
,
|
||||
,
|
||||
.{@tagName(target.os.tag)},
|
||||
);
|
||||
|
||||
@ -2283,7 +2307,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8
|
||||
\\ .max = {s},
|
||||
\\ }}}},
|
||||
\\
|
||||
,
|
||||
,
|
||||
.{ windows.min, windows.max },
|
||||
),
|
||||
}
|
||||
@ -2311,7 +2335,7 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8
|
||||
@tagName(comp.bin_file.options.machine_code_model),
|
||||
});
|
||||
|
||||
if (comp.is_test) {
|
||||
if (comp.bin_file.options.is_test) {
|
||||
try buffer.appendSlice(
|
||||
\\pub var test_functions: []TestFn = undefined; // overwritten later
|
||||
\\
|
||||
@ -2384,7 +2408,7 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR
|
||||
.basename = bin_basename,
|
||||
};
|
||||
const optimize_mode: std.builtin.Mode = blk: {
|
||||
if (comp.is_test)
|
||||
if (comp.bin_file.options.is_test)
|
||||
break :blk comp.bin_file.options.optimize_mode;
|
||||
switch (comp.bin_file.options.optimize_mode) {
|
||||
.Debug, .ReleaseFast, .ReleaseSafe => break :blk .ReleaseFast,
|
||||
@ -2473,7 +2497,7 @@ fn updateStage1Module(comp: *Compilation) !void {
|
||||
man.hash.add(target.os.getVersionRange());
|
||||
man.hash.add(comp.bin_file.options.dll_export_fns);
|
||||
man.hash.add(comp.bin_file.options.function_sections);
|
||||
man.hash.add(comp.is_test);
|
||||
man.hash.add(comp.bin_file.options.is_test);
|
||||
man.hash.add(comp.bin_file.options.emit != null);
|
||||
man.hash.add(comp.emit_h != null);
|
||||
man.hash.add(comp.emit_asm != null);
|
||||
@ -2537,7 +2561,7 @@ fn updateStage1Module(comp: *Compilation) !void {
|
||||
zig_lib_dir.ptr,
|
||||
zig_lib_dir.len,
|
||||
stage2_target,
|
||||
comp.is_test,
|
||||
comp.bin_file.options.is_test,
|
||||
) orelse return error.OutOfMemory;
|
||||
|
||||
const emit_bin_path = if (comp.bin_file.options.emit != null) blk: {
|
||||
@ -2609,8 +2633,22 @@ fn updateStage1Module(comp: *Compilation) !void {
|
||||
.verbose_cimport = comp.verbose_cimport,
|
||||
.verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
|
||||
.main_progress_node = main_progress_node,
|
||||
.have_c_main = false,
|
||||
.have_winmain = false,
|
||||
.have_wwinmain = false,
|
||||
.have_winmain_crt_startup = false,
|
||||
.have_wwinmain_crt_startup = false,
|
||||
.have_dllmain_crt_startup = false,
|
||||
};
|
||||
stage1_module.build_object();
|
||||
|
||||
mod.have_c_main = stage1_module.have_c_main;
|
||||
mod.have_winmain = stage1_module.have_winmain;
|
||||
mod.have_wwinmain = stage1_module.have_wwinmain;
|
||||
mod.have_winmain_crt_startup = stage1_module.have_winmain_crt_startup;
|
||||
mod.have_wwinmain_crt_startup = stage1_module.have_wwinmain_crt_startup;
|
||||
mod.have_dllmain_crt_startup = stage1_module.have_dllmain_crt_startup;
|
||||
|
||||
stage1_module.destroy();
|
||||
|
||||
const digest = man.final();
|
||||
|
||||
@ -75,6 +75,13 @@ global_error_set: std.StringHashMapUnmanaged(u16) = .{},
|
||||
/// previous analysis.
|
||||
generation: u32 = 0,
|
||||
|
||||
have_winmain: bool = false,
|
||||
have_wwinmain: bool = false,
|
||||
have_winmain_crt_startup: bool = false,
|
||||
have_wwinmain_crt_startup: bool = false,
|
||||
have_dllmain_crt_startup: bool = false,
|
||||
have_c_main: bool = false,
|
||||
|
||||
pub const Export = struct {
|
||||
options: std.builtin.ExportOptions,
|
||||
/// Byte offset into the file that contains the export directive.
|
||||
@ -2668,7 +2675,7 @@ pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst
|
||||
const src_info = inst.ty.intInfo(self.getTarget());
|
||||
const dst_info = dest_type.intInfo(self.getTarget());
|
||||
if ((src_info.signed == dst_info.signed and dst_info.bits >= src_info.bits) or
|
||||
// small enough unsigned ints can get casted to large enough signed ints
|
||||
// small enough unsigned ints can get casted to large enough signed ints
|
||||
(src_info.signed and !dst_info.signed and dst_info.bits > src_info.bits))
|
||||
{
|
||||
const b = try self.requireRuntimeBlock(scope, inst.src);
|
||||
|
||||
53
src/link.zig
53
src/link.zig
@ -36,7 +36,7 @@ pub const Options = struct {
|
||||
root_name: []const u8,
|
||||
/// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`.
|
||||
module: ?*Module,
|
||||
dynamic_linker: ?[]const u8 = null,
|
||||
dynamic_linker: ?[]const u8,
|
||||
/// Used for calculating how much space to reserve for symbols in case the binary file
|
||||
/// does not already have a symbol table.
|
||||
symbol_count_hint: u64 = 32,
|
||||
@ -44,53 +44,54 @@ pub const Options = struct {
|
||||
/// the binary file does not already have such a section.
|
||||
program_code_size_hint: u64 = 256 * 1024,
|
||||
entry_addr: ?u64 = null,
|
||||
stack_size_override: ?u64 = null,
|
||||
stack_size_override: ?u64,
|
||||
/// Set to `true` to omit debug info.
|
||||
strip: bool = false,
|
||||
strip: bool,
|
||||
/// If this is true then this link code is responsible for outputting an object
|
||||
/// file and then using LLD to link it together with the link options and other objects.
|
||||
/// Otherwise (depending on `use_llvm`) this link code directly outputs and updates the final binary.
|
||||
use_lld: bool = false,
|
||||
use_lld: bool,
|
||||
/// If this is true then this link code is responsible for making an LLVM IR Module,
|
||||
/// outputting it to an object file, and then linking that together with link options and
|
||||
/// other objects.
|
||||
/// Otherwise (depending on `use_lld`) this link code directly outputs and updates the final binary.
|
||||
use_llvm: bool = false,
|
||||
link_libc: bool = false,
|
||||
link_libcpp: bool = false,
|
||||
function_sections: bool = false,
|
||||
eh_frame_hdr: bool = false,
|
||||
rdynamic: bool = false,
|
||||
z_nodelete: bool = false,
|
||||
z_defs: bool = false,
|
||||
use_llvm: bool,
|
||||
link_libc: bool,
|
||||
link_libcpp: bool,
|
||||
function_sections: bool,
|
||||
eh_frame_hdr: bool,
|
||||
rdynamic: bool,
|
||||
z_nodelete: bool,
|
||||
z_defs: bool,
|
||||
bind_global_refs_locally: bool,
|
||||
is_native_os: bool,
|
||||
pic: bool,
|
||||
valgrind: bool,
|
||||
stack_check: bool,
|
||||
single_threaded: bool,
|
||||
verbose_link: bool = false,
|
||||
verbose_link: bool,
|
||||
dll_export_fns: bool,
|
||||
error_return_tracing: bool,
|
||||
is_compiler_rt_or_libc: bool,
|
||||
each_lib_rpath: bool,
|
||||
disable_lld_caching: bool,
|
||||
is_test: bool,
|
||||
gc_sections: ?bool = null,
|
||||
allow_shlib_undefined: ?bool = null,
|
||||
subsystem: ?std.Target.SubSystem = null,
|
||||
linker_script: ?[]const u8 = null,
|
||||
version_script: ?[]const u8 = null,
|
||||
override_soname: ?[]const u8 = null,
|
||||
llvm_cpu_features: ?[*:0]const u8 = null,
|
||||
allow_shlib_undefined: ?bool,
|
||||
subsystem: ?std.Target.SubSystem,
|
||||
linker_script: ?[]const u8,
|
||||
version_script: ?[]const u8,
|
||||
override_soname: ?[]const u8,
|
||||
llvm_cpu_features: ?[*:0]const u8,
|
||||
/// Extra args passed directly to LLD. Ignored when not linking with LLD.
|
||||
extra_lld_args: []const []const u8 = &[0][]const u8,
|
||||
extra_lld_args: []const []const u8,
|
||||
|
||||
objects: []const []const u8 = &[0][]const u8{},
|
||||
framework_dirs: []const []const u8 = &[0][]const u8{},
|
||||
frameworks: []const []const u8 = &[0][]const u8{},
|
||||
system_libs: []const []const u8 = &[0][]const u8{},
|
||||
lib_dirs: []const []const u8 = &[0][]const u8{},
|
||||
rpath_list: []const []const u8 = &[0][]const u8{},
|
||||
objects: []const []const u8,
|
||||
framework_dirs: []const []const u8,
|
||||
frameworks: []const []const u8,
|
||||
system_libs: std.StringArrayHashMapUnmanaged(void),
|
||||
lib_dirs: []const []const u8,
|
||||
rpath_list: []const []const u8,
|
||||
|
||||
version: ?std.builtin.Version,
|
||||
libc_installation: ?*const LibCInstallation,
|
||||
|
||||
@ -5,6 +5,8 @@ const log = std.log.scoped(.link);
|
||||
const Allocator = std.mem.Allocator;
|
||||
const assert = std.debug.assert;
|
||||
const fs = std.fs;
|
||||
const allocPrint = std.fmt.allocPrint;
|
||||
const mem = std.mem;
|
||||
|
||||
const trace = @import("../tracy.zig").trace;
|
||||
const Module = @import("../Module.zig");
|
||||
@ -12,6 +14,8 @@ const Compilation = @import("../Compilation.zig");
|
||||
const codegen = @import("../codegen.zig");
|
||||
const link = @import("../link.zig");
|
||||
const build_options = @import("build_options");
|
||||
const Cache = @import("../Cache.zig");
|
||||
const mingw = @import("../mingw.zig");
|
||||
|
||||
const allocation_padding = 4 / 3;
|
||||
const minimum_text_block_size = 64 * allocation_padding;
|
||||
@ -21,7 +25,7 @@ const file_alignment = 512;
|
||||
const image_base = 0x400_000;
|
||||
const section_table_size = 2 * 40;
|
||||
comptime {
|
||||
assert(std.mem.isAligned(image_base, section_alignment));
|
||||
assert(mem.isAligned(image_base, section_alignment));
|
||||
}
|
||||
|
||||
pub const base_tag: link.File.Tag = .coff;
|
||||
@ -155,14 +159,14 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
|
||||
if (machine == .Unknown) {
|
||||
return error.UnsupportedCOFFArchitecture;
|
||||
}
|
||||
std.mem.writeIntLittle(u16, hdr_data[0..2], @enumToInt(machine));
|
||||
mem.writeIntLittle(u16, hdr_data[0..2], @enumToInt(machine));
|
||||
index += 2;
|
||||
|
||||
// Number of sections (we only use .got, .text)
|
||||
std.mem.writeIntLittle(u16, hdr_data[index..][0..2], 2);
|
||||
mem.writeIntLittle(u16, hdr_data[index..][0..2], 2);
|
||||
index += 2;
|
||||
// TimeDateStamp (u32), PointerToSymbolTable (u32), NumberOfSymbols (u32)
|
||||
std.mem.set(u8, hdr_data[index..][0..12], 0);
|
||||
mem.set(u8, hdr_data[index..][0..12], 0);
|
||||
index += 12;
|
||||
|
||||
const optional_header_size = switch (options.output_mode) {
|
||||
@ -177,8 +181,8 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
|
||||
const default_offset_table_size = file_alignment;
|
||||
const default_size_of_code = 0;
|
||||
|
||||
self.section_data_offset = std.mem.alignForwardGeneric(u32, self.section_table_offset + section_table_size, file_alignment);
|
||||
const section_data_relative_virtual_address = std.mem.alignForwardGeneric(u32, self.section_table_offset + section_table_size, section_alignment);
|
||||
self.section_data_offset = mem.alignForwardGeneric(u32, self.section_table_offset + section_table_size, file_alignment);
|
||||
const section_data_relative_virtual_address = mem.alignForwardGeneric(u32, self.section_table_offset + section_table_size, section_alignment);
|
||||
self.offset_table_virtual_address = image_base + section_data_relative_virtual_address;
|
||||
self.offset_table_size = default_offset_table_size;
|
||||
self.section_table_offset = section_table_offset;
|
||||
@ -186,9 +190,9 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
|
||||
self.text_section_size = default_size_of_code;
|
||||
|
||||
// Size of file when loaded in memory
|
||||
const size_of_image = std.mem.alignForwardGeneric(u32, self.text_section_virtual_address - image_base + default_size_of_code, section_alignment);
|
||||
const size_of_image = mem.alignForwardGeneric(u32, self.text_section_virtual_address - image_base + default_size_of_code, section_alignment);
|
||||
|
||||
std.mem.writeIntLittle(u16, hdr_data[index..][0..2], optional_header_size);
|
||||
mem.writeIntLittle(u16, hdr_data[index..][0..2], optional_header_size);
|
||||
index += 2;
|
||||
|
||||
// Characteristics
|
||||
@ -200,7 +204,7 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
|
||||
.p32 => characteristics |= std.coff.IMAGE_FILE_32BIT_MACHINE,
|
||||
.p64 => characteristics |= std.coff.IMAGE_FILE_LARGE_ADDRESS_AWARE,
|
||||
}
|
||||
std.mem.writeIntLittle(u16, hdr_data[index..][0..2], characteristics);
|
||||
mem.writeIntLittle(u16, hdr_data[index..][0..2], characteristics);
|
||||
index += 2;
|
||||
|
||||
assert(index == 20);
|
||||
@ -210,106 +214,106 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
|
||||
self.optional_header_offset = coff_file_header_offset + 20;
|
||||
// Optional header
|
||||
index = 0;
|
||||
std.mem.writeIntLittle(u16, hdr_data[0..2], switch (self.ptr_width) {
|
||||
mem.writeIntLittle(u16, hdr_data[0..2], switch (self.ptr_width) {
|
||||
.p32 => @as(u16, 0x10b),
|
||||
.p64 => 0x20b,
|
||||
});
|
||||
index += 2;
|
||||
|
||||
// Linker version (u8 + u8)
|
||||
std.mem.set(u8, hdr_data[index..][0..2], 0);
|
||||
mem.set(u8, hdr_data[index..][0..2], 0);
|
||||
index += 2;
|
||||
|
||||
// SizeOfCode (UNUSED, u32), SizeOfInitializedData (u32), SizeOfUninitializedData (u32), AddressOfEntryPoint (u32), BaseOfCode (UNUSED, u32)
|
||||
std.mem.set(u8, hdr_data[index..][0..20], 0);
|
||||
mem.set(u8, hdr_data[index..][0..20], 0);
|
||||
index += 20;
|
||||
|
||||
if (self.ptr_width == .p32) {
|
||||
// Base of data relative to the image base (UNUSED)
|
||||
std.mem.set(u8, hdr_data[index..][0..4], 0);
|
||||
mem.set(u8, hdr_data[index..][0..4], 0);
|
||||
index += 4;
|
||||
|
||||
// Image base address
|
||||
std.mem.writeIntLittle(u32, hdr_data[index..][0..4], image_base);
|
||||
mem.writeIntLittle(u32, hdr_data[index..][0..4], image_base);
|
||||
index += 4;
|
||||
} else {
|
||||
// Image base address
|
||||
std.mem.writeIntLittle(u64, hdr_data[index..][0..8], image_base);
|
||||
mem.writeIntLittle(u64, hdr_data[index..][0..8], image_base);
|
||||
index += 8;
|
||||
}
|
||||
|
||||
// Section alignment
|
||||
std.mem.writeIntLittle(u32, hdr_data[index..][0..4], section_alignment);
|
||||
mem.writeIntLittle(u32, hdr_data[index..][0..4], section_alignment);
|
||||
index += 4;
|
||||
// File alignment
|
||||
std.mem.writeIntLittle(u32, hdr_data[index..][0..4], file_alignment);
|
||||
mem.writeIntLittle(u32, hdr_data[index..][0..4], file_alignment);
|
||||
index += 4;
|
||||
// Required OS version, 6.0 is vista
|
||||
std.mem.writeIntLittle(u16, hdr_data[index..][0..2], 6);
|
||||
mem.writeIntLittle(u16, hdr_data[index..][0..2], 6);
|
||||
index += 2;
|
||||
std.mem.writeIntLittle(u16, hdr_data[index..][0..2], 0);
|
||||
mem.writeIntLittle(u16, hdr_data[index..][0..2], 0);
|
||||
index += 2;
|
||||
// Image version
|
||||
std.mem.set(u8, hdr_data[index..][0..4], 0);
|
||||
mem.set(u8, hdr_data[index..][0..4], 0);
|
||||
index += 4;
|
||||
// Required subsystem version, same as OS version
|
||||
std.mem.writeIntLittle(u16, hdr_data[index..][0..2], 6);
|
||||
mem.writeIntLittle(u16, hdr_data[index..][0..2], 6);
|
||||
index += 2;
|
||||
std.mem.writeIntLittle(u16, hdr_data[index..][0..2], 0);
|
||||
mem.writeIntLittle(u16, hdr_data[index..][0..2], 0);
|
||||
index += 2;
|
||||
// Reserved zeroes (u32)
|
||||
std.mem.set(u8, hdr_data[index..][0..4], 0);
|
||||
mem.set(u8, hdr_data[index..][0..4], 0);
|
||||
index += 4;
|
||||
std.mem.writeIntLittle(u32, hdr_data[index..][0..4], size_of_image);
|
||||
mem.writeIntLittle(u32, hdr_data[index..][0..4], size_of_image);
|
||||
index += 4;
|
||||
std.mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset);
|
||||
mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset);
|
||||
index += 4;
|
||||
// CheckSum (u32)
|
||||
std.mem.set(u8, hdr_data[index..][0..4], 0);
|
||||
mem.set(u8, hdr_data[index..][0..4], 0);
|
||||
index += 4;
|
||||
// Subsystem, TODO: Let users specify the subsystem, always CUI for now
|
||||
std.mem.writeIntLittle(u16, hdr_data[index..][0..2], 3);
|
||||
mem.writeIntLittle(u16, hdr_data[index..][0..2], 3);
|
||||
index += 2;
|
||||
// DLL characteristics
|
||||
std.mem.writeIntLittle(u16, hdr_data[index..][0..2], 0x0);
|
||||
mem.writeIntLittle(u16, hdr_data[index..][0..2], 0x0);
|
||||
index += 2;
|
||||
|
||||
switch (self.ptr_width) {
|
||||
.p32 => {
|
||||
// Size of stack reserve + commit
|
||||
std.mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000_000);
|
||||
mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000_000);
|
||||
index += 4;
|
||||
std.mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000);
|
||||
mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000);
|
||||
index += 4;
|
||||
// Size of heap reserve + commit
|
||||
std.mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x100_000);
|
||||
mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x100_000);
|
||||
index += 4;
|
||||
std.mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000);
|
||||
mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000);
|
||||
index += 4;
|
||||
},
|
||||
.p64 => {
|
||||
// Size of stack reserve + commit
|
||||
std.mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000_000);
|
||||
mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000_000);
|
||||
index += 8;
|
||||
std.mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000);
|
||||
mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000);
|
||||
index += 8;
|
||||
// Size of heap reserve + commit
|
||||
std.mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x100_000);
|
||||
mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x100_000);
|
||||
index += 8;
|
||||
std.mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000);
|
||||
mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000);
|
||||
index += 8;
|
||||
},
|
||||
}
|
||||
|
||||
// Reserved zeroes
|
||||
std.mem.set(u8, hdr_data[index..][0..4], 0);
|
||||
mem.set(u8, hdr_data[index..][0..4], 0);
|
||||
index += 4;
|
||||
|
||||
// Number of data directories
|
||||
std.mem.writeIntLittle(u32, hdr_data[index..][0..4], data_directory_count);
|
||||
mem.writeIntLittle(u32, hdr_data[index..][0..4], data_directory_count);
|
||||
index += 4;
|
||||
// Initialize data directories to zero
|
||||
std.mem.set(u8, hdr_data[index..][0 .. data_directory_count * 8], 0);
|
||||
mem.set(u8, hdr_data[index..][0 .. data_directory_count * 8], 0);
|
||||
index += data_directory_count * 8;
|
||||
|
||||
assert(index == optional_header_size);
|
||||
@ -321,52 +325,52 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
|
||||
index += 8;
|
||||
if (options.output_mode == .Exe) {
|
||||
// Virtual size (u32)
|
||||
std.mem.writeIntLittle(u32, hdr_data[index..][0..4], default_offset_table_size);
|
||||
mem.writeIntLittle(u32, hdr_data[index..][0..4], default_offset_table_size);
|
||||
index += 4;
|
||||
// Virtual address (u32)
|
||||
std.mem.writeIntLittle(u32, hdr_data[index..][0..4], self.offset_table_virtual_address - image_base);
|
||||
mem.writeIntLittle(u32, hdr_data[index..][0..4], self.offset_table_virtual_address - image_base);
|
||||
index += 4;
|
||||
} else {
|
||||
std.mem.set(u8, hdr_data[index..][0..8], 0);
|
||||
mem.set(u8, hdr_data[index..][0..8], 0);
|
||||
index += 8;
|
||||
}
|
||||
// Size of raw data (u32)
|
||||
std.mem.writeIntLittle(u32, hdr_data[index..][0..4], default_offset_table_size);
|
||||
mem.writeIntLittle(u32, hdr_data[index..][0..4], default_offset_table_size);
|
||||
index += 4;
|
||||
// File pointer to the start of the section
|
||||
std.mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset);
|
||||
mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset);
|
||||
index += 4;
|
||||
// Pointer to relocations (u32), PointerToLinenumbers (u32), NumberOfRelocations (u16), NumberOfLinenumbers (u16)
|
||||
std.mem.set(u8, hdr_data[index..][0..12], 0);
|
||||
mem.set(u8, hdr_data[index..][0..12], 0);
|
||||
index += 12;
|
||||
// Section flags
|
||||
std.mem.writeIntLittle(u32, hdr_data[index..][0..4], std.coff.IMAGE_SCN_CNT_INITIALIZED_DATA | std.coff.IMAGE_SCN_MEM_READ);
|
||||
mem.writeIntLittle(u32, hdr_data[index..][0..4], std.coff.IMAGE_SCN_CNT_INITIALIZED_DATA | std.coff.IMAGE_SCN_MEM_READ);
|
||||
index += 4;
|
||||
// Then, the .text section
|
||||
hdr_data[index..][0..8].* = ".text\x00\x00\x00".*;
|
||||
index += 8;
|
||||
if (options.output_mode == .Exe) {
|
||||
// Virtual size (u32)
|
||||
std.mem.writeIntLittle(u32, hdr_data[index..][0..4], default_size_of_code);
|
||||
mem.writeIntLittle(u32, hdr_data[index..][0..4], default_size_of_code);
|
||||
index += 4;
|
||||
// Virtual address (u32)
|
||||
std.mem.writeIntLittle(u32, hdr_data[index..][0..4], self.text_section_virtual_address - image_base);
|
||||
mem.writeIntLittle(u32, hdr_data[index..][0..4], self.text_section_virtual_address - image_base);
|
||||
index += 4;
|
||||
} else {
|
||||
std.mem.set(u8, hdr_data[index..][0..8], 0);
|
||||
mem.set(u8, hdr_data[index..][0..8], 0);
|
||||
index += 8;
|
||||
}
|
||||
// Size of raw data (u32)
|
||||
std.mem.writeIntLittle(u32, hdr_data[index..][0..4], default_size_of_code);
|
||||
mem.writeIntLittle(u32, hdr_data[index..][0..4], default_size_of_code);
|
||||
index += 4;
|
||||
// File pointer to the start of the section
|
||||
std.mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset + default_offset_table_size);
|
||||
mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset + default_offset_table_size);
|
||||
index += 4;
|
||||
// Pointer to relocations (u32), PointerToLinenumbers (u32), NumberOfRelocations (u16), NumberOfLinenumbers (u16)
|
||||
std.mem.set(u8, hdr_data[index..][0..12], 0);
|
||||
mem.set(u8, hdr_data[index..][0..12], 0);
|
||||
index += 12;
|
||||
// Section flags
|
||||
std.mem.writeIntLittle(
|
||||
mem.writeIntLittle(
|
||||
u32,
|
||||
hdr_data[index..][0..4],
|
||||
std.coff.IMAGE_SCN_CNT_CODE | std.coff.IMAGE_SCN_MEM_EXECUTE | std.coff.IMAGE_SCN_MEM_READ | std.coff.IMAGE_SCN_MEM_WRITE,
|
||||
@ -434,7 +438,7 @@ fn allocateTextBlock(self: *Coff, text_block: *TextBlock, new_block_size: u64, a
|
||||
const free_block = self.text_block_free_list.items[i];
|
||||
|
||||
const next_block_text_offset = free_block.text_offset + free_block.capacity();
|
||||
const new_block_text_offset = std.mem.alignForwardGeneric(u64, free_block.getVAddr(self.*) + free_block.size, alignment) - self.text_section_virtual_address;
|
||||
const new_block_text_offset = mem.alignForwardGeneric(u64, free_block.getVAddr(self.*) + free_block.size, alignment) - self.text_section_virtual_address;
|
||||
if (new_block_text_offset < next_block_text_offset and next_block_text_offset - new_block_text_offset >= new_block_min_capacity) {
|
||||
block_placement = free_block;
|
||||
|
||||
@ -453,7 +457,7 @@ fn allocateTextBlock(self: *Coff, text_block: *TextBlock, new_block_size: u64, a
|
||||
continue;
|
||||
}
|
||||
} else if (self.last_text_block) |last| {
|
||||
const new_block_vaddr = std.mem.alignForwardGeneric(u64, last.getVAddr(self.*) + last.size, alignment);
|
||||
const new_block_vaddr = mem.alignForwardGeneric(u64, last.getVAddr(self.*) + last.size, alignment);
|
||||
block_placement = last;
|
||||
break :blk new_block_vaddr;
|
||||
} else {
|
||||
@ -463,15 +467,15 @@ fn allocateTextBlock(self: *Coff, text_block: *TextBlock, new_block_size: u64, a
|
||||
|
||||
const expand_text_section = block_placement == null or block_placement.?.next == null;
|
||||
if (expand_text_section) {
|
||||
const needed_size = @intCast(u32, std.mem.alignForwardGeneric(u64, vaddr + new_block_size - self.text_section_virtual_address, file_alignment));
|
||||
const needed_size = @intCast(u32, mem.alignForwardGeneric(u64, vaddr + new_block_size - self.text_section_virtual_address, file_alignment));
|
||||
if (needed_size > self.text_section_size) {
|
||||
const current_text_section_virtual_size = std.mem.alignForwardGeneric(u32, self.text_section_size, section_alignment);
|
||||
const new_text_section_virtual_size = std.mem.alignForwardGeneric(u32, needed_size, section_alignment);
|
||||
const current_text_section_virtual_size = mem.alignForwardGeneric(u32, self.text_section_size, section_alignment);
|
||||
const new_text_section_virtual_size = mem.alignForwardGeneric(u32, needed_size, section_alignment);
|
||||
if (current_text_section_virtual_size != new_text_section_virtual_size) {
|
||||
self.size_of_image_dirty = true;
|
||||
// Write new virtual size
|
||||
var buf: [4]u8 = undefined;
|
||||
std.mem.writeIntLittle(u32, &buf, new_text_section_virtual_size);
|
||||
mem.writeIntLittle(u32, &buf, new_text_section_virtual_size);
|
||||
try self.base.file.?.pwriteAll(&buf, self.section_table_offset + 40 + 8);
|
||||
}
|
||||
|
||||
@ -509,7 +513,7 @@ fn allocateTextBlock(self: *Coff, text_block: *TextBlock, new_block_size: u64, a
|
||||
|
||||
fn growTextBlock(self: *Coff, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {
|
||||
const block_vaddr = text_block.getVAddr(self.*);
|
||||
const align_ok = std.mem.alignBackwardGeneric(u64, block_vaddr, alignment) == block_vaddr;
|
||||
const align_ok = mem.alignBackwardGeneric(u64, block_vaddr, alignment) == block_vaddr;
|
||||
const need_realloc = !align_ok or new_block_size > text_block.capacity();
|
||||
if (!need_realloc) return @as(u64, block_vaddr);
|
||||
return self.allocateTextBlock(text_block, new_block_size, alignment);
|
||||
@ -575,14 +579,14 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void {
|
||||
|
||||
// Write the new raw size in the .got header
|
||||
var buf: [8]u8 = undefined;
|
||||
std.mem.writeIntLittle(u32, buf[0..4], new_raw_size);
|
||||
mem.writeIntLittle(u32, buf[0..4], new_raw_size);
|
||||
try self.base.file.?.pwriteAll(buf[0..4], self.section_table_offset + 16);
|
||||
// Write the new .text section file offset in the .text section header
|
||||
std.mem.writeIntLittle(u32, buf[0..4], new_text_section_start);
|
||||
mem.writeIntLittle(u32, buf[0..4], new_text_section_start);
|
||||
try self.base.file.?.pwriteAll(buf[0..4], self.section_table_offset + 40 + 20);
|
||||
|
||||
const current_virtual_size = std.mem.alignForwardGeneric(u32, self.offset_table_size, section_alignment);
|
||||
const new_virtual_size = std.mem.alignForwardGeneric(u32, new_raw_size, section_alignment);
|
||||
const current_virtual_size = mem.alignForwardGeneric(u32, self.offset_table_size, section_alignment);
|
||||
const new_virtual_size = mem.alignForwardGeneric(u32, new_raw_size, section_alignment);
|
||||
// If we had to move in the virtual address space, we need to fix the VAs in the offset table, as well as the virtual address of the `.text` section
|
||||
// and the virutal size of the `.got` section
|
||||
|
||||
@ -592,12 +596,12 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void {
|
||||
const va_offset = new_virtual_size - current_virtual_size;
|
||||
|
||||
// Write .got virtual size
|
||||
std.mem.writeIntLittle(u32, buf[0..4], new_virtual_size);
|
||||
mem.writeIntLittle(u32, buf[0..4], new_virtual_size);
|
||||
try self.base.file.?.pwriteAll(buf[0..4], self.section_table_offset + 8);
|
||||
|
||||
// Write .text new virtual address
|
||||
self.text_section_virtual_address = self.text_section_virtual_address + va_offset;
|
||||
std.mem.writeIntLittle(u32, buf[0..4], self.text_section_virtual_address - image_base);
|
||||
mem.writeIntLittle(u32, buf[0..4], self.text_section_virtual_address - image_base);
|
||||
try self.base.file.?.pwriteAll(buf[0..4], self.section_table_offset + 40 + 12);
|
||||
|
||||
// Fix the VAs in the offset table
|
||||
@ -607,11 +611,11 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void {
|
||||
|
||||
switch (entry_size) {
|
||||
4 => {
|
||||
std.mem.writeInt(u32, buf[0..4], @intCast(u32, va.*), endian);
|
||||
mem.writeInt(u32, buf[0..4], @intCast(u32, va.*), endian);
|
||||
try self.base.file.?.pwriteAll(buf[0..4], offset_table_start + idx * entry_size);
|
||||
},
|
||||
8 => {
|
||||
std.mem.writeInt(u64, &buf, va.*, endian);
|
||||
mem.writeInt(u64, &buf, va.*, endian);
|
||||
try self.base.file.?.pwriteAll(&buf, offset_table_start + idx * entry_size);
|
||||
},
|
||||
else => unreachable,
|
||||
@ -626,12 +630,12 @@ fn writeOffsetTableEntry(self: *Coff, index: usize) !void {
|
||||
switch (entry_size) {
|
||||
4 => {
|
||||
var buf: [4]u8 = undefined;
|
||||
std.mem.writeInt(u32, &buf, @intCast(u32, self.offset_table.items[index]), endian);
|
||||
mem.writeInt(u32, &buf, @intCast(u32, self.offset_table.items[index]), endian);
|
||||
try self.base.file.?.pwriteAll(&buf, offset_table_start + index * entry_size);
|
||||
},
|
||||
8 => {
|
||||
var buf: [8]u8 = undefined;
|
||||
std.mem.writeInt(u64, &buf, self.offset_table.items[index], endian);
|
||||
mem.writeInt(u64, &buf, self.offset_table.items[index], endian);
|
||||
try self.base.file.?.pwriteAll(&buf, offset_table_start + index * entry_size);
|
||||
},
|
||||
else => unreachable,
|
||||
@ -664,7 +668,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
|
||||
if (curr_size != 0) {
|
||||
const capacity = decl.link.coff.capacity();
|
||||
const need_realloc = code.len > capacity or
|
||||
!std.mem.isAlignedGeneric(u32, decl.link.coff.text_offset, required_alignment);
|
||||
!mem.isAlignedGeneric(u32, decl.link.coff.text_offset, required_alignment);
|
||||
if (need_realloc) {
|
||||
const curr_vaddr = self.getDeclVAddr(decl);
|
||||
const vaddr = try self.growTextBlock(&decl.link.coff, code.len, required_alignment);
|
||||
@ -679,7 +683,7 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
|
||||
}
|
||||
} else {
|
||||
const vaddr = try self.allocateTextBlock(&decl.link.coff, code.len, required_alignment);
|
||||
log.debug("allocated text block for {} at 0x{x} (size: {Bi})\n", .{ std.mem.spanZ(decl.name), vaddr, code.len });
|
||||
log.debug("allocated text block for {} at 0x{x} (size: {Bi})\n", .{ mem.spanZ(decl.name), vaddr, code.len });
|
||||
errdefer self.freeTextBlock(&decl.link.coff);
|
||||
self.offset_table.items[decl.link.coff.offset_table_index] = vaddr;
|
||||
try self.writeOffsetTableEntry(decl.link.coff.offset_table_index);
|
||||
@ -702,7 +706,7 @@ pub fn freeDecl(self: *Coff, decl: *Module.Decl) void {
|
||||
pub fn updateDeclExports(self: *Coff, module: *Module, decl: *const Module.Decl, exports: []const *Module.Export) !void {
|
||||
for (exports) |exp| {
|
||||
if (exp.options.section) |section_name| {
|
||||
if (!std.mem.eql(u8, section_name, ".text")) {
|
||||
if (!mem.eql(u8, section_name, ".text")) {
|
||||
try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);
|
||||
module.failed_exports.putAssumeCapacityNoClobber(
|
||||
exp,
|
||||
@ -711,7 +715,7 @@ pub fn updateDeclExports(self: *Coff, module: *Module, decl: *const Module.Decl,
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (std.mem.eql(u8, exp.options.name, "_start")) {
|
||||
if (mem.eql(u8, exp.options.name, "_start")) {
|
||||
self.entry_addr = decl.link.coff.getVAddr(self.*) - image_base;
|
||||
} else {
|
||||
try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);
|
||||
@ -726,8 +730,12 @@ pub fn updateDeclExports(self: *Coff, module: *Module, decl: *const Module.Decl,
|
||||
|
||||
pub fn flush(self: *Coff, comp: *Compilation) !void {
|
||||
if (build_options.have_llvm and self.base.options.use_lld) {
|
||||
return error.CoffLinkingWithLLDUnimplemented;
|
||||
return self.linkWithLLD(comp);
|
||||
} else {
|
||||
switch (self.base.options.effectiveOutputMode()) {
|
||||
.Exe, .Obj => {},
|
||||
.Lib => return error.TODOImplementWritingLibFiles,
|
||||
}
|
||||
return self.flushModule(comp);
|
||||
}
|
||||
}
|
||||
@ -739,16 +747,16 @@ pub fn flushModule(self: *Coff, comp: *Compilation) !void {
|
||||
if (self.text_section_size_dirty) {
|
||||
// Write the new raw size in the .text header
|
||||
var buf: [4]u8 = undefined;
|
||||
std.mem.writeIntLittle(u32, &buf, self.text_section_size);
|
||||
mem.writeIntLittle(u32, &buf, self.text_section_size);
|
||||
try self.base.file.?.pwriteAll(&buf, self.section_table_offset + 40 + 16);
|
||||
try self.base.file.?.setEndPos(self.section_data_offset + self.offset_table_size + self.text_section_size);
|
||||
self.text_section_size_dirty = false;
|
||||
}
|
||||
|
||||
if (self.base.options.output_mode == .Exe and self.size_of_image_dirty) {
|
||||
const new_size_of_image = std.mem.alignForwardGeneric(u32, self.text_section_virtual_address - image_base + self.text_section_size, section_alignment);
|
||||
const new_size_of_image = mem.alignForwardGeneric(u32, self.text_section_virtual_address - image_base + self.text_section_size, section_alignment);
|
||||
var buf: [4]u8 = undefined;
|
||||
std.mem.writeIntLittle(u32, &buf, new_size_of_image);
|
||||
mem.writeIntLittle(u32, &buf, new_size_of_image);
|
||||
try self.base.file.?.pwriteAll(&buf, self.optional_header_offset + 56);
|
||||
self.size_of_image_dirty = false;
|
||||
}
|
||||
@ -763,12 +771,422 @@ pub fn flushModule(self: *Coff, comp: *Compilation) !void {
|
||||
if (self.base.options.output_mode == .Exe) {
|
||||
// Write AddressOfEntryPoint
|
||||
var buf: [4]u8 = undefined;
|
||||
std.mem.writeIntLittle(u32, &buf, self.entry_addr.?);
|
||||
mem.writeIntLittle(u32, &buf, self.entry_addr.?);
|
||||
try self.base.file.?.pwriteAll(&buf, self.optional_header_offset + 16);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn linkWithLLD(self: *Coff, comp: *Compilation) !void {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator);
|
||||
defer arena_allocator.deinit();
|
||||
const arena = &arena_allocator.allocator;
|
||||
|
||||
const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type.
|
||||
|
||||
// If there is no Zig code to compile, then we should skip flushing the output file because it
|
||||
// will not be part of the linker line anyway.
|
||||
const module_obj_path: ?[]const u8 = if (self.base.options.module) |module| blk: {
|
||||
const use_stage1 = build_options.is_stage1 and self.base.options.use_llvm;
|
||||
if (use_stage1) {
|
||||
const obj_basename = try std.zig.binNameAlloc(arena, .{
|
||||
.root_name = self.base.options.root_name,
|
||||
.target = self.base.options.target,
|
||||
.output_mode = .Obj,
|
||||
});
|
||||
const o_directory = self.base.options.module.?.zig_cache_artifact_directory;
|
||||
const full_obj_path = try o_directory.join(arena, &[_][]const u8{obj_basename});
|
||||
break :blk full_obj_path;
|
||||
}
|
||||
|
||||
try self.flushModule(comp);
|
||||
const obj_basename = self.base.intermediary_basename.?;
|
||||
const full_obj_path = try directory.join(arena, &[_][]const u8{obj_basename});
|
||||
break :blk full_obj_path;
|
||||
} else null;
|
||||
|
||||
const is_lib = self.base.options.output_mode == .Lib;
|
||||
const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib;
|
||||
const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe;
|
||||
const link_in_crt = self.base.options.link_libc and self.base.options.output_mode == .Exe;
|
||||
const target = self.base.options.target;
|
||||
|
||||
// See link/Elf.zig for comments on how this mechanism works.
|
||||
const id_symlink_basename = "lld.id";
|
||||
|
||||
var man: Cache.Manifest = undefined;
|
||||
defer if (!self.base.options.disable_lld_caching) man.deinit();
|
||||
|
||||
var digest: [Cache.hex_digest_len]u8 = undefined;
|
||||
|
||||
if (!self.base.options.disable_lld_caching) {
|
||||
man = comp.cache_parent.obtain();
|
||||
self.base.releaseLock();
|
||||
|
||||
try man.addListOfFiles(self.base.options.objects);
|
||||
for (comp.c_object_table.items()) |entry| {
|
||||
_ = try man.addFile(entry.key.status.success.object_path, null);
|
||||
}
|
||||
try man.addOptionalFile(module_obj_path);
|
||||
man.hash.addOptional(self.base.options.stack_size_override);
|
||||
man.hash.addListOfBytes(self.base.options.extra_lld_args);
|
||||
man.hash.addListOfBytes(self.base.options.lib_dirs);
|
||||
man.hash.add(self.base.options.is_compiler_rt_or_libc);
|
||||
if (self.base.options.link_libc) {
|
||||
man.hash.add(self.base.options.libc_installation != null);
|
||||
if (self.base.options.libc_installation) |libc_installation| {
|
||||
man.hash.addBytes(libc_installation.crt_dir.?);
|
||||
if (target.abi == .msvc) {
|
||||
man.hash.addBytes(libc_installation.msvc_lib_dir.?);
|
||||
man.hash.addBytes(libc_installation.kernel32_lib_dir.?);
|
||||
}
|
||||
}
|
||||
}
|
||||
man.hash.addStringSet(self.base.options.system_libs);
|
||||
man.hash.addOptional(self.base.options.subsystem);
|
||||
man.hash.add(self.base.options.is_test);
|
||||
|
||||
// We don't actually care whether it's a cache hit or miss; we just need the digest and the lock.
|
||||
_ = try man.hit();
|
||||
digest = man.final();
|
||||
var prev_digest_buf: [digest.len]u8 = undefined;
|
||||
const prev_digest: []u8 = directory.handle.readLink(id_symlink_basename, &prev_digest_buf) catch |err| blk: {
|
||||
log.debug("COFF LLD new_digest={} readlink error: {}", .{ digest, @errorName(err) });
|
||||
// Handle this as a cache miss.
|
||||
break :blk prev_digest_buf[0..0];
|
||||
};
|
||||
if (mem.eql(u8, prev_digest, &digest)) {
|
||||
log.debug("COFF LLD digest={} match - skipping invocation", .{digest});
|
||||
// Hot diggity dog! The output binary is already there.
|
||||
self.base.lock = man.toOwnedLock();
|
||||
return;
|
||||
}
|
||||
log.debug("COFF LLD prev_digest={} new_digest={}", .{ prev_digest, digest });
|
||||
|
||||
// We are about to change the output file to be different, so we invalidate the build hash now.
|
||||
directory.handle.deleteFile(id_symlink_basename) catch |err| switch (err) {
|
||||
error.FileNotFound => {},
|
||||
else => |e| return e,
|
||||
};
|
||||
}
|
||||
|
||||
const is_obj = self.base.options.output_mode == .Obj;
|
||||
|
||||
// Create an LLD command line and invoke it.
|
||||
var argv = std.ArrayList([]const u8).init(self.base.allocator);
|
||||
defer argv.deinit();
|
||||
// Even though we're calling LLD as a library it thinks the first argument is its own exe name.
|
||||
try argv.append("lld");
|
||||
if (is_obj) {
|
||||
try argv.append("-r");
|
||||
}
|
||||
|
||||
try argv.append("-ERRORLIMIT:0");
|
||||
try argv.append("-NOLOGO");
|
||||
if (!self.base.options.strip) {
|
||||
try argv.append("-DEBUG");
|
||||
}
|
||||
if (self.base.options.output_mode == .Exe) {
|
||||
const stack_size = self.base.options.stack_size_override orelse 16777216;
|
||||
try argv.append(try allocPrint(arena, "-STACK:{d}", .{stack_size}));
|
||||
}
|
||||
|
||||
if (target.cpu.arch == .i386) {
|
||||
try argv.append("-MACHINE:X86");
|
||||
} else if (target.cpu.arch == .x86_64) {
|
||||
try argv.append("-MACHINE:X64");
|
||||
} else if (target.cpu.arch.isARM()) {
|
||||
if (target.cpu.arch.ptrBitWidth() == 32) {
|
||||
try argv.append("-MACHINE:ARM");
|
||||
} else {
|
||||
try argv.append("-MACHINE:ARM64");
|
||||
}
|
||||
}
|
||||
|
||||
if (is_dyn_lib) {
|
||||
try argv.append("-DLL");
|
||||
}
|
||||
|
||||
const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
|
||||
try argv.append(try allocPrint(arena, "-OUT:{s}", .{full_out_path}));
|
||||
|
||||
if (self.base.options.link_libc) {
|
||||
if (self.base.options.libc_installation) |libc_installation| {
|
||||
try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.crt_dir.?}));
|
||||
|
||||
if (target.abi == .msvc) {
|
||||
try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.msvc_lib_dir.?}));
|
||||
try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{libc_installation.kernel32_lib_dir.?}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (self.base.options.lib_dirs) |lib_dir| {
|
||||
try argv.append(try allocPrint(arena, "-LIBPATH:{s}", .{lib_dir}));
|
||||
}
|
||||
|
||||
try argv.appendSlice(self.base.options.objects);
|
||||
|
||||
for (comp.c_object_table.items()) |entry| {
|
||||
try argv.append(entry.key.status.success.object_path);
|
||||
}
|
||||
|
||||
if (module_obj_path) |p| {
|
||||
try argv.append(p);
|
||||
}
|
||||
|
||||
const resolved_subsystem: ?std.Target.SubSystem = blk: {
|
||||
if (self.base.options.subsystem) |explicit| break :blk explicit;
|
||||
switch (target.os.tag) {
|
||||
.windows => {
|
||||
if (self.base.options.module) |module| {
|
||||
if (module.have_dllmain_crt_startup or is_dyn_lib)
|
||||
break :blk null;
|
||||
if (module.have_c_main or self.base.options.is_test or
|
||||
module.have_winmain_crt_startup or module.have_wwinmain_crt_startup)
|
||||
{
|
||||
break :blk .Console;
|
||||
}
|
||||
if (module.have_winmain or module.have_wwinmain)
|
||||
break :blk .Windows;
|
||||
}
|
||||
},
|
||||
.uefi => break :blk .EfiApplication,
|
||||
else => {},
|
||||
}
|
||||
break :blk null;
|
||||
};
|
||||
const Mode = enum { uefi, win32 };
|
||||
const mode: Mode = mode: {
|
||||
if (resolved_subsystem) |subsystem| switch (subsystem) {
|
||||
.Console => {
|
||||
try argv.append("-SUBSYSTEM:console");
|
||||
break :mode .win32;
|
||||
},
|
||||
.EfiApplication => {
|
||||
try argv.append("-SUBSYSTEM:efi_application");
|
||||
break :mode .uefi;
|
||||
},
|
||||
.EfiBootServiceDriver => {
|
||||
try argv.append("-SUBSYSTEM:efi_boot_service_driver");
|
||||
break :mode .uefi;
|
||||
},
|
||||
.EfiRom => {
|
||||
try argv.append("-SUBSYSTEM:efi_rom");
|
||||
break :mode .uefi;
|
||||
},
|
||||
.EfiRuntimeDriver => {
|
||||
try argv.append("-SUBSYSTEM:efi_runtime_driver");
|
||||
break :mode .uefi;
|
||||
},
|
||||
.Native => {
|
||||
try argv.append("-SUBSYSTEM:native");
|
||||
break :mode .win32;
|
||||
},
|
||||
.Posix => {
|
||||
try argv.append("-SUBSYSTEM:posix");
|
||||
break :mode .win32;
|
||||
},
|
||||
.Windows => {
|
||||
try argv.append("-SUBSYSTEM:windows");
|
||||
break :mode .win32;
|
||||
},
|
||||
} else if (target.os.tag == .uefi) {
|
||||
break :mode .uefi;
|
||||
} else {
|
||||
break :mode .win32;
|
||||
}
|
||||
};
|
||||
|
||||
switch (mode) {
|
||||
.uefi => try argv.appendSlice(&[_][]const u8{
|
||||
"-BASE:0",
|
||||
"-ENTRY:EfiMain",
|
||||
"-OPT:REF",
|
||||
"-SAFESEH:NO",
|
||||
"-MERGE:.rdata=.data",
|
||||
"-ALIGN:32",
|
||||
"-NODEFAULTLIB",
|
||||
"-SECTION:.xdata,D",
|
||||
}),
|
||||
.win32 => {
|
||||
if (link_in_crt) {
|
||||
if (target.abi.isGnu()) {
|
||||
try argv.append("-lldmingw");
|
||||
|
||||
if (target.cpu.arch == .i386) {
|
||||
try argv.append("-ALTERNATENAME:__image_base__=___ImageBase");
|
||||
} else {
|
||||
try argv.append("-ALTERNATENAME:__image_base__=__ImageBase");
|
||||
}
|
||||
|
||||
if (is_dyn_lib) {
|
||||
try argv.append(try comp.get_libc_crt_file(arena, "dllcrt2.o"));
|
||||
} else {
|
||||
try argv.append(try comp.get_libc_crt_file(arena, "crt2.o"));
|
||||
}
|
||||
|
||||
try argv.append(try comp.get_libc_crt_file(arena, "mingw32.lib"));
|
||||
try argv.append(try comp.get_libc_crt_file(arena, "mingwex.lib"));
|
||||
try argv.append(try comp.get_libc_crt_file(arena, "msvcrt-os.lib"));
|
||||
|
||||
for (mingw.always_link_libs) |name| {
|
||||
if (!self.base.options.system_libs.contains(name)) {
|
||||
const lib_basename = try allocPrint(arena, "{s}.lib", .{name});
|
||||
try argv.append(try comp.get_libc_crt_file(arena, lib_basename));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const lib_str = switch (self.base.options.link_mode) {
|
||||
.Dynamic => "",
|
||||
.Static => "lib",
|
||||
};
|
||||
const d_str = switch (self.base.options.optimize_mode) {
|
||||
.Debug => "d",
|
||||
else => "",
|
||||
};
|
||||
switch (self.base.options.link_mode) {
|
||||
.Static => try argv.append(try allocPrint(arena, "libcmt{s}.lib", .{d_str})),
|
||||
.Dynamic => try argv.append(try allocPrint(arena, "msvcrt{s}.lib", .{d_str})),
|
||||
}
|
||||
|
||||
try argv.append(try allocPrint(arena, "{s}vcruntime{s}.lib", .{ lib_str, d_str }));
|
||||
try argv.append(try allocPrint(arena, "{s}ucrt{s}.lib", .{ lib_str, d_str }));
|
||||
|
||||
//Visual C++ 2015 Conformance Changes
|
||||
//https://msdn.microsoft.com/en-us/library/bb531344.aspx
|
||||
try argv.append("legacy_stdio_definitions.lib");
|
||||
|
||||
// msvcrt depends on kernel32 and ntdll
|
||||
try argv.append("kernel32.lib");
|
||||
try argv.append("ntdll.lib");
|
||||
}
|
||||
} else {
|
||||
try argv.append("-NODEFAULTLIB");
|
||||
if (!is_lib) {
|
||||
if (self.base.options.module) |module| {
|
||||
if (module.have_winmain) {
|
||||
try argv.append("-ENTRY:WinMain");
|
||||
} else if (module.have_wwinmain) {
|
||||
try argv.append("-ENTRY:wWinMain");
|
||||
} else if (module.have_wwinmain_crt_startup) {
|
||||
try argv.append("-ENTRY:wWinMainCRTStartup");
|
||||
} else {
|
||||
try argv.append("-ENTRY:WinMainCRTStartup");
|
||||
}
|
||||
} else {
|
||||
try argv.append("-ENTRY:WinMainCRTStartup");
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
if (!is_obj) {
|
||||
// libc++ dep
|
||||
if (self.base.options.link_libcpp) {
|
||||
try argv.append(comp.libcxxabi_static_lib.?.full_object_path);
|
||||
try argv.append(comp.libcxx_static_lib.?.full_object_path);
|
||||
try argv.append(comp.libunwind_static_lib.?.full_object_path);
|
||||
}
|
||||
}
|
||||
|
||||
// compiler-rt and libc
|
||||
if (is_exe_or_dyn_lib and !self.base.options.is_compiler_rt_or_libc) {
|
||||
if (!self.base.options.link_libc) {
|
||||
try argv.append(comp.libc_static_lib.?.full_object_path);
|
||||
}
|
||||
// MSVC compiler_rt is missing some stuff, so we build it unconditionally but
|
||||
// and rely on weak linkage to allow MSVC compiler_rt functions to override ours.
|
||||
try argv.append(comp.compiler_rt_static_lib.?.full_object_path);
|
||||
}
|
||||
|
||||
for (self.base.options.system_libs.items()) |entry| {
|
||||
const lib_basename = try allocPrint(arena, "{s}.lib", .{entry.key});
|
||||
if (comp.crt_files.get(lib_basename)) |crt_file| {
|
||||
try argv.append(crt_file.full_object_path);
|
||||
} else {
|
||||
try argv.append(lib_basename);
|
||||
}
|
||||
}
|
||||
|
||||
if (self.base.options.verbose_link) {
|
||||
Compilation.dump_argv(argv.items);
|
||||
}
|
||||
|
||||
const new_argv_with_sentinel = try arena.alloc(?[*:0]const u8, argv.items.len + 1);
|
||||
new_argv_with_sentinel[argv.items.len] = null;
|
||||
const new_argv = new_argv_with_sentinel[0..argv.items.len :null];
|
||||
for (argv.items) |arg, i| {
|
||||
new_argv[i] = try arena.dupeZ(u8, arg);
|
||||
}
|
||||
|
||||
var stderr_context: LLDContext = .{
|
||||
.coff = self,
|
||||
.data = std.ArrayList(u8).init(self.base.allocator),
|
||||
};
|
||||
defer stderr_context.data.deinit();
|
||||
var stdout_context: LLDContext = .{
|
||||
.coff = self,
|
||||
.data = std.ArrayList(u8).init(self.base.allocator),
|
||||
};
|
||||
defer stdout_context.data.deinit();
|
||||
const llvm = @import("../llvm.zig");
|
||||
const ok = llvm.Link(
|
||||
.COFF,
|
||||
new_argv.ptr,
|
||||
new_argv.len,
|
||||
append_diagnostic,
|
||||
@ptrToInt(&stdout_context),
|
||||
@ptrToInt(&stderr_context),
|
||||
);
|
||||
if (stderr_context.oom or stdout_context.oom) return error.OutOfMemory;
|
||||
if (stdout_context.data.items.len != 0) {
|
||||
std.log.warn("unexpected LLD stdout: {}", .{stdout_context.data.items});
|
||||
}
|
||||
if (!ok) {
|
||||
// TODO parse this output and surface with the Compilation API rather than
|
||||
// directly outputting to stderr here.
|
||||
std.debug.print("{}", .{stderr_context.data.items});
|
||||
return error.LLDReportedFailure;
|
||||
}
|
||||
if (stderr_context.data.items.len != 0) {
|
||||
std.log.warn("unexpected LLD stderr: {}", .{stderr_context.data.items});
|
||||
}
|
||||
|
||||
if (!self.base.options.disable_lld_caching) {
|
||||
// Update the dangling symlink with the digest. If it fails we can continue; it only
|
||||
// means that the next invocation will have an unnecessary cache miss.
|
||||
directory.handle.symLink(&digest, id_symlink_basename, .{}) catch |err| {
|
||||
std.log.warn("failed to save linking hash digest symlink: {}", .{@errorName(err)});
|
||||
};
|
||||
// Again failure here only means an unnecessary cache miss.
|
||||
man.writeManifest() catch |err| {
|
||||
std.log.warn("failed to write cache manifest when linking: {}", .{@errorName(err)});
|
||||
};
|
||||
// We hang on to this lock so that the output file path can be used without
|
||||
// other processes clobbering it.
|
||||
self.base.lock = man.toOwnedLock();
|
||||
}
|
||||
}
|
||||
|
||||
const LLDContext = struct {
|
||||
data: std.ArrayList(u8),
|
||||
coff: *Coff,
|
||||
oom: bool = false,
|
||||
};
|
||||
|
||||
fn append_diagnostic(context: usize, ptr: [*]const u8, len: usize) callconv(.C) void {
|
||||
const lld_context = @intToPtr(*LLDContext, context);
|
||||
const msg = ptr[0..len];
|
||||
lld_context.data.appendSlice(msg) catch |err| switch (err) {
|
||||
error.OutOfMemory => lld_context.oom = true,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getDeclVAddr(self: *Coff, decl: *const Module.Decl) u64 {
|
||||
return self.text_section_virtual_address + decl.link.coff.text_offset;
|
||||
}
|
||||
|
||||
@ -1225,7 +1225,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
|
||||
const module_obj_path: ?[]const u8 = if (self.base.options.module) |module| blk: {
|
||||
const use_stage1 = build_options.is_stage1 and self.base.options.use_llvm;
|
||||
if (use_stage1) {
|
||||
const obj_basename = try std.fmt.allocPrint(arena, "{}.o", .{self.base.options.root_name});
|
||||
const obj_basename = try std.zig.binNameAlloc(arena, .{
|
||||
.root_name = self.base.options.root_name,
|
||||
.target = self.base.options.target,
|
||||
.output_mode = .Obj,
|
||||
});
|
||||
const o_directory = self.base.options.module.?.zig_cache_artifact_directory;
|
||||
const full_obj_path = try o_directory.join(arena, &[_][]const u8{obj_basename});
|
||||
break :blk full_obj_path;
|
||||
@ -1242,6 +1246,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
|
||||
const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe;
|
||||
const have_dynamic_linker = self.base.options.link_libc and
|
||||
self.base.options.link_mode == .Dynamic and is_exe_or_dyn_lib;
|
||||
const link_in_crt = self.base.options.link_libc and self.base.options.output_mode == .Exe;
|
||||
const target = self.base.options.target;
|
||||
|
||||
// Here we want to determine whether we can save time by not invoking LLD when the
|
||||
// output is unchanged. None of the linker options or the object files that are being
|
||||
@ -1297,7 +1303,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
|
||||
man.hash.addOptionalBytes(self.base.options.override_soname);
|
||||
man.hash.addOptional(self.base.options.version);
|
||||
}
|
||||
man.hash.addListOfBytes(self.base.options.system_libs);
|
||||
man.hash.addStringSet(self.base.options.system_libs);
|
||||
man.hash.addOptional(self.base.options.allow_shlib_undefined);
|
||||
man.hash.add(self.base.options.bind_global_refs_locally);
|
||||
|
||||
@ -1326,7 +1332,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
|
||||
};
|
||||
}
|
||||
|
||||
const target = self.base.options.target;
|
||||
const is_obj = self.base.options.output_mode == .Obj;
|
||||
|
||||
// Create an LLD command line and invoke it.
|
||||
@ -1337,7 +1342,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
|
||||
if (is_obj) {
|
||||
try argv.append("-r");
|
||||
}
|
||||
const link_in_crt = self.base.options.link_libc and self.base.options.output_mode == .Exe;
|
||||
|
||||
try argv.append("-error-limit=0");
|
||||
|
||||
@ -1440,7 +1444,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
|
||||
var test_path = std.ArrayList(u8).init(self.base.allocator);
|
||||
defer test_path.deinit();
|
||||
for (self.base.options.lib_dirs) |lib_dir_path| {
|
||||
for (self.base.options.system_libs) |link_lib| {
|
||||
for (self.base.options.system_libs.items()) |link_lib| {
|
||||
test_path.shrinkRetainingCapacity(0);
|
||||
const sep = fs.path.sep_str;
|
||||
try test_path.writer().print("{}" ++ sep ++ "lib{}.so", .{ lib_dir_path, link_lib });
|
||||
@ -1509,8 +1513,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
|
||||
}
|
||||
|
||||
// Shared libraries.
|
||||
try argv.ensureCapacity(argv.items.len + self.base.options.system_libs.len);
|
||||
for (self.base.options.system_libs) |link_lib| {
|
||||
const system_libs = self.base.options.system_libs.items();
|
||||
try argv.ensureCapacity(argv.items.len + system_libs.len);
|
||||
for (system_libs) |entry| {
|
||||
const link_lib = entry.key;
|
||||
// By this time, we depend on these libs being dynamically linked libraries and not static libraries
|
||||
// (the check for that needs to be earlier), but they could be full paths to .so files, in which
|
||||
// case we want to avoid prepending "-l".
|
||||
@ -1581,10 +1587,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
|
||||
}
|
||||
|
||||
if (self.base.options.verbose_link) {
|
||||
for (argv.items[0 .. argv.items.len - 1]) |arg| {
|
||||
std.debug.print("{} ", .{arg});
|
||||
}
|
||||
std.debug.print("{}\n", .{argv.items[argv.items.len - 1]});
|
||||
Compilation.dump_argv(argv.items);
|
||||
}
|
||||
|
||||
// Oh, snapplesauce! We need null terminated argv.
|
||||
|
||||
866
src/mingw.zig
Normal file
866
src/mingw.zig
Normal file
@ -0,0 +1,866 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const mem = std.mem;
|
||||
const path = std.fs.path;
|
||||
const assert = std.debug.assert;
|
||||
|
||||
const target_util = @import("target.zig");
|
||||
const Compilation = @import("Compilation.zig");
|
||||
const build_options = @import("build_options");
|
||||
|
||||
pub const CRTFile = enum {
|
||||
crt2_o,
|
||||
dllcrt2_o,
|
||||
mingw32_lib,
|
||||
msvcrt_os_lib,
|
||||
mingwex_lib,
|
||||
uuid_lib,
|
||||
};
|
||||
|
||||
pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
|
||||
if (!build_options.have_llvm) {
|
||||
return error.ZigCompilerNotBuiltWithLLVMExtensions;
|
||||
}
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
|
||||
defer arena_allocator.deinit();
|
||||
const arena = &arena_allocator.allocator;
|
||||
|
||||
switch (crt_file) {
|
||||
.crt2_o => {
|
||||
var args = std.ArrayList([]const u8).init(arena);
|
||||
try add_cc_args(comp, arena, &args);
|
||||
try args.appendSlice(&[_][]const u8{
|
||||
"-U__CRTDLL__",
|
||||
"-D__MSVCRT__",
|
||||
// Uncomment these 3 things for crtu
|
||||
//"-DUNICODE",
|
||||
//"-D_UNICODE",
|
||||
//"-DWPRFLAG=1",
|
||||
});
|
||||
return comp.build_crt_file("crt2", .Obj, &[1]Compilation.CSourceFile{
|
||||
.{
|
||||
.src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
|
||||
"libc", "mingw", "crt", "crtexe.c",
|
||||
}),
|
||||
.extra_flags = args.items,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
.dllcrt2_o => {
|
||||
var args = std.ArrayList([]const u8).init(arena);
|
||||
try add_cc_args(comp, arena, &args);
|
||||
try args.appendSlice(&[_][]const u8{
|
||||
"-U__CRTDLL__",
|
||||
"-D__MSVCRT__",
|
||||
});
|
||||
return comp.build_crt_file("dllcrt2", .Obj, &[1]Compilation.CSourceFile{
|
||||
.{
|
||||
.src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
|
||||
"libc", "mingw", "crt", "crtdll.c",
|
||||
}),
|
||||
.extra_flags = args.items,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
.mingw32_lib => {
|
||||
var c_source_files: [mingw32_lib_deps.len]Compilation.CSourceFile = undefined;
|
||||
for (mingw32_lib_deps) |dep, i| {
|
||||
var args = std.ArrayList([]const u8).init(arena);
|
||||
try args.appendSlice(&[_][]const u8{
|
||||
"-DHAVE_CONFIG_H",
|
||||
"-D_SYSCRT=1",
|
||||
"-DCRTDLL=1",
|
||||
|
||||
"-isystem",
|
||||
try comp.zig_lib_directory.join(arena, &[_][]const u8{
|
||||
"libc", "include", "any-windows-any",
|
||||
}),
|
||||
|
||||
"-isystem",
|
||||
try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw", "include" }),
|
||||
|
||||
"-std=gnu99",
|
||||
"-D_CRTBLD",
|
||||
"-D_WIN32_WINNT=0x0f00",
|
||||
"-D__MSVCRT_VERSION__=0x700",
|
||||
"-g",
|
||||
"-O2",
|
||||
});
|
||||
c_source_files[i] = .{
|
||||
.src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
|
||||
"libc", "mingw", "crt", dep,
|
||||
}),
|
||||
.extra_flags = args.items,
|
||||
};
|
||||
}
|
||||
return comp.build_crt_file("mingw32", .Lib, &c_source_files);
|
||||
},
|
||||
|
||||
.msvcrt_os_lib => {
|
||||
const extra_flags = try arena.dupe([]const u8, &[_][]const u8{
|
||||
"-DHAVE_CONFIG_H",
|
||||
"-D__LIBMSVCRT__",
|
||||
|
||||
"-I",
|
||||
try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw", "include" }),
|
||||
|
||||
"-std=gnu99",
|
||||
"-D_CRTBLD",
|
||||
"-D_WIN32_WINNT=0x0f00",
|
||||
"-D__MSVCRT_VERSION__=0x700",
|
||||
|
||||
"-isystem",
|
||||
try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "include", "any-windows-any" }),
|
||||
|
||||
"-g",
|
||||
"-O2",
|
||||
});
|
||||
var c_source_files = std.ArrayList(Compilation.CSourceFile).init(arena);
|
||||
|
||||
for (msvcrt_common_src) |dep| {
|
||||
(try c_source_files.addOne()).* = .{
|
||||
.src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw", dep }),
|
||||
.extra_flags = extra_flags,
|
||||
};
|
||||
}
|
||||
if (comp.getTarget().cpu.arch == .i386) {
|
||||
for (msvcrt_i386_src) |dep| {
|
||||
(try c_source_files.addOne()).* = .{
|
||||
.src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
|
||||
"libc", "mingw", dep,
|
||||
}),
|
||||
.extra_flags = extra_flags,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
for (msvcrt_other_src) |dep| {
|
||||
(try c_source_files.addOne()).* = .{
|
||||
.src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
|
||||
"libc", "mingw", dep,
|
||||
}),
|
||||
.extra_flags = extra_flags,
|
||||
};
|
||||
}
|
||||
}
|
||||
return comp.build_crt_file("msvcrt-os", .Lib, c_source_files.items);
|
||||
},
|
||||
|
||||
.mingwex_lib => {
|
||||
const extra_flags = try arena.dupe([]const u8, &[_][]const u8{
|
||||
"-DHAVE_CONFIG_H",
|
||||
|
||||
"-I",
|
||||
try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw" }),
|
||||
|
||||
"-I",
|
||||
try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw", "include" }),
|
||||
|
||||
"-std=gnu99",
|
||||
"-D_CRTBLD",
|
||||
"-D_WIN32_WINNT=0x0f00",
|
||||
"-D__MSVCRT_VERSION__=0x700",
|
||||
"-g",
|
||||
"-O2",
|
||||
|
||||
"-isystem",
|
||||
try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "include", "any-windows-any" }),
|
||||
});
|
||||
var c_source_files = std.ArrayList(Compilation.CSourceFile).init(arena);
|
||||
|
||||
for (mingwex_generic_src) |dep| {
|
||||
(try c_source_files.addOne()).* = .{
|
||||
.src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
|
||||
"libc", "mingw", dep,
|
||||
}),
|
||||
.extra_flags = extra_flags,
|
||||
};
|
||||
}
|
||||
const target = comp.getTarget();
|
||||
if (target.cpu.arch == .i386 or target.cpu.arch == .x86_64) {
|
||||
for (mingwex_x86_src) |dep| {
|
||||
(try c_source_files.addOne()).* = .{
|
||||
.src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
|
||||
"libc", "mingw", dep,
|
||||
}),
|
||||
.extra_flags = extra_flags,
|
||||
};
|
||||
}
|
||||
} else if (target.cpu.arch.isARM()) {
|
||||
if (target.cpu.arch.ptrBitWidth() == 32) {
|
||||
for (mingwex_arm32_src) |dep| {
|
||||
(try c_source_files.addOne()).* = .{
|
||||
.src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
|
||||
"libc", "mingw", dep,
|
||||
}),
|
||||
.extra_flags = extra_flags,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
for (mingwex_arm64_src) |dep| {
|
||||
(try c_source_files.addOne()).* = .{
|
||||
.src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
|
||||
"libc", "mingw", dep,
|
||||
}),
|
||||
.extra_flags = extra_flags,
|
||||
};
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unreachable;
|
||||
}
|
||||
return comp.build_crt_file("mingwex", .Lib, c_source_files.items);
|
||||
},
|
||||
|
||||
.uuid_lib => {
|
||||
const extra_flags = try arena.dupe([]const u8, &[_][]const u8{
|
||||
"-DHAVE_CONFIG_H",
|
||||
|
||||
"-I",
|
||||
try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw" }),
|
||||
|
||||
"-I",
|
||||
try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw", "include" }),
|
||||
|
||||
"-std=gnu99",
|
||||
"-D_CRTBLD",
|
||||
"-D_WIN32_WINNT=0x0f00",
|
||||
"-D__MSVCRT_VERSION__=0x700",
|
||||
"-g",
|
||||
"-O2",
|
||||
|
||||
"-isystem",
|
||||
try comp.zig_lib_directory.join(arena, &[_][]const u8{
|
||||
"libc", "include", "any-windows-any",
|
||||
}),
|
||||
});
|
||||
var c_source_files: [uuid_src.len]Compilation.CSourceFile = undefined;
|
||||
for (uuid_src) |dep, i| {
|
||||
c_source_files[i] = .{
|
||||
.src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
|
||||
"libc", "mingw", "libsrc", dep,
|
||||
}),
|
||||
.extra_flags = extra_flags,
|
||||
};
|
||||
}
|
||||
return comp.build_crt_file("uuid", .Lib, &c_source_files);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn add_cc_args(
|
||||
comp: *Compilation,
|
||||
arena: *Allocator,
|
||||
args: *std.ArrayList([]const u8),
|
||||
) error{OutOfMemory}!void {
|
||||
try args.appendSlice(&[_][]const u8{
|
||||
"-DHAVE_CONFIG_H",
|
||||
|
||||
"-I",
|
||||
try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "mingw", "include" }),
|
||||
|
||||
"-isystem",
|
||||
try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "include", "any-windows-any" }),
|
||||
});
|
||||
|
||||
const target = comp.getTarget();
|
||||
if (target.cpu.arch.isARM() and target.cpu.arch.ptrBitWidth() == 32) {
|
||||
try args.append("-mfpu=vfp");
|
||||
}
|
||||
|
||||
try args.appendSlice(&[_][]const u8{
|
||||
"-std=gnu11",
|
||||
"-D_CRTBLD",
|
||||
"-D_WIN32_WINNT=0x0f00",
|
||||
"-D__MSVCRT_VERSION__=0x700",
|
||||
});
|
||||
}
|
||||
|
||||
const mingw32_lib_deps = [_][]const u8{
|
||||
"crt0_c.c",
|
||||
"dll_argv.c",
|
||||
"gccmain.c",
|
||||
"natstart.c",
|
||||
"pseudo-reloc-list.c",
|
||||
"wildcard.c",
|
||||
"charmax.c",
|
||||
"crt0_w.c",
|
||||
"dllargv.c",
|
||||
"gs_support.c",
|
||||
"_newmode.c",
|
||||
"tlssup.c",
|
||||
"xncommod.c",
|
||||
"cinitexe.c",
|
||||
"merr.c",
|
||||
"usermatherr.c",
|
||||
"pesect.c",
|
||||
"udllargc.c",
|
||||
"xthdloc.c",
|
||||
"CRT_fp10.c",
|
||||
"mingw_helpers.c",
|
||||
"pseudo-reloc.c",
|
||||
"udll_argv.c",
|
||||
"xtxtmode.c",
|
||||
"crt_handler.c",
|
||||
"tlsthrd.c",
|
||||
"tlsmthread.c",
|
||||
"tlsmcrt.c",
|
||||
"cxa_atexit.c",
|
||||
};
|
||||
const msvcrt_common_src = [_][]const u8{
|
||||
"misc" ++ path.sep_str ++ "_create_locale.c",
|
||||
"misc" ++ path.sep_str ++ "_free_locale.c",
|
||||
"misc" ++ path.sep_str ++ "onexit_table.c",
|
||||
"misc" ++ path.sep_str ++ "register_tls_atexit.c",
|
||||
"stdio" ++ path.sep_str ++ "acrt_iob_func.c",
|
||||
"misc" ++ path.sep_str ++ "_configthreadlocale.c",
|
||||
"misc" ++ path.sep_str ++ "_get_current_locale.c",
|
||||
"misc" ++ path.sep_str ++ "invalid_parameter_handler.c",
|
||||
"misc" ++ path.sep_str ++ "output_format.c",
|
||||
"misc" ++ path.sep_str ++ "purecall.c",
|
||||
"secapi" ++ path.sep_str ++ "_access_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_cgets_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_cgetws_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_chsize_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_controlfp_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_cprintf_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_cprintf_s_l.c",
|
||||
"secapi" ++ path.sep_str ++ "_ctime32_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_ctime64_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_cwprintf_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_cwprintf_s_l.c",
|
||||
"secapi" ++ path.sep_str ++ "_gmtime32_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_gmtime64_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_localtime32_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_localtime64_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_mktemp_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_sopen_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_strdate_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_strtime_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_umask_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_vcprintf_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_vcprintf_s_l.c",
|
||||
"secapi" ++ path.sep_str ++ "_vcwprintf_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_vcwprintf_s_l.c",
|
||||
"secapi" ++ path.sep_str ++ "_vscprintf_p.c",
|
||||
"secapi" ++ path.sep_str ++ "_vscwprintf_p.c",
|
||||
"secapi" ++ path.sep_str ++ "_vswprintf_p.c",
|
||||
"secapi" ++ path.sep_str ++ "_waccess_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_wasctime_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_wctime32_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_wctime64_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_wstrtime_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_wmktemp_s.c",
|
||||
"secapi" ++ path.sep_str ++ "_wstrdate_s.c",
|
||||
"secapi" ++ path.sep_str ++ "asctime_s.c",
|
||||
"secapi" ++ path.sep_str ++ "memcpy_s.c",
|
||||
"secapi" ++ path.sep_str ++ "memmove_s.c",
|
||||
"secapi" ++ path.sep_str ++ "rand_s.c",
|
||||
"secapi" ++ path.sep_str ++ "sprintf_s.c",
|
||||
"secapi" ++ path.sep_str ++ "strerror_s.c",
|
||||
"secapi" ++ path.sep_str ++ "vsprintf_s.c",
|
||||
"secapi" ++ path.sep_str ++ "wmemcpy_s.c",
|
||||
"secapi" ++ path.sep_str ++ "wmemmove_s.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_lock.c",
|
||||
};
|
||||
const msvcrt_i386_src = [_][]const u8{
|
||||
"misc" ++ path.sep_str ++ "lc_locale_func.c",
|
||||
"misc" ++ path.sep_str ++ "___mb_cur_max_func.c",
|
||||
};
|
||||
|
||||
const msvcrt_other_src = [_][]const u8{
|
||||
"misc" ++ path.sep_str ++ "__p___argv.c",
|
||||
"misc" ++ path.sep_str ++ "__p__acmdln.c",
|
||||
"misc" ++ path.sep_str ++ "__p__fmode.c",
|
||||
"misc" ++ path.sep_str ++ "__p__wcmdln.c",
|
||||
};
|
||||
const mingwex_generic_src = [_][]const u8{
|
||||
"complex" ++ path.sep_str ++ "_cabs.c",
|
||||
"complex" ++ path.sep_str ++ "cabs.c",
|
||||
"complex" ++ path.sep_str ++ "cabsf.c",
|
||||
"complex" ++ path.sep_str ++ "cabsl.c",
|
||||
"complex" ++ path.sep_str ++ "cacos.c",
|
||||
"complex" ++ path.sep_str ++ "cacosf.c",
|
||||
"complex" ++ path.sep_str ++ "cacosl.c",
|
||||
"complex" ++ path.sep_str ++ "carg.c",
|
||||
"complex" ++ path.sep_str ++ "cargf.c",
|
||||
"complex" ++ path.sep_str ++ "cargl.c",
|
||||
"complex" ++ path.sep_str ++ "casin.c",
|
||||
"complex" ++ path.sep_str ++ "casinf.c",
|
||||
"complex" ++ path.sep_str ++ "casinl.c",
|
||||
"complex" ++ path.sep_str ++ "catan.c",
|
||||
"complex" ++ path.sep_str ++ "catanf.c",
|
||||
"complex" ++ path.sep_str ++ "catanl.c",
|
||||
"complex" ++ path.sep_str ++ "ccos.c",
|
||||
"complex" ++ path.sep_str ++ "ccosf.c",
|
||||
"complex" ++ path.sep_str ++ "ccosl.c",
|
||||
"complex" ++ path.sep_str ++ "cexp.c",
|
||||
"complex" ++ path.sep_str ++ "cexpf.c",
|
||||
"complex" ++ path.sep_str ++ "cexpl.c",
|
||||
"complex" ++ path.sep_str ++ "cimag.c",
|
||||
"complex" ++ path.sep_str ++ "cimagf.c",
|
||||
"complex" ++ path.sep_str ++ "cimagl.c",
|
||||
"complex" ++ path.sep_str ++ "clog.c",
|
||||
"complex" ++ path.sep_str ++ "clog10.c",
|
||||
"complex" ++ path.sep_str ++ "clog10f.c",
|
||||
"complex" ++ path.sep_str ++ "clog10l.c",
|
||||
"complex" ++ path.sep_str ++ "clogf.c",
|
||||
"complex" ++ path.sep_str ++ "clogl.c",
|
||||
"complex" ++ path.sep_str ++ "conj.c",
|
||||
"complex" ++ path.sep_str ++ "conjf.c",
|
||||
"complex" ++ path.sep_str ++ "conjl.c",
|
||||
"complex" ++ path.sep_str ++ "cpow.c",
|
||||
"complex" ++ path.sep_str ++ "cpowf.c",
|
||||
"complex" ++ path.sep_str ++ "cpowl.c",
|
||||
"complex" ++ path.sep_str ++ "cproj.c",
|
||||
"complex" ++ path.sep_str ++ "cprojf.c",
|
||||
"complex" ++ path.sep_str ++ "cprojl.c",
|
||||
"complex" ++ path.sep_str ++ "creal.c",
|
||||
"complex" ++ path.sep_str ++ "crealf.c",
|
||||
"complex" ++ path.sep_str ++ "creall.c",
|
||||
"complex" ++ path.sep_str ++ "csin.c",
|
||||
"complex" ++ path.sep_str ++ "csinf.c",
|
||||
"complex" ++ path.sep_str ++ "csinl.c",
|
||||
"complex" ++ path.sep_str ++ "csqrt.c",
|
||||
"complex" ++ path.sep_str ++ "csqrtf.c",
|
||||
"complex" ++ path.sep_str ++ "csqrtl.c",
|
||||
"complex" ++ path.sep_str ++ "ctan.c",
|
||||
"complex" ++ path.sep_str ++ "ctanf.c",
|
||||
"complex" ++ path.sep_str ++ "ctanl.c",
|
||||
"crt" ++ path.sep_str ++ "dllentry.c",
|
||||
"crt" ++ path.sep_str ++ "dllmain.c",
|
||||
"gdtoa" ++ path.sep_str ++ "arithchk.c",
|
||||
"gdtoa" ++ path.sep_str ++ "dmisc.c",
|
||||
"gdtoa" ++ path.sep_str ++ "dtoa.c",
|
||||
"gdtoa" ++ path.sep_str ++ "g__fmt.c",
|
||||
"gdtoa" ++ path.sep_str ++ "g_dfmt.c",
|
||||
"gdtoa" ++ path.sep_str ++ "g_ffmt.c",
|
||||
"gdtoa" ++ path.sep_str ++ "g_xfmt.c",
|
||||
"gdtoa" ++ path.sep_str ++ "gdtoa.c",
|
||||
"gdtoa" ++ path.sep_str ++ "gethex.c",
|
||||
"gdtoa" ++ path.sep_str ++ "gmisc.c",
|
||||
"gdtoa" ++ path.sep_str ++ "hd_init.c",
|
||||
"gdtoa" ++ path.sep_str ++ "hexnan.c",
|
||||
"gdtoa" ++ path.sep_str ++ "misc.c",
|
||||
"gdtoa" ++ path.sep_str ++ "qnan.c",
|
||||
"gdtoa" ++ path.sep_str ++ "smisc.c",
|
||||
"gdtoa" ++ path.sep_str ++ "strtodg.c",
|
||||
"gdtoa" ++ path.sep_str ++ "strtodnrp.c",
|
||||
"gdtoa" ++ path.sep_str ++ "strtof.c",
|
||||
"gdtoa" ++ path.sep_str ++ "strtopx.c",
|
||||
"gdtoa" ++ path.sep_str ++ "sum.c",
|
||||
"gdtoa" ++ path.sep_str ++ "ulp.c",
|
||||
"math" ++ path.sep_str ++ "abs64.c",
|
||||
"math" ++ path.sep_str ++ "cbrt.c",
|
||||
"math" ++ path.sep_str ++ "cbrtf.c",
|
||||
"math" ++ path.sep_str ++ "cbrtl.c",
|
||||
"math" ++ path.sep_str ++ "cephes_emath.c",
|
||||
"math" ++ path.sep_str ++ "copysign.c",
|
||||
"math" ++ path.sep_str ++ "copysignf.c",
|
||||
"math" ++ path.sep_str ++ "coshf.c",
|
||||
"math" ++ path.sep_str ++ "coshl.c",
|
||||
"math" ++ path.sep_str ++ "erfl.c",
|
||||
"math" ++ path.sep_str ++ "expf.c",
|
||||
"math" ++ path.sep_str ++ "fabs.c",
|
||||
"math" ++ path.sep_str ++ "fabsf.c",
|
||||
"math" ++ path.sep_str ++ "fabsl.c",
|
||||
"math" ++ path.sep_str ++ "fdim.c",
|
||||
"math" ++ path.sep_str ++ "fdimf.c",
|
||||
"math" ++ path.sep_str ++ "fdiml.c",
|
||||
"math" ++ path.sep_str ++ "fma.c",
|
||||
"math" ++ path.sep_str ++ "fmaf.c",
|
||||
"math" ++ path.sep_str ++ "fmal.c",
|
||||
"math" ++ path.sep_str ++ "fmax.c",
|
||||
"math" ++ path.sep_str ++ "fmaxf.c",
|
||||
"math" ++ path.sep_str ++ "fmaxl.c",
|
||||
"math" ++ path.sep_str ++ "fmin.c",
|
||||
"math" ++ path.sep_str ++ "fminf.c",
|
||||
"math" ++ path.sep_str ++ "fminl.c",
|
||||
"math" ++ path.sep_str ++ "fp_consts.c",
|
||||
"math" ++ path.sep_str ++ "fp_constsf.c",
|
||||
"math" ++ path.sep_str ++ "fp_constsl.c",
|
||||
"math" ++ path.sep_str ++ "fpclassify.c",
|
||||
"math" ++ path.sep_str ++ "fpclassifyf.c",
|
||||
"math" ++ path.sep_str ++ "fpclassifyl.c",
|
||||
"math" ++ path.sep_str ++ "frexpf.c",
|
||||
"math" ++ path.sep_str ++ "hypot.c",
|
||||
"math" ++ path.sep_str ++ "hypotf.c",
|
||||
"math" ++ path.sep_str ++ "hypotl.c",
|
||||
"math" ++ path.sep_str ++ "isnan.c",
|
||||
"math" ++ path.sep_str ++ "isnanf.c",
|
||||
"math" ++ path.sep_str ++ "isnanl.c",
|
||||
"math" ++ path.sep_str ++ "ldexpf.c",
|
||||
"math" ++ path.sep_str ++ "lgamma.c",
|
||||
"math" ++ path.sep_str ++ "lgammaf.c",
|
||||
"math" ++ path.sep_str ++ "lgammal.c",
|
||||
"math" ++ path.sep_str ++ "llrint.c",
|
||||
"math" ++ path.sep_str ++ "llrintf.c",
|
||||
"math" ++ path.sep_str ++ "llrintl.c",
|
||||
"math" ++ path.sep_str ++ "llround.c",
|
||||
"math" ++ path.sep_str ++ "llroundf.c",
|
||||
"math" ++ path.sep_str ++ "llroundl.c",
|
||||
"math" ++ path.sep_str ++ "log10f.c",
|
||||
"math" ++ path.sep_str ++ "logf.c",
|
||||
"math" ++ path.sep_str ++ "lrint.c",
|
||||
"math" ++ path.sep_str ++ "lrintf.c",
|
||||
"math" ++ path.sep_str ++ "lrintl.c",
|
||||
"math" ++ path.sep_str ++ "lround.c",
|
||||
"math" ++ path.sep_str ++ "lroundf.c",
|
||||
"math" ++ path.sep_str ++ "lroundl.c",
|
||||
"math" ++ path.sep_str ++ "modf.c",
|
||||
"math" ++ path.sep_str ++ "modff.c",
|
||||
"math" ++ path.sep_str ++ "modfl.c",
|
||||
"math" ++ path.sep_str ++ "nextafterf.c",
|
||||
"math" ++ path.sep_str ++ "nextafterl.c",
|
||||
"math" ++ path.sep_str ++ "nexttoward.c",
|
||||
"math" ++ path.sep_str ++ "nexttowardf.c",
|
||||
"math" ++ path.sep_str ++ "powf.c",
|
||||
"math" ++ path.sep_str ++ "powi.c",
|
||||
"math" ++ path.sep_str ++ "powif.c",
|
||||
"math" ++ path.sep_str ++ "powil.c",
|
||||
"math" ++ path.sep_str ++ "rint.c",
|
||||
"math" ++ path.sep_str ++ "rintf.c",
|
||||
"math" ++ path.sep_str ++ "rintl.c",
|
||||
"math" ++ path.sep_str ++ "round.c",
|
||||
"math" ++ path.sep_str ++ "roundf.c",
|
||||
"math" ++ path.sep_str ++ "roundl.c",
|
||||
"math" ++ path.sep_str ++ "s_erf.c",
|
||||
"math" ++ path.sep_str ++ "sf_erf.c",
|
||||
"math" ++ path.sep_str ++ "signbit.c",
|
||||
"math" ++ path.sep_str ++ "signbitf.c",
|
||||
"math" ++ path.sep_str ++ "signbitl.c",
|
||||
"math" ++ path.sep_str ++ "signgam.c",
|
||||
"math" ++ path.sep_str ++ "sinhf.c",
|
||||
"math" ++ path.sep_str ++ "sinhl.c",
|
||||
"math" ++ path.sep_str ++ "sqrt.c",
|
||||
"math" ++ path.sep_str ++ "sqrtf.c",
|
||||
"math" ++ path.sep_str ++ "sqrtl.c",
|
||||
"math" ++ path.sep_str ++ "tanhf.c",
|
||||
"math" ++ path.sep_str ++ "tanhl.c",
|
||||
"math" ++ path.sep_str ++ "tgamma.c",
|
||||
"math" ++ path.sep_str ++ "tgammaf.c",
|
||||
"math" ++ path.sep_str ++ "tgammal.c",
|
||||
"math" ++ path.sep_str ++ "truncl.c",
|
||||
"misc" ++ path.sep_str ++ "alarm.c",
|
||||
"misc" ++ path.sep_str ++ "basename.c",
|
||||
"misc" ++ path.sep_str ++ "btowc.c",
|
||||
"misc" ++ path.sep_str ++ "delay-f.c",
|
||||
"misc" ++ path.sep_str ++ "delay-n.c",
|
||||
"misc" ++ path.sep_str ++ "delayimp.c",
|
||||
"misc" ++ path.sep_str ++ "dirent.c",
|
||||
"misc" ++ path.sep_str ++ "dirname.c",
|
||||
"misc" ++ path.sep_str ++ "feclearexcept.c",
|
||||
"misc" ++ path.sep_str ++ "fegetenv.c",
|
||||
"misc" ++ path.sep_str ++ "fegetexceptflag.c",
|
||||
"misc" ++ path.sep_str ++ "fegetround.c",
|
||||
"misc" ++ path.sep_str ++ "feholdexcept.c",
|
||||
"misc" ++ path.sep_str ++ "feraiseexcept.c",
|
||||
"misc" ++ path.sep_str ++ "fesetenv.c",
|
||||
"misc" ++ path.sep_str ++ "fesetexceptflag.c",
|
||||
"misc" ++ path.sep_str ++ "fesetround.c",
|
||||
"misc" ++ path.sep_str ++ "fetestexcept.c",
|
||||
"misc" ++ path.sep_str ++ "feupdateenv.c",
|
||||
"misc" ++ path.sep_str ++ "ftruncate.c",
|
||||
"misc" ++ path.sep_str ++ "ftw.c",
|
||||
"misc" ++ path.sep_str ++ "ftw64.c",
|
||||
"misc" ++ path.sep_str ++ "fwide.c",
|
||||
"misc" ++ path.sep_str ++ "getlogin.c",
|
||||
"misc" ++ path.sep_str ++ "getopt.c",
|
||||
"misc" ++ path.sep_str ++ "gettimeofday.c",
|
||||
"misc" ++ path.sep_str ++ "imaxabs.c",
|
||||
"misc" ++ path.sep_str ++ "imaxdiv.c",
|
||||
"misc" ++ path.sep_str ++ "isblank.c",
|
||||
"misc" ++ path.sep_str ++ "iswblank.c",
|
||||
"misc" ++ path.sep_str ++ "mbrtowc.c",
|
||||
"misc" ++ path.sep_str ++ "mbsinit.c",
|
||||
"misc" ++ path.sep_str ++ "mempcpy.c",
|
||||
"misc" ++ path.sep_str ++ "mingw-aligned-malloc.c",
|
||||
"misc" ++ path.sep_str ++ "mingw-fseek.c",
|
||||
"misc" ++ path.sep_str ++ "mingw_getsp.S",
|
||||
"misc" ++ path.sep_str ++ "mingw_matherr.c",
|
||||
"misc" ++ path.sep_str ++ "mingw_mbwc_convert.c",
|
||||
"misc" ++ path.sep_str ++ "mingw_usleep.c",
|
||||
"misc" ++ path.sep_str ++ "mingw_wcstod.c",
|
||||
"misc" ++ path.sep_str ++ "mingw_wcstof.c",
|
||||
"misc" ++ path.sep_str ++ "mingw_wcstold.c",
|
||||
"misc" ++ path.sep_str ++ "mkstemp.c",
|
||||
"misc" ++ path.sep_str ++ "seterrno.c",
|
||||
"misc" ++ path.sep_str ++ "sleep.c",
|
||||
"misc" ++ path.sep_str ++ "strnlen.c",
|
||||
"misc" ++ path.sep_str ++ "strsafe.c",
|
||||
"misc" ++ path.sep_str ++ "strtoimax.c",
|
||||
"misc" ++ path.sep_str ++ "strtold.c",
|
||||
"misc" ++ path.sep_str ++ "strtoumax.c",
|
||||
"misc" ++ path.sep_str ++ "tdelete.c",
|
||||
"misc" ++ path.sep_str ++ "tfind.c",
|
||||
"misc" ++ path.sep_str ++ "tsearch.c",
|
||||
"misc" ++ path.sep_str ++ "twalk.c",
|
||||
"misc" ++ path.sep_str ++ "uchar_c16rtomb.c",
|
||||
"misc" ++ path.sep_str ++ "uchar_c32rtomb.c",
|
||||
"misc" ++ path.sep_str ++ "uchar_mbrtoc16.c",
|
||||
"misc" ++ path.sep_str ++ "uchar_mbrtoc32.c",
|
||||
"misc" ++ path.sep_str ++ "wassert.c",
|
||||
"misc" ++ path.sep_str ++ "wcrtomb.c",
|
||||
"misc" ++ path.sep_str ++ "wcsnlen.c",
|
||||
"misc" ++ path.sep_str ++ "wcstof.c",
|
||||
"misc" ++ path.sep_str ++ "wcstoimax.c",
|
||||
"misc" ++ path.sep_str ++ "wcstold.c",
|
||||
"misc" ++ path.sep_str ++ "wcstoumax.c",
|
||||
"misc" ++ path.sep_str ++ "wctob.c",
|
||||
"misc" ++ path.sep_str ++ "wctrans.c",
|
||||
"misc" ++ path.sep_str ++ "wctype.c",
|
||||
"misc" ++ path.sep_str ++ "wdirent.c",
|
||||
"misc" ++ path.sep_str ++ "winbs_uint64.c",
|
||||
"misc" ++ path.sep_str ++ "winbs_ulong.c",
|
||||
"misc" ++ path.sep_str ++ "winbs_ushort.c",
|
||||
"misc" ++ path.sep_str ++ "wmemchr.c",
|
||||
"misc" ++ path.sep_str ++ "wmemcmp.c",
|
||||
"misc" ++ path.sep_str ++ "wmemcpy.c",
|
||||
"misc" ++ path.sep_str ++ "wmemmove.c",
|
||||
"misc" ++ path.sep_str ++ "wmempcpy.c",
|
||||
"misc" ++ path.sep_str ++ "wmemset.c",
|
||||
"stdio" ++ path.sep_str ++ "_Exit.c",
|
||||
"stdio" ++ path.sep_str ++ "_findfirst64i32.c",
|
||||
"stdio" ++ path.sep_str ++ "_findnext64i32.c",
|
||||
"stdio" ++ path.sep_str ++ "_fstat.c",
|
||||
"stdio" ++ path.sep_str ++ "_fstat64i32.c",
|
||||
"stdio" ++ path.sep_str ++ "_ftime.c",
|
||||
"stdio" ++ path.sep_str ++ "_getc_nolock.c",
|
||||
"stdio" ++ path.sep_str ++ "_getwc_nolock.c",
|
||||
"stdio" ++ path.sep_str ++ "_putc_nolock.c",
|
||||
"stdio" ++ path.sep_str ++ "_putwc_nolock.c",
|
||||
"stdio" ++ path.sep_str ++ "_stat.c",
|
||||
"stdio" ++ path.sep_str ++ "_stat64i32.c",
|
||||
"stdio" ++ path.sep_str ++ "_wfindfirst64i32.c",
|
||||
"stdio" ++ path.sep_str ++ "_wfindnext64i32.c",
|
||||
"stdio" ++ path.sep_str ++ "_wstat.c",
|
||||
"stdio" ++ path.sep_str ++ "_wstat64i32.c",
|
||||
"stdio" ++ path.sep_str ++ "asprintf.c",
|
||||
"stdio" ++ path.sep_str ++ "atoll.c",
|
||||
"stdio" ++ path.sep_str ++ "fgetpos64.c",
|
||||
"stdio" ++ path.sep_str ++ "fopen64.c",
|
||||
"stdio" ++ path.sep_str ++ "fseeko32.c",
|
||||
"stdio" ++ path.sep_str ++ "fseeko64.c",
|
||||
"stdio" ++ path.sep_str ++ "fsetpos64.c",
|
||||
"stdio" ++ path.sep_str ++ "ftello.c",
|
||||
"stdio" ++ path.sep_str ++ "ftello64.c",
|
||||
"stdio" ++ path.sep_str ++ "ftruncate64.c",
|
||||
"stdio" ++ path.sep_str ++ "lltoa.c",
|
||||
"stdio" ++ path.sep_str ++ "lltow.c",
|
||||
"stdio" ++ path.sep_str ++ "lseek64.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_asprintf.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_fprintf.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_fprintfw.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_fscanf.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_fwscanf.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_pformat.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_pformatw.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_printf.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_printfw.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_scanf.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_snprintf.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_snprintfw.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_sprintf.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_sprintfw.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_sscanf.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_swscanf.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_vasprintf.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_vfprintf.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_vfprintfw.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_vfscanf.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_vprintf.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_vprintfw.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_vsnprintf.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_vsnprintfw.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_vsprintf.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_vsprintfw.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_wscanf.c",
|
||||
"stdio" ++ path.sep_str ++ "mingw_wvfscanf.c",
|
||||
"stdio" ++ path.sep_str ++ "scanf.S",
|
||||
"stdio" ++ path.sep_str ++ "snprintf.c",
|
||||
"stdio" ++ path.sep_str ++ "snwprintf.c",
|
||||
"stdio" ++ path.sep_str ++ "strtof.c",
|
||||
"stdio" ++ path.sep_str ++ "strtok_r.c",
|
||||
"stdio" ++ path.sep_str ++ "truncate.c",
|
||||
"stdio" ++ path.sep_str ++ "ulltoa.c",
|
||||
"stdio" ++ path.sep_str ++ "ulltow.c",
|
||||
"stdio" ++ path.sep_str ++ "vasprintf.c",
|
||||
"stdio" ++ path.sep_str ++ "vfscanf.c",
|
||||
"stdio" ++ path.sep_str ++ "vfscanf2.S",
|
||||
"stdio" ++ path.sep_str ++ "vfwscanf.c",
|
||||
"stdio" ++ path.sep_str ++ "vfwscanf2.S",
|
||||
"stdio" ++ path.sep_str ++ "vscanf.c",
|
||||
"stdio" ++ path.sep_str ++ "vscanf2.S",
|
||||
"stdio" ++ path.sep_str ++ "vsnprintf.c",
|
||||
"stdio" ++ path.sep_str ++ "vsnwprintf.c",
|
||||
"stdio" ++ path.sep_str ++ "vsscanf.c",
|
||||
"stdio" ++ path.sep_str ++ "vsscanf2.S",
|
||||
"stdio" ++ path.sep_str ++ "vswscanf.c",
|
||||
"stdio" ++ path.sep_str ++ "vswscanf2.S",
|
||||
"stdio" ++ path.sep_str ++ "vwscanf.c",
|
||||
"stdio" ++ path.sep_str ++ "vwscanf2.S",
|
||||
"stdio" ++ path.sep_str ++ "wtoll.c",
|
||||
};
|
||||
|
||||
const mingwex_x86_src = [_][]const u8{
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "acosf.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "acosh.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "acoshf.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "acoshl.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "acosl.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "asinf.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "asinh.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "asinhf.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "asinhl.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "asinl.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "atan2.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "atan2f.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "atan2l.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "atanf.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "atanh.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "atanhf.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "atanhl.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "atanl.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "ceilf.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "ceill.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "ceil.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "_chgsignl.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "copysignl.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "cos.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "cosf.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "cosl.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "cosl_internal.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "cossin.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "exp2f.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "exp2l.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "exp2.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "exp.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "expl.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "expm1.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "expm1f.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "expm1l.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "floorf.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "floorl.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "floor.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "fmod.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "fmodf.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "fmodl.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "fucom.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "ilogbf.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "ilogbl.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "ilogb.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "internal_logl.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "ldexp.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "ldexpl.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "log10l.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "log1pf.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "log1pl.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "log1p.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "log2f.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "log2l.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "log2.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "logb.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "logbf.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "logbl.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "log.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "logl.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "nearbyintf.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "nearbyintl.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "nearbyint.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "pow.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "powl.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "remainderf.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "remainderl.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "remainder.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "remquof.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "remquol.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "remquo.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "scalbnf.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "scalbnl.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "scalbn.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "sin.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "sinf.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "sinl.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "sinl_internal.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "tanf.c",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "tanl.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "truncf.S",
|
||||
"math" ++ path.sep_str ++ "x86" ++ path.sep_str ++ "trunc.S",
|
||||
};
|
||||
|
||||
const mingwex_arm32_src = [_][]const u8{
|
||||
"math" ++ path.sep_str ++ "arm" ++ path.sep_str ++ "_chgsignl.S",
|
||||
"math" ++ path.sep_str ++ "arm" ++ path.sep_str ++ "exp2.c",
|
||||
"math" ++ path.sep_str ++ "arm" ++ path.sep_str ++ "nearbyint.S",
|
||||
"math" ++ path.sep_str ++ "arm" ++ path.sep_str ++ "nearbyintf.S",
|
||||
"math" ++ path.sep_str ++ "arm" ++ path.sep_str ++ "nearbyintl.S",
|
||||
"math" ++ path.sep_str ++ "arm" ++ path.sep_str ++ "trunc.S",
|
||||
"math" ++ path.sep_str ++ "arm" ++ path.sep_str ++ "truncf.S",
|
||||
};
|
||||
|
||||
const mingwex_arm64_src = [_][]const u8{
|
||||
"math" ++ path.sep_str ++ "arm64" ++ path.sep_str ++ "_chgsignl.S",
|
||||
"math" ++ path.sep_str ++ "arm64" ++ path.sep_str ++ "exp2f.S",
|
||||
"math" ++ path.sep_str ++ "arm64" ++ path.sep_str ++ "exp2.S",
|
||||
"math" ++ path.sep_str ++ "arm64" ++ path.sep_str ++ "nearbyintf.S",
|
||||
"math" ++ path.sep_str ++ "arm64" ++ path.sep_str ++ "nearbyintl.S",
|
||||
"math" ++ path.sep_str ++ "arm64" ++ path.sep_str ++ "nearbyint.S",
|
||||
"math" ++ path.sep_str ++ "arm64" ++ path.sep_str ++ "truncf.S",
|
||||
"math" ++ path.sep_str ++ "arm64" ++ path.sep_str ++ "trunc.S",
|
||||
};
|
||||
|
||||
const uuid_src = [_][]const u8{
|
||||
"ativscp-uuid.c",
|
||||
"atsmedia-uuid.c",
|
||||
"bth-uuid.c",
|
||||
"cguid-uuid.c",
|
||||
"comcat-uuid.c",
|
||||
"devguid.c",
|
||||
"docobj-uuid.c",
|
||||
"dxva-uuid.c",
|
||||
"exdisp-uuid.c",
|
||||
"extras-uuid.c",
|
||||
"fwp-uuid.c",
|
||||
"guid_nul.c",
|
||||
"hlguids-uuid.c",
|
||||
"hlink-uuid.c",
|
||||
"mlang-uuid.c",
|
||||
"msctf-uuid.c",
|
||||
"mshtmhst-uuid.c",
|
||||
"mshtml-uuid.c",
|
||||
"msxml-uuid.c",
|
||||
"netcon-uuid.c",
|
||||
"ntddkbd-uuid.c",
|
||||
"ntddmou-uuid.c",
|
||||
"ntddpar-uuid.c",
|
||||
"ntddscsi-uuid.c",
|
||||
"ntddser-uuid.c",
|
||||
"ntddstor-uuid.c",
|
||||
"ntddvdeo-uuid.c",
|
||||
"oaidl-uuid.c",
|
||||
"objidl-uuid.c",
|
||||
"objsafe-uuid.c",
|
||||
"ocidl-uuid.c",
|
||||
"oleacc-uuid.c",
|
||||
"olectlid-uuid.c",
|
||||
"oleidl-uuid.c",
|
||||
"power-uuid.c",
|
||||
"powrprof-uuid.c",
|
||||
"uianimation-uuid.c",
|
||||
"usbcamdi-uuid.c",
|
||||
"usbiodef-uuid.c",
|
||||
"uuid.c",
|
||||
"vds-uuid.c",
|
||||
"virtdisk-uuid.c",
|
||||
"wia-uuid.c",
|
||||
};
|
||||
|
||||
pub const always_link_libs = [_][]const u8{
|
||||
"advapi32",
|
||||
"kernel32",
|
||||
"msvcrt",
|
||||
"ntdll",
|
||||
"shell32",
|
||||
"user32",
|
||||
};
|
||||
@ -7,9 +7,6 @@ const assert = std.debug.assert;
|
||||
const target_util = @import("target.zig");
|
||||
const Compilation = @import("Compilation.zig");
|
||||
const build_options = @import("build_options");
|
||||
const trace = @import("tracy.zig").trace;
|
||||
const Cache = @import("Cache.zig");
|
||||
const Package = @import("Package.zig");
|
||||
|
||||
pub const CRTFile = enum {
|
||||
crti_o,
|
||||
|
||||
@ -121,6 +121,14 @@ pub const Module = extern struct {
|
||||
verbose_cimport: bool,
|
||||
verbose_llvm_cpu_features: bool,
|
||||
|
||||
// Set by stage1
|
||||
have_c_main: bool,
|
||||
have_winmain: bool,
|
||||
have_wwinmain: bool,
|
||||
have_winmain_crt_startup: bool,
|
||||
have_wwinmain_crt_startup: bool,
|
||||
have_dllmain_crt_startup: bool,
|
||||
|
||||
pub fn build_object(mod: *Module) void {
|
||||
zig_stage1_build_object(mod);
|
||||
}
|
||||
|
||||
@ -2152,12 +2152,6 @@ struct CodeGen {
|
||||
uint32_t next_unresolved_index;
|
||||
unsigned pointer_size_bytes;
|
||||
bool is_big_endian;
|
||||
bool have_c_main;
|
||||
bool have_winmain;
|
||||
bool have_wwinmain;
|
||||
bool have_winmain_crt_startup;
|
||||
bool have_wwinmain_crt_startup;
|
||||
bool have_dllmain_crt_startup;
|
||||
bool have_err_ret_tracing;
|
||||
bool verbose_tokenize;
|
||||
bool verbose_ast;
|
||||
|
||||
@ -3496,18 +3496,18 @@ void add_var_export(CodeGen *g, ZigVar *var, const char *symbol_name, GlobalLink
|
||||
|
||||
void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, const char *symbol_name, GlobalLinkageId linkage, CallingConvention cc) {
|
||||
if (cc == CallingConventionC && strcmp(symbol_name, "main") == 0 && g->link_libc) {
|
||||
g->have_c_main = true;
|
||||
g->stage1.have_c_main = true;
|
||||
} else if (cc == CallingConventionStdcall && g->zig_target->os == OsWindows) {
|
||||
if (strcmp(symbol_name, "WinMain") == 0) {
|
||||
g->have_winmain = true;
|
||||
g->stage1.have_winmain = true;
|
||||
} else if (strcmp(symbol_name, "wWinMain") == 0) {
|
||||
g->have_wwinmain = true;
|
||||
g->stage1.have_wwinmain = true;
|
||||
} else if (strcmp(symbol_name, "WinMainCRTStartup") == 0) {
|
||||
g->have_winmain_crt_startup = true;
|
||||
g->stage1.have_winmain_crt_startup = true;
|
||||
} else if (strcmp(symbol_name, "wWinMainCRTStartup") == 0) {
|
||||
g->have_wwinmain_crt_startup = true;
|
||||
g->stage1.have_wwinmain_crt_startup = true;
|
||||
} else if (strcmp(symbol_name, "DllMainCRTStartup") == 0) {
|
||||
g->have_dllmain_crt_startup = true;
|
||||
g->stage1.have_dllmain_crt_startup = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -8666,11 +8666,11 @@ TargetSubsystem detect_subsystem(CodeGen *g) {
|
||||
if (g->subsystem != TargetSubsystemAuto)
|
||||
return g->subsystem;
|
||||
if (g->zig_target->os == OsWindows) {
|
||||
if (g->have_dllmain_crt_startup)
|
||||
if (g->stage1.have_dllmain_crt_startup)
|
||||
return TargetSubsystemAuto;
|
||||
if (g->have_c_main || g->is_test_build || g->have_winmain_crt_startup || g->have_wwinmain_crt_startup)
|
||||
if (g->stage1.have_c_main || g->is_test_build || g->stage1.have_winmain_crt_startup || g->stage1.have_wwinmain_crt_startup)
|
||||
return TargetSubsystemConsole;
|
||||
if (g->have_winmain || g->have_wwinmain)
|
||||
if (g->stage1.have_winmain || g->stage1.have_wwinmain)
|
||||
return TargetSubsystemWindows;
|
||||
} else if (g->zig_target->os == OsUefi) {
|
||||
return TargetSubsystemEfiApplication;
|
||||
|
||||
@ -195,6 +195,14 @@ struct ZigStage1 {
|
||||
bool verbose_llvm_ir;
|
||||
bool verbose_cimport;
|
||||
bool verbose_llvm_cpu_features;
|
||||
|
||||
// Set by stage1
|
||||
bool have_c_main;
|
||||
bool have_winmain;
|
||||
bool have_wwinmain;
|
||||
bool have_winmain_crt_startup;
|
||||
bool have_wwinmain_crt_startup;
|
||||
bool have_dllmain_crt_startup;
|
||||
};
|
||||
|
||||
ZIG_EXTERN_C void zig_stage1_os_init(void);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user