self-hosted: linking against libc
also introduce `zig libc` command to display paths `zig libc file.txt` will parse equivalent text and use that for libc paths.master
parent
3e4a3fa5b7
commit
aa3b41247f
|
@ -15,7 +15,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
|
|||
defer fn_val.base.deref(comp);
|
||||
defer code.destroy(comp.gpa());
|
||||
|
||||
var output_path = try await (async comp.createRandomOutputPath(comp.target.oFileExt()) catch unreachable);
|
||||
var output_path = try await (async comp.createRandomOutputPath(comp.target.objFileExt()) catch unreachable);
|
||||
errdefer output_path.deinit();
|
||||
|
||||
const llvm_handle = try comp.event_loop_local.getAnyLlvmContext();
|
||||
|
|
|
@ -120,7 +120,6 @@ pub const Compilation = struct {
|
|||
|
||||
linker_script: ?[]const u8,
|
||||
cache_dir: []const u8,
|
||||
dynamic_linker: ?[]const u8,
|
||||
out_h_path: ?[]const u8,
|
||||
|
||||
is_test: bool,
|
||||
|
@ -201,6 +200,13 @@ pub const Compilation = struct {
|
|||
root_package: *Package,
|
||||
std_package: *Package,
|
||||
|
||||
override_libc: ?*LibCInstallation,
|
||||
|
||||
/// need to wait on this group before deinitializing
|
||||
deinit_group: event.Group(void),
|
||||
|
||||
destroy_handle: promise,
|
||||
|
||||
const CompileErrList = std.ArrayList(*errmsg.Msg);
|
||||
|
||||
// TODO handle some of these earlier and report them in a way other than error codes
|
||||
|
@ -246,6 +252,8 @@ pub const Compilation = struct {
|
|||
EnvironmentVariableNotFound,
|
||||
AppDataDirUnavailable,
|
||||
LinkFailed,
|
||||
LibCRequiredButNotProvidedOrFound,
|
||||
LibCMissingDynamicLinker,
|
||||
};
|
||||
|
||||
pub const Event = union(enum) {
|
||||
|
@ -324,7 +332,6 @@ pub const Compilation = struct {
|
|||
.verbose_link = false,
|
||||
|
||||
.linker_script = null,
|
||||
.dynamic_linker = null,
|
||||
.out_h_path = null,
|
||||
.is_test = false,
|
||||
.each_lib_rpath = false,
|
||||
|
@ -351,6 +358,7 @@ pub const Compilation = struct {
|
|||
.link_out_file = null,
|
||||
.exported_symbol_names = event.Locked(Decl.Table).init(loop, Decl.Table.init(loop.allocator)),
|
||||
.prelink_group = event.Group(BuildError!void).init(loop),
|
||||
.deinit_group = event.Group(void).init(loop),
|
||||
.compile_errors = event.Locked(CompileErrList).init(loop, CompileErrList.init(loop.allocator)),
|
||||
|
||||
.meta_type = undefined,
|
||||
|
@ -368,6 +376,9 @@ pub const Compilation = struct {
|
|||
|
||||
.root_package = undefined,
|
||||
.std_package = undefined,
|
||||
|
||||
.override_libc = null,
|
||||
.destroy_handle = undefined,
|
||||
});
|
||||
errdefer {
|
||||
comp.arena_allocator.deinit();
|
||||
|
@ -431,6 +442,9 @@ pub const Compilation = struct {
|
|||
}
|
||||
|
||||
try comp.initTypes();
|
||||
errdefer comp.derefTypes();
|
||||
|
||||
comp.destroy_handle = try async<loop.allocator> comp.internalDeinit();
|
||||
|
||||
return comp;
|
||||
}
|
||||
|
@ -526,11 +540,7 @@ pub const Compilation = struct {
|
|||
errdefer comp.gpa().destroy(comp.noreturn_value);
|
||||
}
|
||||
|
||||
pub fn destroy(self: *Compilation) void {
|
||||
if (self.tmp_dir.getOrNull()) |tmp_dir_result| if (tmp_dir_result.*) |tmp_dir| {
|
||||
os.deleteTree(self.arena(), tmp_dir) catch {};
|
||||
} else |_| {};
|
||||
|
||||
fn derefTypes(self: *Compilation) void {
|
||||
self.noreturn_value.base.deref(self);
|
||||
self.void_value.base.deref(self);
|
||||
self.false_value.base.deref(self);
|
||||
|
@ -538,6 +548,17 @@ pub const Compilation = struct {
|
|||
self.noreturn_type.base.base.deref(self);
|
||||
self.void_type.base.base.deref(self);
|
||||
self.meta_type.base.base.deref(self);
|
||||
}
|
||||
|
||||
async fn internalDeinit(self: *Compilation) void {
|
||||
suspend;
|
||||
await (async self.deinit_group.wait() catch unreachable);
|
||||
if (self.tmp_dir.getOrNull()) |tmp_dir_result| if (tmp_dir_result.*) |tmp_dir| {
|
||||
// TODO evented I/O?
|
||||
os.deleteTree(self.arena(), tmp_dir) catch {};
|
||||
} else |_| {};
|
||||
|
||||
self.derefTypes();
|
||||
|
||||
self.events.destroy();
|
||||
|
||||
|
@ -549,6 +570,10 @@ pub const Compilation = struct {
|
|||
self.gpa().destroy(self);
|
||||
}
|
||||
|
||||
pub fn destroy(self: *Compilation) void {
|
||||
resume self.destroy_handle;
|
||||
}
|
||||
|
||||
pub fn build(self: *Compilation) !void {
|
||||
if (self.llvm_argv.len != 0) {
|
||||
var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(self.arena(), [][]const []const u8{
|
||||
|
@ -680,7 +705,7 @@ pub const Compilation = struct {
|
|||
};
|
||||
|
||||
if (!any_prelink_errors) {
|
||||
try link(self);
|
||||
try await (async link(self) catch unreachable);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -765,8 +790,8 @@ pub const Compilation = struct {
|
|||
self.libc_link_lib = link_lib;
|
||||
|
||||
// get a head start on looking for the native libc
|
||||
if (self.target == Target.Native) {
|
||||
try async<self.loop.allocator> self.startFindingNativeLibC();
|
||||
if (self.target == Target.Native and self.override_libc == null) {
|
||||
try self.deinit_group.call(startFindingNativeLibC, self);
|
||||
}
|
||||
}
|
||||
return link_lib;
|
||||
|
@ -774,11 +799,9 @@ pub const Compilation = struct {
|
|||
|
||||
/// cancels itself so no need to await or cancel the promise.
|
||||
async fn startFindingNativeLibC(self: *Compilation) void {
|
||||
await (async self.loop.yield() catch unreachable);
|
||||
// we don't care if it fails, we're just trying to kick off the future resolution
|
||||
_ = (await (async self.loop.call(EventLoopLocal.getNativeLibC, self.event_loop_local) catch unreachable)) catch {};
|
||||
suspend |p| {
|
||||
cancel p;
|
||||
}
|
||||
_ = (await (async self.event_loop_local.getNativeLibC() catch unreachable)) catch return;
|
||||
}
|
||||
|
||||
/// General Purpose Allocator. Must free when done.
|
||||
|
|
|
@ -1,31 +1,18 @@
|
|||
const std = @import("std");
|
||||
const builtin = @import("builtin");
|
||||
const event = std.event;
|
||||
const Target = @import("target.zig").Target;
|
||||
|
||||
/// See the render function implementation for documentation of the fields.
|
||||
pub const LibCInstallation = struct {
|
||||
/// The directory that contains `stdlib.h`.
|
||||
/// On Linux, can be found with: `cc -E -Wp,-v -xc /dev/null`
|
||||
include_dir: []const u8,
|
||||
|
||||
/// The directory that contains `crt1.o`.
|
||||
/// On Linux, can be found with `cc -print-file-name=crt1.o`.
|
||||
/// Not needed when targeting MacOS.
|
||||
lib_dir: ?[]const u8,
|
||||
|
||||
/// The directory that contains `crtbegin.o`.
|
||||
/// On Linux, can be found with `cc -print-file-name=crt1.o`.
|
||||
/// Not needed when targeting MacOS or Windows.
|
||||
static_lib_dir: ?[]const u8,
|
||||
|
||||
/// The directory that contains `vcruntime.lib`.
|
||||
/// Only needed when targeting Windows.
|
||||
msvc_lib_dir: ?[]const u8,
|
||||
|
||||
/// The directory that contains `kernel32.lib`.
|
||||
/// Only needed when targeting Windows.
|
||||
kernel32_lib_dir: ?[]const u8,
|
||||
dynamic_linker_path: ?[]const u8,
|
||||
|
||||
pub const Error = error{
|
||||
pub const FindError = error{
|
||||
OutOfMemory,
|
||||
FileSystem,
|
||||
UnableToSpawnCCompiler,
|
||||
|
@ -36,16 +23,124 @@ pub const LibCInstallation = struct {
|
|||
LibCStdLibHeaderNotFound,
|
||||
};
|
||||
|
||||
pub fn parse(
|
||||
self: *LibCInstallation,
|
||||
allocator: *std.mem.Allocator,
|
||||
libc_file: []const u8,
|
||||
stderr: *std.io.OutStream(std.io.FileOutStream.Error),
|
||||
) !void {
|
||||
self.initEmpty();
|
||||
|
||||
const keys = []const []const u8{
|
||||
"include_dir",
|
||||
"lib_dir",
|
||||
"static_lib_dir",
|
||||
"msvc_lib_dir",
|
||||
"kernel32_lib_dir",
|
||||
"dynamic_linker_path",
|
||||
};
|
||||
const FoundKey = struct {
|
||||
found: bool,
|
||||
allocated: ?[]u8,
|
||||
};
|
||||
var found_keys = [1]FoundKey{FoundKey{ .found = false, .allocated = null }} ** keys.len;
|
||||
errdefer {
|
||||
self.initEmpty();
|
||||
for (found_keys) |found_key| {
|
||||
if (found_key.allocated) |s| allocator.free(s);
|
||||
}
|
||||
}
|
||||
|
||||
const contents = try std.io.readFileAlloc(allocator, libc_file);
|
||||
defer allocator.free(contents);
|
||||
|
||||
var it = std.mem.split(contents, "\n");
|
||||
while (it.next()) |line| {
|
||||
if (line.len == 0 or line[0] == '#') continue;
|
||||
var line_it = std.mem.split(line, "=");
|
||||
const name = line_it.next() orelse {
|
||||
try stderr.print("missing equal sign after field name\n");
|
||||
return error.ParseError;
|
||||
};
|
||||
const value = line_it.rest();
|
||||
inline for (keys) |key, i| {
|
||||
if (std.mem.eql(u8, name, key)) {
|
||||
found_keys[i].found = true;
|
||||
switch (@typeInfo(@typeOf(@field(self, key)))) {
|
||||
builtin.TypeId.Optional => {
|
||||
if (value.len == 0) {
|
||||
@field(self, key) = null;
|
||||
} else {
|
||||
found_keys[i].allocated = try std.mem.dupe(allocator, u8, value);
|
||||
@field(self, key) = found_keys[i].allocated;
|
||||
}
|
||||
},
|
||||
else => {
|
||||
if (value.len == 0) {
|
||||
try stderr.print("field cannot be empty: {}\n", key);
|
||||
return error.ParseError;
|
||||
}
|
||||
const dupe = try std.mem.dupe(allocator, u8, value);
|
||||
found_keys[i].allocated = dupe;
|
||||
@field(self, key) = dupe;
|
||||
},
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (found_keys) |found_key, i| {
|
||||
if (!found_key.found) {
|
||||
try stderr.print("missing field: {}\n", keys[i]);
|
||||
return error.ParseError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(self: *const LibCInstallation, out: *std.io.OutStream(std.io.FileOutStream.Error)) !void {
|
||||
@setEvalBranchQuota(4000);
|
||||
try out.print(
|
||||
\\# The directory that contains `stdlib.h`.
|
||||
\\# On Linux, can be found with: `cc -E -Wp,-v -xc /dev/null`
|
||||
\\include_dir={}
|
||||
\\
|
||||
\\# The directory that contains `crt1.o`.
|
||||
\\# On Linux, can be found with `cc -print-file-name=crt1.o`.
|
||||
\\# Not needed when targeting MacOS.
|
||||
\\lib_dir={}
|
||||
\\
|
||||
\\# The directory that contains `crtbegin.o`.
|
||||
\\# On Linux, can be found with `cc -print-file-name=crt1.o`.
|
||||
\\# Not needed when targeting MacOS or Windows.
|
||||
\\static_lib_dir={}
|
||||
\\
|
||||
\\# The directory that contains `vcruntime.lib`.
|
||||
\\# Only needed when targeting Windows.
|
||||
\\msvc_lib_dir={}
|
||||
\\
|
||||
\\# The directory that contains `kernel32.lib`.
|
||||
\\# Only needed when targeting Windows.
|
||||
\\kernel32_lib_dir={}
|
||||
\\
|
||||
\\# The full path to the dynamic linker.
|
||||
\\# Only needed when targeting Linux.
|
||||
\\dynamic_linker_path={}
|
||||
\\
|
||||
,
|
||||
self.include_dir,
|
||||
self.lib_dir orelse "",
|
||||
self.static_lib_dir orelse "",
|
||||
self.msvc_lib_dir orelse "",
|
||||
self.kernel32_lib_dir orelse "",
|
||||
self.dynamic_linker_path orelse Target(Target.Native).getDynamicLinkerPath(),
|
||||
);
|
||||
}
|
||||
|
||||
/// Finds the default, native libc.
|
||||
pub async fn findNative(self: *LibCInstallation, loop: *event.Loop) !void {
|
||||
self.* = LibCInstallation{
|
||||
.lib_dir = null,
|
||||
.include_dir = ([*]const u8)(undefined)[0..0],
|
||||
.static_lib_dir = null,
|
||||
.msvc_lib_dir = null,
|
||||
.kernel32_lib_dir = null,
|
||||
};
|
||||
var group = event.Group(Error!void).init(loop);
|
||||
self.initEmpty();
|
||||
var group = event.Group(FindError!void).init(loop);
|
||||
errdefer group.cancelAll();
|
||||
switch (builtin.os) {
|
||||
builtin.Os.windows => {
|
||||
try group.call(findNativeIncludeDirWindows, self, loop);
|
||||
|
@ -57,6 +152,7 @@ pub const LibCInstallation = struct {
|
|||
try group.call(findNativeIncludeDirLinux, self, loop);
|
||||
try group.call(findNativeLibDirLinux, self, loop);
|
||||
try group.call(findNativeStaticLibDir, self, loop);
|
||||
try group.call(findNativeDynamicLinker, self, loop);
|
||||
},
|
||||
builtin.Os.macosx => {
|
||||
try group.call(findNativeIncludeDirMacOS, self, loop);
|
||||
|
@ -147,7 +243,7 @@ pub const LibCInstallation = struct {
|
|||
self.include_dir = try std.mem.dupe(loop.allocator, u8, "/usr/include");
|
||||
}
|
||||
|
||||
async fn findNativeLibDirWindows(self: *LibCInstallation, loop: *event.Loop) Error!void {
|
||||
async fn findNativeLibDirWindows(self: *LibCInstallation, loop: *event.Loop) FindError!void {
|
||||
// TODO
|
||||
//ZigWindowsSDK *sdk = get_windows_sdk(g);
|
||||
|
||||
|
@ -180,31 +276,83 @@ pub const LibCInstallation = struct {
|
|||
@panic("TODO");
|
||||
}
|
||||
|
||||
async fn findNativeLibDirLinux(self: *LibCInstallation, loop: *event.Loop) Error!void {
|
||||
self.lib_dir = try await (async ccPrintFileNameDir(loop, "crt1.o") catch unreachable);
|
||||
async fn findNativeLibDirLinux(self: *LibCInstallation, loop: *event.Loop) FindError!void {
|
||||
self.lib_dir = try await (async ccPrintFileName(loop, "crt1.o", true) catch unreachable);
|
||||
}
|
||||
|
||||
async fn findNativeStaticLibDir(self: *LibCInstallation, loop: *event.Loop) Error!void {
|
||||
self.static_lib_dir = try await (async ccPrintFileNameDir(loop, "crtbegin.o") catch unreachable);
|
||||
async fn findNativeStaticLibDir(self: *LibCInstallation, loop: *event.Loop) FindError!void {
|
||||
self.static_lib_dir = try await (async ccPrintFileName(loop, "crtbegin.o", true) catch unreachable);
|
||||
}
|
||||
|
||||
async fn findNativeMsvcLibDir(self: *LibCInstallation, loop: *event.Loop) Error!void {
|
||||
async fn findNativeDynamicLinker(self: *LibCInstallation, loop: *event.Loop) FindError!void {
|
||||
var dyn_tests = []DynTest{
|
||||
DynTest{
|
||||
.name = "ld-linux-x86-64.so.2",
|
||||
.result = null,
|
||||
},
|
||||
DynTest{
|
||||
.name = "ld-musl-x86_64.so.1",
|
||||
.result = null,
|
||||
},
|
||||
};
|
||||
var group = event.Group(FindError!void).init(loop);
|
||||
errdefer group.cancelAll();
|
||||
for (dyn_tests) |*dyn_test| {
|
||||
try group.call(testNativeDynamicLinker, self, loop, dyn_test);
|
||||
}
|
||||
try await (async group.wait() catch unreachable);
|
||||
for (dyn_tests) |*dyn_test| {
|
||||
if (dyn_test.result) |result| {
|
||||
self.dynamic_linker_path = result;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const DynTest = struct {
|
||||
name: []const u8,
|
||||
result: ?[]const u8,
|
||||
};
|
||||
|
||||
async fn testNativeDynamicLinker(self: *LibCInstallation, loop: *event.Loop, dyn_test: *DynTest) FindError!void {
|
||||
if (await (async ccPrintFileName(loop, dyn_test.name, false) catch unreachable)) |result| {
|
||||
dyn_test.result = result;
|
||||
return;
|
||||
} else |err| switch (err) {
|
||||
error.CCompilerCannotFindCRuntime => return,
|
||||
else => return err,
|
||||
}
|
||||
}
|
||||
|
||||
async fn findNativeMsvcLibDir(self: *LibCInstallation, loop: *event.Loop) FindError!void {
|
||||
@panic("TODO");
|
||||
}
|
||||
|
||||
async fn findNativeKernel32LibDir(self: *LibCInstallation, loop: *event.Loop) Error!void {
|
||||
async fn findNativeKernel32LibDir(self: *LibCInstallation, loop: *event.Loop) FindError!void {
|
||||
@panic("TODO");
|
||||
}
|
||||
|
||||
fn initEmpty(self: *LibCInstallation) void {
|
||||
self.* = LibCInstallation{
|
||||
.include_dir = ([*]const u8)(undefined)[0..0],
|
||||
.lib_dir = null,
|
||||
.static_lib_dir = null,
|
||||
.msvc_lib_dir = null,
|
||||
.kernel32_lib_dir = null,
|
||||
.dynamic_linker_path = null,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// caller owns returned memory
|
||||
async fn ccPrintFileNameDir(loop: *event.Loop, o_file: []const u8) ![]u8 {
|
||||
async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bool) ![]u8 {
|
||||
const cc_exe = std.os.getEnvPosix("CC") orelse "cc";
|
||||
const arg1 = try std.fmt.allocPrint(loop.allocator, "-print-file-name={}", o_file);
|
||||
defer loop.allocator.free(arg1);
|
||||
const argv = []const []const u8{ cc_exe, arg1 };
|
||||
|
||||
// TODO evented I/O
|
||||
// TODO This simulates evented I/O for the child process exec
|
||||
await (async loop.yield() catch unreachable);
|
||||
const errorable_result = std.os.ChildProcess.exec(loop.allocator, argv, null, null, 1024 * 1024);
|
||||
const exec_result = if (std.debug.runtime_safety) blk: {
|
||||
break :blk errorable_result catch unreachable;
|
||||
|
@ -230,5 +378,9 @@ async fn ccPrintFileNameDir(loop: *event.Loop, o_file: []const u8) ![]u8 {
|
|||
const line = it.next() orelse return error.CCompilerCannotFindCRuntime;
|
||||
const dirname = std.os.path.dirname(line) orelse return error.CCompilerCannotFindCRuntime;
|
||||
|
||||
return std.mem.dupe(loop.allocator, u8, dirname);
|
||||
if (want_dirname) {
|
||||
return std.mem.dupe(loop.allocator, u8, dirname);
|
||||
} else {
|
||||
return std.mem.dupe(loop.allocator, u8, line);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ const c = @import("c.zig");
|
|||
const builtin = @import("builtin");
|
||||
const ObjectFormat = builtin.ObjectFormat;
|
||||
const Compilation = @import("compilation.zig").Compilation;
|
||||
const Target = @import("target.zig").Target;
|
||||
const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
|
||||
|
||||
const Context = struct {
|
||||
comp: *Compilation,
|
||||
|
@ -12,9 +14,12 @@ const Context = struct {
|
|||
|
||||
link_err: error{OutOfMemory}!void,
|
||||
link_msg: std.Buffer,
|
||||
|
||||
libc: *LibCInstallation,
|
||||
out_file_path: std.Buffer,
|
||||
};
|
||||
|
||||
pub fn link(comp: *Compilation) !void {
|
||||
pub async fn link(comp: *Compilation) !void {
|
||||
var ctx = Context{
|
||||
.comp = comp,
|
||||
.arena = std.heap.ArenaAllocator.init(comp.gpa()),
|
||||
|
@ -22,15 +27,45 @@ pub fn link(comp: *Compilation) !void {
|
|||
.link_in_crt = comp.haveLibC() and comp.kind == Compilation.Kind.Exe,
|
||||
.link_err = {},
|
||||
.link_msg = undefined,
|
||||
.libc = undefined,
|
||||
.out_file_path = undefined,
|
||||
};
|
||||
defer ctx.arena.deinit();
|
||||
ctx.args = std.ArrayList([*]const u8).init(&ctx.arena.allocator);
|
||||
ctx.link_msg = std.Buffer.initNull(&ctx.arena.allocator);
|
||||
|
||||
if (comp.link_out_file) |out_file| {
|
||||
ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, out_file);
|
||||
} else {
|
||||
ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, comp.name.toSliceConst());
|
||||
switch (comp.kind) {
|
||||
Compilation.Kind.Exe => {
|
||||
try ctx.out_file_path.append(comp.target.exeFileExt());
|
||||
},
|
||||
Compilation.Kind.Lib => {
|
||||
try ctx.out_file_path.append(comp.target.libFileExt(comp.is_static));
|
||||
},
|
||||
Compilation.Kind.Obj => {
|
||||
try ctx.out_file_path.append(comp.target.objFileExt());
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// even though we're calling LLD as a library it thinks the first
|
||||
// argument is its own exe name
|
||||
try ctx.args.append(c"lld");
|
||||
|
||||
if (comp.haveLibC()) {
|
||||
ctx.libc = ctx.comp.override_libc orelse blk: {
|
||||
switch (comp.target) {
|
||||
Target.Native => {
|
||||
break :blk (await (async comp.event_loop_local.getNativeLibC() catch unreachable)) catch return error.LibCRequiredButNotProvidedOrFound;
|
||||
},
|
||||
else => return error.LibCRequiredButNotProvidedOrFound,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
try constructLinkerArgs(&ctx);
|
||||
|
||||
if (comp.verbose_link) {
|
||||
|
@ -43,6 +78,7 @@ pub fn link(comp: *Compilation) !void {
|
|||
|
||||
const extern_ofmt = toExternObjectFormatType(comp.target.getObjectFormat());
|
||||
const args_slice = ctx.args.toSlice();
|
||||
// Not evented I/O. LLD does its own multithreading internally.
|
||||
if (!ZigLLDLink(extern_ofmt, args_slice.ptr, args_slice.len, linkDiagCallback, @ptrCast(*c_void, &ctx))) {
|
||||
if (!ctx.link_msg.isNull()) {
|
||||
// TODO capture these messages and pass them through the system, reporting them through the
|
||||
|
@ -95,10 +131,7 @@ fn constructLinkerArgs(ctx: *Context) !void {
|
|||
}
|
||||
|
||||
fn constructLinkerArgsElf(ctx: *Context) !void {
|
||||
//if (g->libc_link_lib != nullptr) {
|
||||
// find_libc_lib_path(g);
|
||||
//}
|
||||
|
||||
// TODO commented out code in this function
|
||||
//if (g->linker_script) {
|
||||
// lj->args.append("-T");
|
||||
// lj->args.append(g->linker_script);
|
||||
|
@ -107,7 +140,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
|
|||
//if (g->no_rosegment_workaround) {
|
||||
// lj->args.append("--no-rosegment");
|
||||
//}
|
||||
//lj->args.append("--gc-sections");
|
||||
try ctx.args.append(c"--gc-sections");
|
||||
|
||||
//lj->args.append("-m");
|
||||
//lj->args.append(getLDMOption(&g->zig_target));
|
||||
|
@ -115,14 +148,13 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
|
|||
//bool is_lib = g->out_type == OutTypeLib;
|
||||
//bool shared = !g->is_static && is_lib;
|
||||
//Buf *soname = nullptr;
|
||||
//if (g->is_static) {
|
||||
// if (g->zig_target.arch.arch == ZigLLVM_arm || g->zig_target.arch.arch == ZigLLVM_armeb ||
|
||||
// g->zig_target.arch.arch == ZigLLVM_thumb || g->zig_target.arch.arch == ZigLLVM_thumbeb)
|
||||
// {
|
||||
// lj->args.append("-Bstatic");
|
||||
// } else {
|
||||
// lj->args.append("-static");
|
||||
// }
|
||||
if (ctx.comp.is_static) {
|
||||
if (ctx.comp.target.isArmOrThumb()) {
|
||||
try ctx.args.append(c"-Bstatic");
|
||||
} else {
|
||||
try ctx.args.append(c"-static");
|
||||
}
|
||||
}
|
||||
//} else if (shared) {
|
||||
// lj->args.append("-shared");
|
||||
|
||||
|
@ -133,23 +165,16 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
|
|||
// soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize "", buf_ptr(g->root_out_name), g->version_major);
|
||||
//}
|
||||
|
||||
//lj->args.append("-o");
|
||||
//lj->args.append(buf_ptr(&lj->out_file));
|
||||
try ctx.args.append(c"-o");
|
||||
try ctx.args.append(ctx.out_file_path.ptr());
|
||||
|
||||
//if (lj->link_in_crt) {
|
||||
// const char *crt1o;
|
||||
// const char *crtbegino;
|
||||
// if (g->is_static) {
|
||||
// crt1o = "crt1.o";
|
||||
// crtbegino = "crtbeginT.o";
|
||||
// } else {
|
||||
// crt1o = "Scrt1.o";
|
||||
// crtbegino = "crtbegin.o";
|
||||
// }
|
||||
// lj->args.append(get_libc_file(g, crt1o));
|
||||
// lj->args.append(get_libc_file(g, "crti.o"));
|
||||
// lj->args.append(get_libc_static_file(g, crtbegino));
|
||||
//}
|
||||
if (ctx.link_in_crt) {
|
||||
const crt1o = if (ctx.comp.is_static) "crt1.o" else "Scrt1.o";
|
||||
const crtbegino = if (ctx.comp.is_static) "crtbeginT.o" else "crtbegin.o";
|
||||
try addPathJoin(ctx, ctx.libc.lib_dir.?, crt1o);
|
||||
try addPathJoin(ctx, ctx.libc.lib_dir.?, "crti.o");
|
||||
try addPathJoin(ctx, ctx.libc.static_lib_dir.?, crtbegino);
|
||||
}
|
||||
|
||||
//for (size_t i = 0; i < g->rpath_list.length; i += 1) {
|
||||
// Buf *rpath = g->rpath_list.at(i);
|
||||
|
@ -182,25 +207,23 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
|
|||
// lj->args.append(lib_dir);
|
||||
//}
|
||||
|
||||
//if (g->libc_link_lib != nullptr) {
|
||||
// lj->args.append("-L");
|
||||
// lj->args.append(buf_ptr(g->libc_lib_dir));
|
||||
if (ctx.comp.haveLibC()) {
|
||||
try ctx.args.append(c"-L");
|
||||
try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.lib_dir.?)).ptr);
|
||||
|
||||
// lj->args.append("-L");
|
||||
// lj->args.append(buf_ptr(g->libc_static_lib_dir));
|
||||
//}
|
||||
try ctx.args.append(c"-L");
|
||||
try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.static_lib_dir.?)).ptr);
|
||||
|
||||
//if (!g->is_static) {
|
||||
// if (g->dynamic_linker != nullptr) {
|
||||
// assert(buf_len(g->dynamic_linker) != 0);
|
||||
// lj->args.append("-dynamic-linker");
|
||||
// lj->args.append(buf_ptr(g->dynamic_linker));
|
||||
// } else {
|
||||
// Buf *resolved_dynamic_linker = get_dynamic_linker_path(g);
|
||||
// lj->args.append("-dynamic-linker");
|
||||
// lj->args.append(buf_ptr(resolved_dynamic_linker));
|
||||
// }
|
||||
//}
|
||||
if (!ctx.comp.is_static) {
|
||||
const dl = blk: {
|
||||
if (ctx.libc.dynamic_linker_path) |dl| break :blk dl;
|
||||
if (ctx.comp.target.getDynamicLinkerPath()) |dl| break :blk dl;
|
||||
return error.LibCMissingDynamicLinker;
|
||||
};
|
||||
try ctx.args.append(c"-dynamic-linker");
|
||||
try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, dl)).ptr);
|
||||
}
|
||||
}
|
||||
|
||||
//if (shared) {
|
||||
// lj->args.append("-soname");
|
||||
|
@ -241,45 +264,51 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
|
|||
// lj->args.append(buf_ptr(arg));
|
||||
//}
|
||||
|
||||
//// libc dep
|
||||
//if (g->libc_link_lib != nullptr) {
|
||||
// if (g->is_static) {
|
||||
// lj->args.append("--start-group");
|
||||
// lj->args.append("-lgcc");
|
||||
// lj->args.append("-lgcc_eh");
|
||||
// lj->args.append("-lc");
|
||||
// lj->args.append("-lm");
|
||||
// lj->args.append("--end-group");
|
||||
// } else {
|
||||
// lj->args.append("-lgcc");
|
||||
// lj->args.append("--as-needed");
|
||||
// lj->args.append("-lgcc_s");
|
||||
// lj->args.append("--no-as-needed");
|
||||
// lj->args.append("-lc");
|
||||
// lj->args.append("-lm");
|
||||
// lj->args.append("-lgcc");
|
||||
// lj->args.append("--as-needed");
|
||||
// lj->args.append("-lgcc_s");
|
||||
// lj->args.append("--no-as-needed");
|
||||
// }
|
||||
//}
|
||||
// libc dep
|
||||
if (ctx.comp.haveLibC()) {
|
||||
if (ctx.comp.is_static) {
|
||||
try ctx.args.append(c"--start-group");
|
||||
try ctx.args.append(c"-lgcc");
|
||||
try ctx.args.append(c"-lgcc_eh");
|
||||
try ctx.args.append(c"-lc");
|
||||
try ctx.args.append(c"-lm");
|
||||
try ctx.args.append(c"--end-group");
|
||||
} else {
|
||||
try ctx.args.append(c"-lgcc");
|
||||
try ctx.args.append(c"--as-needed");
|
||||
try ctx.args.append(c"-lgcc_s");
|
||||
try ctx.args.append(c"--no-as-needed");
|
||||
try ctx.args.append(c"-lc");
|
||||
try ctx.args.append(c"-lm");
|
||||
try ctx.args.append(c"-lgcc");
|
||||
try ctx.args.append(c"--as-needed");
|
||||
try ctx.args.append(c"-lgcc_s");
|
||||
try ctx.args.append(c"--no-as-needed");
|
||||
}
|
||||
}
|
||||
|
||||
//// crt end
|
||||
//if (lj->link_in_crt) {
|
||||
// lj->args.append(get_libc_static_file(g, "crtend.o"));
|
||||
// lj->args.append(get_libc_file(g, "crtn.o"));
|
||||
//}
|
||||
// crt end
|
||||
if (ctx.link_in_crt) {
|
||||
try addPathJoin(ctx, ctx.libc.static_lib_dir.?, "crtend.o");
|
||||
try addPathJoin(ctx, ctx.libc.lib_dir.?, "crtn.o");
|
||||
}
|
||||
|
||||
//if (!g->is_native_target) {
|
||||
// lj->args.append("--allow-shlib-undefined");
|
||||
//}
|
||||
if (ctx.comp.target != Target.Native) {
|
||||
try ctx.args.append(c"--allow-shlib-undefined");
|
||||
}
|
||||
|
||||
//if (g->zig_target.os == OsZen) {
|
||||
// lj->args.append("-e");
|
||||
// lj->args.append("_start");
|
||||
if (ctx.comp.target.getOs() == builtin.Os.zen) {
|
||||
try ctx.args.append(c"-e");
|
||||
try ctx.args.append(c"_start");
|
||||
|
||||
// lj->args.append("--image-base=0x10000000");
|
||||
//}
|
||||
try ctx.args.append(c"--image-base=0x10000000");
|
||||
}
|
||||
}
|
||||
|
||||
fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void {
|
||||
const full_path = try std.os.path.join(&ctx.arena.allocator, dirname, basename);
|
||||
const full_path_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, full_path);
|
||||
try ctx.args.append(full_path_with_null.ptr);
|
||||
}
|
||||
|
||||
fn constructLinkerArgsCoff(ctx: *Context) void {
|
||||
|
|
|
@ -18,6 +18,7 @@ const EventLoopLocal = @import("compilation.zig").EventLoopLocal;
|
|||
const Compilation = @import("compilation.zig").Compilation;
|
||||
const Target = @import("target.zig").Target;
|
||||
const errmsg = @import("errmsg.zig");
|
||||
const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
|
||||
|
||||
var stderr_file: os.File = undefined;
|
||||
var stderr: *io.OutStream(io.FileOutStream.Error) = undefined;
|
||||
|
@ -28,14 +29,14 @@ const usage =
|
|||
\\
|
||||
\\Commands:
|
||||
\\
|
||||
\\ build-exe [source] Create executable from source or object files
|
||||
\\ build-lib [source] Create library from source or object files
|
||||
\\ build-obj [source] Create object from source or assembly
|
||||
\\ find-libc Show native libc installation paths
|
||||
\\ fmt [source] Parse file and render in canonical zig format
|
||||
\\ targets List available compilation targets
|
||||
\\ version Print version number and exit
|
||||
\\ zen Print zen of zig and exit
|
||||
\\ build-exe [source] Create executable from source or object files
|
||||
\\ build-lib [source] Create library from source or object files
|
||||
\\ build-obj [source] Create object from source or assembly
|
||||
\\ fmt [source] Parse file and render in canonical zig format
|
||||
\\ libc [paths_file] Display native libc paths file or validate one
|
||||
\\ targets List available compilation targets
|
||||
\\ version Print version number and exit
|
||||
\\ zen Print zen of zig and exit
|
||||
\\
|
||||
\\
|
||||
;
|
||||
|
@ -82,14 +83,14 @@ pub fn main() !void {
|
|||
.name = "build-obj",
|
||||
.exec = cmdBuildObj,
|
||||
},
|
||||
Command{
|
||||
.name = "find-libc",
|
||||
.exec = cmdFindLibc,
|
||||
},
|
||||
Command{
|
||||
.name = "fmt",
|
||||
.exec = cmdFmt,
|
||||
},
|
||||
Command{
|
||||
.name = "libc",
|
||||
.exec = cmdLibC,
|
||||
},
|
||||
Command{
|
||||
.name = "targets",
|
||||
.exec = cmdTargets,
|
||||
|
@ -135,6 +136,7 @@ const usage_build_generic =
|
|||
\\ --color [auto|off|on] Enable or disable colored error messages
|
||||
\\
|
||||
\\Compile Options:
|
||||
\\ --libc [file] Provide a file which specifies libc paths
|
||||
\\ --assembly [source] Add assembly file to build
|
||||
\\ --cache-dir [path] Override the cache directory
|
||||
\\ --emit [filetype] Emit a specific file format as compilation output
|
||||
|
@ -167,7 +169,6 @@ const usage_build_generic =
|
|||
\\
|
||||
\\Link Options:
|
||||
\\ --ar-path [path] Set the path to ar
|
||||
\\ --dynamic-linker [path] Set the path to ld.so
|
||||
\\ --each-lib-rpath Add rpath for each used dynamic library
|
||||
\\ --library [lib] Link against lib
|
||||
\\ --forbid-library [lib] Make it an error to link against lib
|
||||
|
@ -210,6 +211,7 @@ const args_build_generic = []Flag{
|
|||
"llvm-ir",
|
||||
}),
|
||||
Flag.Bool("--enable-timing-info"),
|
||||
Flag.Arg1("--libc"),
|
||||
Flag.Arg1("--name"),
|
||||
Flag.Arg1("--output"),
|
||||
Flag.Arg1("--output-h"),
|
||||
|
@ -233,7 +235,6 @@ const args_build_generic = []Flag{
|
|||
Flag.Arg1("-mllvm"),
|
||||
|
||||
Flag.Arg1("--ar-path"),
|
||||
Flag.Arg1("--dynamic-linker"),
|
||||
Flag.Bool("--each-lib-rpath"),
|
||||
Flag.ArgMergeN("--library", 1),
|
||||
Flag.ArgMergeN("--forbid-library", 1),
|
||||
|
@ -382,6 +383,8 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
|
|||
const zig_lib_dir = introspect.resolveZigLibDir(allocator) catch os.exit(1);
|
||||
defer allocator.free(zig_lib_dir);
|
||||
|
||||
var override_libc: LibCInstallation = undefined;
|
||||
|
||||
var loop: event.Loop = undefined;
|
||||
try loop.initMultiThreaded(allocator);
|
||||
defer loop.deinit();
|
||||
|
@ -402,6 +405,15 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
|
|||
);
|
||||
defer comp.destroy();
|
||||
|
||||
if (flags.single("libc")) |libc_path| {
|
||||
parseLibcPaths(loop.allocator, &override_libc, libc_path);
|
||||
comp.override_libc = &override_libc;
|
||||
}
|
||||
|
||||
for (flags.many("library")) |lib| {
|
||||
_ = try comp.addLinkLib(lib, true);
|
||||
}
|
||||
|
||||
comp.version_major = try std.fmt.parseUnsigned(u32, flags.single("ver-major") orelse "0", 10);
|
||||
comp.version_minor = try std.fmt.parseUnsigned(u32, flags.single("ver-minor") orelse "0", 10);
|
||||
comp.version_patch = try std.fmt.parseUnsigned(u32, flags.single("ver-patch") orelse "0", 10);
|
||||
|
@ -425,10 +437,6 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
|
|||
|
||||
comp.strip = flags.present("strip");
|
||||
|
||||
if (flags.single("dynamic-linker")) |dynamic_linker| {
|
||||
comp.dynamic_linker = dynamic_linker;
|
||||
}
|
||||
|
||||
comp.verbose_tokenize = flags.present("verbose-tokenize");
|
||||
comp.verbose_ast_tree = flags.present("verbose-ast-tree");
|
||||
comp.verbose_ast_fmt = flags.present("verbose-ast-fmt");
|
||||
|
@ -479,7 +487,6 @@ async fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {
|
|||
|
||||
switch (build_event) {
|
||||
Compilation.Event.Ok => {
|
||||
std.debug.warn("Build succeeded\n");
|
||||
return;
|
||||
},
|
||||
Compilation.Event.Error => |err| {
|
||||
|
@ -559,7 +566,32 @@ const Fmt = struct {
|
|||
}
|
||||
};
|
||||
|
||||
fn cmdFindLibc(allocator: *Allocator, args: []const []const u8) !void {
|
||||
fn parseLibcPaths(allocator: *Allocator, libc: *LibCInstallation, libc_paths_file: []const u8) void {
|
||||
libc.parse(allocator, libc_paths_file, stderr) catch |err| {
|
||||
stderr.print(
|
||||
"Unable to parse libc path file '{}': {}.\n" ++
|
||||
"Try running `zig libc` to see an example for the native target.\n",
|
||||
libc_paths_file,
|
||||
@errorName(err),
|
||||
) catch os.exit(1);
|
||||
os.exit(1);
|
||||
};
|
||||
}
|
||||
|
||||
fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {
|
||||
switch (args.len) {
|
||||
0 => {},
|
||||
1 => {
|
||||
var libc_installation: LibCInstallation = undefined;
|
||||
parseLibcPaths(allocator, &libc_installation, args[0]);
|
||||
return;
|
||||
},
|
||||
else => {
|
||||
try stderr.print("unexpected extra parameter: {}\n", args[1]);
|
||||
os.exit(1);
|
||||
},
|
||||
}
|
||||
|
||||
var loop: event.Loop = undefined;
|
||||
try loop.initMultiThreaded(allocator);
|
||||
defer loop.deinit();
|
||||
|
@ -578,20 +610,7 @@ async fn findLibCAsync(event_loop_local: *EventLoopLocal) void {
|
|||
stderr.print("unable to find libc: {}\n", @errorName(err)) catch os.exit(1);
|
||||
os.exit(1);
|
||||
};
|
||||
stderr.print(
|
||||
\\include_dir={}
|
||||
\\lib_dir={}
|
||||
\\static_lib_dir={}
|
||||
\\msvc_lib_dir={}
|
||||
\\kernel32_lib_dir={}
|
||||
\\
|
||||
,
|
||||
libc.include_dir,
|
||||
libc.lib_dir,
|
||||
libc.static_lib_dir orelse "",
|
||||
libc.msvc_lib_dir orelse "",
|
||||
libc.kernel32_lib_dir orelse "",
|
||||
) catch os.exit(1);
|
||||
libc.render(stdout) catch os.exit(1);
|
||||
}
|
||||
|
||||
fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
|
||||
|
|
|
@ -2,6 +2,12 @@ const std = @import("std");
|
|||
const builtin = @import("builtin");
|
||||
const llvm = @import("llvm.zig");
|
||||
|
||||
pub const FloatAbi = enum {
|
||||
Hard,
|
||||
Soft,
|
||||
SoftFp,
|
||||
};
|
||||
|
||||
pub const Target = union(enum) {
|
||||
Native,
|
||||
Cross: Cross,
|
||||
|
@ -13,7 +19,7 @@ pub const Target = union(enum) {
|
|||
object_format: builtin.ObjectFormat,
|
||||
};
|
||||
|
||||
pub fn oFileExt(self: Target) []const u8 {
|
||||
pub fn objFileExt(self: Target) []const u8 {
|
||||
return switch (self.getObjectFormat()) {
|
||||
builtin.ObjectFormat.coff => ".obj",
|
||||
else => ".o",
|
||||
|
@ -27,6 +33,13 @@ pub const Target = union(enum) {
|
|||
};
|
||||
}
|
||||
|
||||
pub fn libFileExt(self: Target, is_static: bool) []const u8 {
|
||||
return switch (self.getOs()) {
|
||||
builtin.Os.windows => if (is_static) ".lib" else ".dll",
|
||||
else => if (is_static) ".a" else ".so",
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getOs(self: Target) builtin.Os {
|
||||
return switch (self) {
|
||||
Target.Native => builtin.os,
|
||||
|
@ -76,6 +89,56 @@ pub const Target = union(enum) {
|
|||
};
|
||||
}
|
||||
|
||||
/// TODO expose the arch and subarch separately
|
||||
pub fn isArmOrThumb(self: Target) bool {
|
||||
return switch (self.getArch()) {
|
||||
builtin.Arch.armv8_3a,
|
||||
builtin.Arch.armv8_2a,
|
||||
builtin.Arch.armv8_1a,
|
||||
builtin.Arch.armv8,
|
||||
builtin.Arch.armv8r,
|
||||
builtin.Arch.armv8m_baseline,
|
||||
builtin.Arch.armv8m_mainline,
|
||||
builtin.Arch.armv7,
|
||||
builtin.Arch.armv7em,
|
||||
builtin.Arch.armv7m,
|
||||
builtin.Arch.armv7s,
|
||||
builtin.Arch.armv7k,
|
||||
builtin.Arch.armv7ve,
|
||||
builtin.Arch.armv6,
|
||||
builtin.Arch.armv6m,
|
||||
builtin.Arch.armv6k,
|
||||
builtin.Arch.armv6t2,
|
||||
builtin.Arch.armv5,
|
||||
builtin.Arch.armv5te,
|
||||
builtin.Arch.armv4t,
|
||||
builtin.Arch.armebv8_3a,
|
||||
builtin.Arch.armebv8_2a,
|
||||
builtin.Arch.armebv8_1a,
|
||||
builtin.Arch.armebv8,
|
||||
builtin.Arch.armebv8r,
|
||||
builtin.Arch.armebv8m_baseline,
|
||||
builtin.Arch.armebv8m_mainline,
|
||||
builtin.Arch.armebv7,
|
||||
builtin.Arch.armebv7em,
|
||||
builtin.Arch.armebv7m,
|
||||
builtin.Arch.armebv7s,
|
||||
builtin.Arch.armebv7k,
|
||||
builtin.Arch.armebv7ve,
|
||||
builtin.Arch.armebv6,
|
||||
builtin.Arch.armebv6m,
|
||||
builtin.Arch.armebv6k,
|
||||
builtin.Arch.armebv6t2,
|
||||
builtin.Arch.armebv5,
|
||||
builtin.Arch.armebv5te,
|
||||
builtin.Arch.armebv4t,
|
||||
builtin.Arch.thumb,
|
||||
builtin.Arch.thumbeb,
|
||||
=> true,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn initializeAll() void {
|
||||
llvm.InitializeAllTargets();
|
||||
llvm.InitializeAllTargetInfos();
|
||||
|
@ -106,6 +169,257 @@ pub const Target = union(enum) {
|
|||
return result;
|
||||
}
|
||||
|
||||
pub fn is64bit(self: Target) bool {
|
||||
return self.getArchPtrBitWidth() == 64;
|
||||
}
|
||||
|
||||
pub fn getArchPtrBitWidth(self: Target) u8 {
|
||||
switch (self.getArch()) {
|
||||
builtin.Arch.avr,
|
||||
builtin.Arch.msp430,
|
||||
=> return 16,
|
||||
|
||||
builtin.Arch.arc,
|
||||
builtin.Arch.armv8_3a,
|
||||
builtin.Arch.armv8_2a,
|
||||
builtin.Arch.armv8_1a,
|
||||
builtin.Arch.armv8,
|
||||
builtin.Arch.armv8r,
|
||||
builtin.Arch.armv8m_baseline,
|
||||
builtin.Arch.armv8m_mainline,
|
||||
builtin.Arch.armv7,
|
||||
builtin.Arch.armv7em,
|
||||
builtin.Arch.armv7m,
|
||||
builtin.Arch.armv7s,
|
||||
builtin.Arch.armv7k,
|
||||
builtin.Arch.armv7ve,
|
||||
builtin.Arch.armv6,
|
||||
builtin.Arch.armv6m,
|
||||
builtin.Arch.armv6k,
|
||||
builtin.Arch.armv6t2,
|
||||
builtin.Arch.armv5,
|
||||
builtin.Arch.armv5te,
|
||||
builtin.Arch.armv4t,
|
||||
builtin.Arch.armebv8_3a,
|
||||
builtin.Arch.armebv8_2a,
|
||||
builtin.Arch.armebv8_1a,
|
||||
builtin.Arch.armebv8,
|
||||
builtin.Arch.armebv8r,
|
||||
builtin.Arch.armebv8m_baseline,
|
||||
builtin.Arch.armebv8m_mainline,
|
||||
builtin.Arch.armebv7,
|
||||
builtin.Arch.armebv7em,
|
||||
builtin.Arch.armebv7m,
|
||||
builtin.Arch.armebv7s,
|
||||
builtin.Arch.armebv7k,
|
||||
builtin.Arch.armebv7ve,
|
||||
builtin.Arch.armebv6,
|
||||
builtin.Arch.armebv6m,
|
||||
builtin.Arch.armebv6k,
|
||||
builtin.Arch.armebv6t2,
|
||||
builtin.Arch.armebv5,
|
||||
builtin.Arch.armebv5te,
|
||||
builtin.Arch.armebv4t,
|
||||
builtin.Arch.hexagon,
|
||||
builtin.Arch.le32,
|
||||
builtin.Arch.mips,
|
||||
builtin.Arch.mipsel,
|
||||
builtin.Arch.nios2,
|
||||
builtin.Arch.powerpc,
|
||||
builtin.Arch.r600,
|
||||
builtin.Arch.riscv32,
|
||||
builtin.Arch.sparc,
|
||||
builtin.Arch.sparcel,
|
||||
builtin.Arch.tce,
|
||||
builtin.Arch.tcele,
|
||||
builtin.Arch.thumb,
|
||||
builtin.Arch.thumbeb,
|
||||
builtin.Arch.i386,
|
||||
builtin.Arch.xcore,
|
||||
builtin.Arch.nvptx,
|
||||
builtin.Arch.amdil,
|
||||
builtin.Arch.hsail,
|
||||
builtin.Arch.spir,
|
||||
builtin.Arch.kalimbav3,
|
||||
builtin.Arch.kalimbav4,
|
||||
builtin.Arch.kalimbav5,
|
||||
builtin.Arch.shave,
|
||||
builtin.Arch.lanai,
|
||||
builtin.Arch.wasm32,
|
||||
builtin.Arch.renderscript32,
|
||||
=> return 32,
|
||||
|
||||
builtin.Arch.aarch64,
|
||||
builtin.Arch.aarch64_be,
|
||||
builtin.Arch.mips64,
|
||||
builtin.Arch.mips64el,
|
||||
builtin.Arch.powerpc64,
|
||||
builtin.Arch.powerpc64le,
|
||||
builtin.Arch.riscv64,
|
||||
builtin.Arch.x86_64,
|
||||
builtin.Arch.nvptx64,
|
||||
builtin.Arch.le64,
|
||||
builtin.Arch.amdil64,
|
||||
builtin.Arch.hsail64,
|
||||
builtin.Arch.spir64,
|
||||
builtin.Arch.wasm64,
|
||||
builtin.Arch.renderscript64,
|
||||
builtin.Arch.amdgcn,
|
||||
builtin.Arch.bpfel,
|
||||
builtin.Arch.bpfeb,
|
||||
builtin.Arch.sparcv9,
|
||||
builtin.Arch.s390x,
|
||||
=> return 64,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getFloatAbi(self: Target) FloatAbi {
|
||||
return switch (self.getEnviron()) {
|
||||
builtin.Environ.gnueabihf,
|
||||
builtin.Environ.eabihf,
|
||||
builtin.Environ.musleabihf,
|
||||
=> FloatAbi.Hard,
|
||||
else => FloatAbi.Soft,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn getDynamicLinkerPath(self: Target) ?[]const u8 {
|
||||
const env = self.getEnviron();
|
||||
const arch = self.getArch();
|
||||
switch (env) {
|
||||
builtin.Environ.android => {
|
||||
if (self.is64bit()) {
|
||||
return "/system/bin/linker64";
|
||||
} else {
|
||||
return "/system/bin/linker";
|
||||
}
|
||||
},
|
||||
builtin.Environ.gnux32 => {
|
||||
if (arch == builtin.Arch.x86_64) {
|
||||
return "/libx32/ld-linux-x32.so.2";
|
||||
}
|
||||
},
|
||||
builtin.Environ.musl,
|
||||
builtin.Environ.musleabi,
|
||||
builtin.Environ.musleabihf,
|
||||
=> {
|
||||
if (arch == builtin.Arch.x86_64) {
|
||||
return "/lib/ld-musl-x86_64.so.1";
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
switch (arch) {
|
||||
builtin.Arch.i386,
|
||||
builtin.Arch.sparc,
|
||||
builtin.Arch.sparcel,
|
||||
=> return "/lib/ld-linux.so.2",
|
||||
|
||||
builtin.Arch.aarch64 => return "/lib/ld-linux-aarch64.so.1",
|
||||
builtin.Arch.aarch64_be => return "/lib/ld-linux-aarch64_be.so.1",
|
||||
|
||||
builtin.Arch.armv8_3a,
|
||||
builtin.Arch.armv8_2a,
|
||||
builtin.Arch.armv8_1a,
|
||||
builtin.Arch.armv8,
|
||||
builtin.Arch.armv8r,
|
||||
builtin.Arch.armv8m_baseline,
|
||||
builtin.Arch.armv8m_mainline,
|
||||
builtin.Arch.armv7,
|
||||
builtin.Arch.armv7em,
|
||||
builtin.Arch.armv7m,
|
||||
builtin.Arch.armv7s,
|
||||
builtin.Arch.armv7k,
|
||||
builtin.Arch.armv7ve,
|
||||
builtin.Arch.armv6,
|
||||
builtin.Arch.armv6m,
|
||||
builtin.Arch.armv6k,
|
||||
builtin.Arch.armv6t2,
|
||||
builtin.Arch.armv5,
|
||||
builtin.Arch.armv5te,
|
||||
builtin.Arch.armv4t,
|
||||
builtin.Arch.thumb,
|
||||
=> return switch (self.getFloatAbi()) {
|
||||
FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3",
|
||||
else => return "/lib/ld-linux.so.3",
|
||||
},
|
||||
|
||||
builtin.Arch.armebv8_3a,
|
||||
builtin.Arch.armebv8_2a,
|
||||
builtin.Arch.armebv8_1a,
|
||||
builtin.Arch.armebv8,
|
||||
builtin.Arch.armebv8r,
|
||||
builtin.Arch.armebv8m_baseline,
|
||||
builtin.Arch.armebv8m_mainline,
|
||||
builtin.Arch.armebv7,
|
||||
builtin.Arch.armebv7em,
|
||||
builtin.Arch.armebv7m,
|
||||
builtin.Arch.armebv7s,
|
||||
builtin.Arch.armebv7k,
|
||||
builtin.Arch.armebv7ve,
|
||||
builtin.Arch.armebv6,
|
||||
builtin.Arch.armebv6m,
|
||||
builtin.Arch.armebv6k,
|
||||
builtin.Arch.armebv6t2,
|
||||
builtin.Arch.armebv5,
|
||||
builtin.Arch.armebv5te,
|
||||
builtin.Arch.armebv4t,
|
||||
builtin.Arch.thumbeb,
|
||||
=> return switch (self.getFloatAbi()) {
|
||||
FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3",
|
||||
else => return "/lib/ld-linux.so.3",
|
||||
},
|
||||
|
||||
builtin.Arch.mips,
|
||||
builtin.Arch.mipsel,
|
||||
builtin.Arch.mips64,
|
||||
builtin.Arch.mips64el,
|
||||
=> return null,
|
||||
|
||||
builtin.Arch.powerpc => return "/lib/ld.so.1",
|
||||
builtin.Arch.powerpc64 => return "/lib64/ld64.so.2",
|
||||
builtin.Arch.powerpc64le => return "/lib64/ld64.so.2",
|
||||
builtin.Arch.s390x => return "/lib64/ld64.so.1",
|
||||
builtin.Arch.sparcv9 => return "/lib64/ld-linux.so.2",
|
||||
builtin.Arch.x86_64 => return "/lib64/ld-linux-x86-64.so.2",
|
||||
|
||||
builtin.Arch.arc,
|
||||
builtin.Arch.avr,
|
||||
builtin.Arch.bpfel,
|
||||
builtin.Arch.bpfeb,
|
||||
builtin.Arch.hexagon,
|
||||
builtin.Arch.msp430,
|
||||
builtin.Arch.nios2,
|
||||
builtin.Arch.r600,
|
||||
builtin.Arch.amdgcn,
|
||||
builtin.Arch.riscv32,
|
||||
builtin.Arch.riscv64,
|
||||
builtin.Arch.tce,
|
||||
builtin.Arch.tcele,
|
||||
builtin.Arch.xcore,
|
||||
builtin.Arch.nvptx,
|
||||
builtin.Arch.nvptx64,
|
||||
builtin.Arch.le32,
|
||||
builtin.Arch.le64,
|
||||
builtin.Arch.amdil,
|
||||
builtin.Arch.amdil64,
|
||||
builtin.Arch.hsail,
|
||||
builtin.Arch.hsail64,
|
||||
builtin.Arch.spir,
|
||||
builtin.Arch.spir64,
|
||||
builtin.Arch.kalimbav3,
|
||||
builtin.Arch.kalimbav4,
|
||||
builtin.Arch.kalimbav5,
|
||||
builtin.Arch.shave,
|
||||
builtin.Arch.lanai,
|
||||
builtin.Arch.wasm32,
|
||||
builtin.Arch.wasm64,
|
||||
builtin.Arch.renderscript32,
|
||||
builtin.Arch.renderscript64,
|
||||
=> return null,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn llvmTargetFromTriple(triple: std.Buffer) !llvm.TargetRef {
|
||||
var result: llvm.TargetRef = undefined;
|
||||
var err_msg: [*]u8 = undefined;
|
||||
|
|
|
@ -6,7 +6,7 @@ const AtomicRmwOp = builtin.AtomicRmwOp;
|
|||
const AtomicOrder = builtin.AtomicOrder;
|
||||
const assert = std.debug.assert;
|
||||
|
||||
/// ReturnType should be `void` or `E!void`
|
||||
/// ReturnType must be `void` or `E!void`
|
||||
pub fn Group(comptime ReturnType: type) type {
|
||||
return struct {
|
||||
coro_stack: Stack,
|
||||
|
@ -39,7 +39,7 @@ pub fn Group(comptime ReturnType: type) type {
|
|||
}
|
||||
|
||||
/// This is equivalent to an async call, but the async function is added to the group, instead
|
||||
/// of returning a promise. func must be async and have return type void.
|
||||
/// of returning a promise. func must be async and have return type ReturnType.
|
||||
/// Thread-safe.
|
||||
pub fn call(self: *Self, comptime func: var, args: ...) (error{OutOfMemory}!void) {
|
||||
const S = struct {
|
||||
|
|
|
@ -444,7 +444,7 @@ pub const Loop = struct {
|
|||
.next = undefined,
|
||||
.data = p,
|
||||
};
|
||||
loop.onNextTick(&my_tick_node);
|
||||
self.onNextTick(&my_tick_node);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue