mirror of
https://github.com/ziglang/zig.git
synced 2025-12-25 23:53:15 +00:00
Merge pull request #25414 from squeek502/mingw-def-implib
Support generating import libraries from mingw .def files without LLVM
This commit is contained in:
commit
6893e7feee
@ -528,13 +528,11 @@ pub const SectionHeader = extern struct {
|
||||
|
||||
/// Applicable only to section headers in COFF objects.
|
||||
pub fn getAlignment(self: SectionHeader) ?u16 {
|
||||
if (self.flags.ALIGN == 0) return null;
|
||||
return std.math.powi(u16, 2, self.flags.ALIGN - 1) catch unreachable;
|
||||
return self.flags.ALIGN.toByteUnits();
|
||||
}
|
||||
|
||||
pub fn setAlignment(self: *SectionHeader, new_alignment: u16) void {
|
||||
assert(new_alignment > 0 and new_alignment <= 8192);
|
||||
self.flags.ALIGN = @intCast(std.math.log2(new_alignment));
|
||||
self.flags.ALIGN = .fromByteUnits(new_alignment);
|
||||
}
|
||||
|
||||
pub fn isCode(self: SectionHeader) bool {
|
||||
@ -651,6 +649,16 @@ pub const SectionHeader = extern struct {
|
||||
@"4096BYTES" = 13,
|
||||
@"8192BYTES" = 14,
|
||||
_,
|
||||
|
||||
pub fn toByteUnits(a: Align) ?u16 {
|
||||
if (a == .NONE) return null;
|
||||
return @as(u16, 1) << (@intFromEnum(a) - 1);
|
||||
}
|
||||
|
||||
pub fn fromByteUnits(n: u16) Align {
|
||||
std.debug.assert(std.math.isPowerOfTwo(n));
|
||||
return @enumFromInt(@ctz(n) + 1);
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -925,6 +933,10 @@ pub const WeakExternalDefinition = struct {
|
||||
flag: WeakExternalFlag,
|
||||
|
||||
unused: [10]u8,
|
||||
|
||||
pub fn sizeOf() usize {
|
||||
return 18;
|
||||
}
|
||||
};
|
||||
|
||||
// https://github.com/tpn/winsdk-10/blob/master/Include/10.0.16299.0/km/ntimage.h
|
||||
@ -1338,14 +1350,16 @@ pub const Strtab = struct {
|
||||
};
|
||||
|
||||
pub const ImportHeader = extern struct {
|
||||
sig1: IMAGE.FILE.MACHINE,
|
||||
sig2: u16,
|
||||
/// Must be IMAGE_FILE_MACHINE_UNKNOWN
|
||||
sig1: IMAGE.FILE.MACHINE = .UNKNOWN,
|
||||
/// Must be 0xFFFF
|
||||
sig2: u16 = 0xFFFF,
|
||||
version: u16,
|
||||
machine: IMAGE.FILE.MACHINE,
|
||||
time_date_stamp: u32,
|
||||
size_of_data: u32,
|
||||
hint: u16,
|
||||
types: packed struct(u32) {
|
||||
types: packed struct(u16) {
|
||||
type: ImportType,
|
||||
name_type: ImportNameType,
|
||||
reserved: u11,
|
||||
|
||||
@ -338,14 +338,6 @@ extern fn ZigLLVMWriteArchive(
|
||||
pub const ParseCommandLineOptions = ZigLLVMParseCommandLineOptions;
|
||||
extern fn ZigLLVMParseCommandLineOptions(argc: usize, argv: [*]const [*:0]const u8) void;
|
||||
|
||||
pub const WriteImportLibrary = ZigLLVMWriteImportLibrary;
|
||||
extern fn ZigLLVMWriteImportLibrary(
|
||||
def_path: [*:0]const u8,
|
||||
coff_machine: c_uint,
|
||||
output_lib_path: [*:0]const u8,
|
||||
kill_at: bool,
|
||||
) bool;
|
||||
|
||||
pub const GetHostCPUName = LLVMGetHostCPUName;
|
||||
extern fn LLVMGetHostCPUName() ?[*:0]u8;
|
||||
|
||||
|
||||
@ -10,6 +10,13 @@ const Compilation = @import("../Compilation.zig");
|
||||
const build_options = @import("build_options");
|
||||
const Cache = std.Build.Cache;
|
||||
const dev = @import("../dev.zig");
|
||||
const def = @import("mingw/def.zig");
|
||||
const implib = @import("mingw/implib.zig");
|
||||
|
||||
test {
|
||||
_ = def;
|
||||
_ = implib;
|
||||
}
|
||||
|
||||
pub const CrtFile = enum {
|
||||
crt2_o,
|
||||
@ -290,11 +297,6 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
|
||||
var o_dir = try comp.dirs.global_cache.handle.makeOpenPath(o_sub_path, .{});
|
||||
defer o_dir.close();
|
||||
|
||||
const final_def_basename = try std.fmt.allocPrint(arena, "{s}.def", .{lib_name});
|
||||
const def_final_path = try comp.dirs.global_cache.join(arena, &[_][]const u8{
|
||||
"o", &digest, final_def_basename,
|
||||
});
|
||||
|
||||
const aro = @import("aro");
|
||||
var diagnostics: aro.Diagnostics = .{
|
||||
.output = .{ .to_list = .{ .arena = .init(gpa) } },
|
||||
@ -312,7 +314,6 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
|
||||
defer std.debug.unlockStderrWriter();
|
||||
nosuspend stderr.print("def file: {s}\n", .{def_file_path}) catch break :print;
|
||||
nosuspend stderr.print("include dir: {s}\n", .{include_dir}) catch break :print;
|
||||
nosuspend stderr.print("output path: {s}\n", .{def_final_path}) catch break :print;
|
||||
}
|
||||
|
||||
try aro_comp.include_dirs.append(gpa, include_dir);
|
||||
@ -339,32 +340,46 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void {
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// new scope to ensure definition file is written before passing the path to WriteImportLibrary
|
||||
const def_final_file = try o_dir.createFile(final_def_basename, .{ .truncate = true });
|
||||
defer def_final_file.close();
|
||||
var buffer: [1024]u8 = undefined;
|
||||
var file_writer = def_final_file.writer(&buffer);
|
||||
try pp.prettyPrintTokens(&file_writer.interface, .result_only);
|
||||
try file_writer.interface.flush();
|
||||
}
|
||||
const members = members: {
|
||||
var aw: std.Io.Writer.Allocating = .init(gpa);
|
||||
errdefer aw.deinit();
|
||||
try pp.prettyPrintTokens(&aw.writer, .result_only);
|
||||
|
||||
const input = try aw.toOwnedSliceSentinel(0);
|
||||
defer gpa.free(input);
|
||||
|
||||
const machine_type = target.toCoffMachine();
|
||||
var def_diagnostics: def.Diagnostics = undefined;
|
||||
var module_def = def.parse(gpa, input, machine_type, .mingw, &def_diagnostics) catch |err| switch (err) {
|
||||
error.OutOfMemory => |e| return e,
|
||||
error.ParseError => {
|
||||
var buffer: [64]u8 = undefined;
|
||||
const w = std.debug.lockStderrWriter(&buffer);
|
||||
defer std.debug.unlockStderrWriter();
|
||||
try w.writeAll("error: ");
|
||||
try def_diagnostics.writeMsg(w, input);
|
||||
try w.writeByte('\n');
|
||||
return error.WritingImportLibFailed;
|
||||
},
|
||||
};
|
||||
defer module_def.deinit();
|
||||
|
||||
module_def.fixupForImportLibraryGeneration(machine_type);
|
||||
|
||||
break :members try implib.getMembers(gpa, module_def, machine_type);
|
||||
};
|
||||
defer members.deinit();
|
||||
|
||||
const lib_final_path = try std.fs.path.join(gpa, &.{ "o", &digest, final_lib_basename });
|
||||
errdefer gpa.free(lib_final_path);
|
||||
|
||||
if (!build_options.have_llvm) return error.ZigCompilerNotBuiltWithLLVMExtensions;
|
||||
const llvm_bindings = @import("../codegen/llvm/bindings.zig");
|
||||
const def_final_path_z = try arena.dupeZ(u8, def_final_path);
|
||||
const lib_final_path_z = try comp.dirs.global_cache.joinZ(arena, &.{lib_final_path});
|
||||
if (llvm_bindings.WriteImportLibrary(
|
||||
def_final_path_z.ptr,
|
||||
@intFromEnum(target.toCoffMachine()),
|
||||
lib_final_path_z.ptr,
|
||||
true,
|
||||
)) {
|
||||
// TODO surface a proper error here
|
||||
log.err("unable to turn {s}.def into {s}.lib", .{ lib_name, lib_name });
|
||||
return error.WritingImportLibFailed;
|
||||
{
|
||||
const lib_final_file = try o_dir.createFile(final_lib_basename, .{ .truncate = true });
|
||||
defer lib_final_file.close();
|
||||
var buffer: [1024]u8 = undefined;
|
||||
var file_writer = lib_final_file.writer(&buffer);
|
||||
try implib.writeCoffArchive(gpa, &file_writer.interface, members);
|
||||
try file_writer.interface.flush();
|
||||
}
|
||||
|
||||
man.writeManifest() catch |err| {
|
||||
|
||||
1079
src/libs/mingw/def.zig
Normal file
1079
src/libs/mingw/def.zig
Normal file
File diff suppressed because it is too large
Load Diff
1088
src/libs/mingw/implib.zig
Normal file
1088
src/libs/mingw/implib.zig
Normal file
File diff suppressed because it is too large
Load Diff
@ -39,9 +39,6 @@
|
||||
#include <llvm/Passes/StandardInstrumentations.h>
|
||||
#include <llvm/Object/Archive.h>
|
||||
#include <llvm/Object/ArchiveWriter.h>
|
||||
#include <llvm/Object/COFF.h>
|
||||
#include <llvm/Object/COFFImportFile.h>
|
||||
#include <llvm/Object/COFFModuleDefinition.h>
|
||||
#include <llvm/PassRegistry.h>
|
||||
#include <llvm/Support/CommandLine.h>
|
||||
#include <llvm/Support/FileSystem.h>
|
||||
@ -475,62 +472,6 @@ void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv) {
|
||||
cl::ParseCommandLineOptions(argc, argv);
|
||||
}
|
||||
|
||||
bool ZigLLVMWriteImportLibrary(const char *def_path, unsigned int coff_machine,
|
||||
const char *output_lib_path, bool kill_at)
|
||||
{
|
||||
COFF::MachineTypes machine = static_cast<COFF::MachineTypes>(coff_machine);
|
||||
|
||||
auto bufOrErr = MemoryBuffer::getFile(def_path);
|
||||
if (!bufOrErr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MemoryBuffer& buf = *bufOrErr.get();
|
||||
Expected<object::COFFModuleDefinition> def =
|
||||
object::parseCOFFModuleDefinition(buf, machine, /* MingwDef */ true);
|
||||
|
||||
if (!def) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// The exports-juggling code below is ripped from LLVM's DlltoolDriver.cpp
|
||||
|
||||
// If ExtName is set (if the "ExtName = Name" syntax was used), overwrite
|
||||
// Name with ExtName and clear ExtName. When only creating an import
|
||||
// library and not linking, the internal name is irrelevant. This avoids
|
||||
// cases where writeImportLibrary tries to transplant decoration from
|
||||
// symbol decoration onto ExtName.
|
||||
for (object::COFFShortExport& E : def->Exports) {
|
||||
if (!E.ExtName.empty()) {
|
||||
E.Name = E.ExtName;
|
||||
E.ExtName.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (kill_at) {
|
||||
for (object::COFFShortExport& E : def->Exports) {
|
||||
if (!E.ImportName.empty() || (!E.Name.empty() && E.Name[0] == '?'))
|
||||
continue;
|
||||
if (machine == COFF::IMAGE_FILE_MACHINE_I386) {
|
||||
// By making sure E.SymbolName != E.Name for decorated symbols,
|
||||
// writeImportLibrary writes these symbols with the type
|
||||
// IMPORT_NAME_UNDECORATE.
|
||||
E.SymbolName = E.Name;
|
||||
}
|
||||
// Trim off the trailing decoration. Symbols will always have a
|
||||
// starting prefix here (either _ for cdecl/stdcall, @ for fastcall
|
||||
// or ? for C++ functions). Vectorcall functions won't have any
|
||||
// fixed prefix, but the function base name will still be at least
|
||||
// one char.
|
||||
E.Name = E.Name.substr(0, E.Name.find('@', 1));
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<bool>(
|
||||
object::writeImportLibrary(def->OutputFile, output_lib_path,
|
||||
def->Exports, machine, /* MinGW */ true));
|
||||
}
|
||||
|
||||
bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count,
|
||||
ZigLLVMArchiveKind archive_kind)
|
||||
{
|
||||
|
||||
@ -124,7 +124,4 @@ ZIG_EXTERN_C bool ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_earl
|
||||
ZIG_EXTERN_C bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count,
|
||||
ZigLLVMArchiveKind archive_kind);
|
||||
|
||||
ZIG_EXTERN_C bool ZigLLVMWriteImportLibrary(const char *def_path, unsigned int coff_machine,
|
||||
const char *output_lib_path, bool kill_at);
|
||||
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user