Improve clang integration
LLVM can now be compiled with nat
This commit is contained in:
parent
f245b28ed8
commit
dfcda18a70
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,6 @@
|
||||
zig-cache/
|
||||
zig-out/
|
||||
nat/
|
||||
*.o
|
||||
*.out
|
||||
*.obj
|
||||
|
@ -6,6 +6,8 @@ const data_structures = @import("library.zig");
|
||||
const assert = data_structures.assert;
|
||||
const byte_equal = data_structures.byte_equal;
|
||||
const byte_equal_terminated = data_structures.byte_equal_terminated;
|
||||
const first_slice = data_structures.first_slice;
|
||||
const starts_with_slice = data_structures.starts_with_slice;
|
||||
const UnpinnedArray = data_structures.UnpinnedArray;
|
||||
const BlockList = data_structures.BlockList;
|
||||
const MyAllocator = data_structures.MyAllocator;
|
||||
@ -17,6 +19,7 @@ const lexer = @import("frontend/lexer.zig");
|
||||
const parser = @import("frontend/parser.zig");
|
||||
const Node = parser.Node;
|
||||
const llvm = @import("backend/llvm.zig");
|
||||
const linker = @import("linker/linker.zig");
|
||||
const cache_dir_name = "cache";
|
||||
const installation_dir_name = "installation";
|
||||
|
||||
@ -59,7 +62,7 @@ pub fn createContext(allocator: Allocator, my_allocator: *MyAllocator) !*const C
|
||||
return context;
|
||||
}
|
||||
|
||||
pub fn compileBuildExecutable(context: *const Context, arguments: [][*:0]u8) !void {
|
||||
pub fn compileBuildExecutable(context: *const Context, arguments: []const []const u8) !void {
|
||||
_ = arguments; // autofix
|
||||
const unit = try context.my_allocator.allocate_one(Unit);
|
||||
unit.* = .{
|
||||
@ -83,7 +86,9 @@ pub fn compileBuildExecutable(context: *const Context, arguments: [][*:0]u8) !vo
|
||||
},
|
||||
.only_parse = false,
|
||||
.executable_path = "nat/build",
|
||||
.object_path = "nat/build.o",
|
||||
.link_libc = @import("builtin").os.tag == .macos,
|
||||
.link_libcpp = false,
|
||||
.generate_debug_information = true,
|
||||
.name = "build",
|
||||
.is_test = false,
|
||||
@ -263,126 +268,608 @@ fn compileMusl(context: *const Context) MuslContext{
|
||||
return musl;
|
||||
}
|
||||
|
||||
pub fn compileCSourceFile(context: *const Context, arguments: [][*:0]u8, kind: CSourceKind) !void {
|
||||
var clang_args = UnpinnedArray([]const u8){};
|
||||
try clang_args.append(context.my_allocator, context.executable_absolute_path);
|
||||
try clang_args.append(context.my_allocator, "clang");
|
||||
|
||||
pub fn compileCSourceFile(context: *const Context, arguments: []const []const u8, kind: CSourceKind) !void {
|
||||
_ = kind; // autofix
|
||||
var argument_index: usize = 0;
|
||||
_ = &argument_index;
|
||||
const Mode = enum{
|
||||
object,
|
||||
link,
|
||||
};
|
||||
const mode: Mode = for (arguments) |argz| {
|
||||
const arg = span(argz);
|
||||
if (byte_equal(arg, "-c")) break .object;
|
||||
} else .link;
|
||||
_ = mode; // autofix
|
||||
var out_path: ?[]const u8 = null;
|
||||
var out_mode: ?Mode = null;
|
||||
const Extension = enum{
|
||||
c,
|
||||
cpp,
|
||||
assembly,
|
||||
object,
|
||||
static_library,
|
||||
shared_library,
|
||||
};
|
||||
const CSourceFile = struct{
|
||||
path: []const u8,
|
||||
extension: Extension,
|
||||
};
|
||||
const DebugInfo = enum{
|
||||
yes,
|
||||
no,
|
||||
};
|
||||
const LinkArch = enum{
|
||||
arm64,
|
||||
};
|
||||
var debug_info: ?DebugInfo = null;
|
||||
var stack_protector: ?bool = null;
|
||||
var link_arch: ?LinkArch = null;
|
||||
|
||||
if (kind == .cpp) {
|
||||
try clang_args.append(context.my_allocator, "-nostdinc++");
|
||||
var cc_argv = UnpinnedArray([]const u8){};
|
||||
var ld_argv = UnpinnedArray([]const u8){};
|
||||
var c_source_files = UnpinnedArray(CSourceFile){};
|
||||
var link_objects = UnpinnedArray(linker.Object){};
|
||||
var link_libraries = UnpinnedArray(linker.Library){};
|
||||
|
||||
switch (@import("builtin").os.tag) {
|
||||
.linux => {
|
||||
switch (@import("builtin").abi) {
|
||||
.gnu => {
|
||||
try clang_args.append_slice(context.my_allocator, &.{
|
||||
"-isystem", "/usr/include/c++/13.2.1",
|
||||
"-isystem", "/usr/include/c++/13.2.1/x86_64-pc-linux-gnu",
|
||||
while (argument_index < arguments.len) {
|
||||
const argument = arguments[argument_index];
|
||||
|
||||
if (argument[0] != '-') {
|
||||
if (data_structures.last_byte(argument, '.')) |dot_index| {
|
||||
const extension_string = argument[dot_index..];
|
||||
const extension: Extension =
|
||||
if (byte_equal(extension_string, ".c")) .c
|
||||
else if (byte_equal(extension_string, ".cpp") or byte_equal(extension_string, ".cxx") or byte_equal(extension_string, ".cc")) .cpp
|
||||
else if (byte_equal(extension_string, ".S")) .assembly
|
||||
else if (byte_equal(extension_string, ".o")) .object
|
||||
else if (byte_equal(extension_string, ".a")) .static_library
|
||||
else if (byte_equal(extension_string, ".so") or
|
||||
byte_equal(extension_string, ".dll") or
|
||||
byte_equal(extension_string, ".dylib") or
|
||||
byte_equal(extension_string, ".tbd")
|
||||
) .shared_library
|
||||
else {
|
||||
try write(.panic, argument);
|
||||
try write(.panic, "\n");
|
||||
@panic("Unable to recognize extension for the file above");
|
||||
};
|
||||
switch (extension) {
|
||||
.c, .cpp, .assembly => {
|
||||
try c_source_files.append(context.my_allocator, .{
|
||||
.path = argument,
|
||||
.extension = extension,
|
||||
});
|
||||
},
|
||||
.musl => {
|
||||
try clang_args.append_slice(context.my_allocator, &.{
|
||||
"-isystem", try context.pathFromCompiler("lib/libcxx/include"),
|
||||
"-isystem", try context.pathFromCompiler("lib/libcxxabi/include"),
|
||||
"-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
|
||||
"-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
|
||||
"-D_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS",
|
||||
"-D_LIBCPP_PSTL_CPU_BACKEND_SERIAL",
|
||||
"-D_LIBCPP_ABI_VERSION=1",
|
||||
"-D_LIBCPP_ABI_NAMESPACE=__1",
|
||||
.object, .static_library, .shared_library => {
|
||||
try link_objects.append(context.my_allocator, .{
|
||||
.path = argument,
|
||||
});
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
},
|
||||
.macos => {
|
||||
try clang_args.append_slice(context.my_allocator, &.{
|
||||
"-isystem", try context.pathFromCompiler("lib/libcxx/include"),
|
||||
"-isystem", try context.pathFromCompiler("lib/libcxxabi/include"),
|
||||
"-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
|
||||
"-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
|
||||
"-D_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS",
|
||||
"-D_LIBCPP_PSTL_CPU_BACKEND_SERIAL",
|
||||
"-D_LIBCPP_ABI_VERSION=1",
|
||||
"-D_LIBCPP_ABI_NAMESPACE=__1",
|
||||
});
|
||||
},
|
||||
else => @compileError("Operating system not supported"),
|
||||
} else {
|
||||
try write(.panic, argument);
|
||||
try write(.panic, "\n");
|
||||
@panic("Positional argument without extension");
|
||||
}
|
||||
} else if (byte_equal(argument, "-c")) {
|
||||
out_mode = .object;
|
||||
} else if (byte_equal(argument, "-o")) {
|
||||
argument_index += 1;
|
||||
out_path = arguments[argument_index];
|
||||
} else if (byte_equal(argument, "-g")) {
|
||||
debug_info = .yes;
|
||||
} else if (byte_equal(argument, "-fno-stack-protector")) {
|
||||
stack_protector = false;
|
||||
} else if (byte_equal(argument, "-arch")) {
|
||||
argument_index += 1;
|
||||
const arch_argument = arguments[argument_index];
|
||||
if (byte_equal(arch_argument, "arm64")) {
|
||||
link_arch = .arm64;
|
||||
try cc_argv.append(context.my_allocator, "-arch");
|
||||
try cc_argv.append(context.my_allocator, "arm64");
|
||||
} else {
|
||||
unreachable;
|
||||
}
|
||||
} else if (byte_equal(argument, "-bundle")) {
|
||||
try ld_argv.append(context.my_allocator, argument);
|
||||
} else if (byte_equal(argument, "-pthread")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
} else if (byte_equal(argument, "-fPIC")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
} else if (byte_equal(argument, "-MD")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
} else if (byte_equal(argument, "-MT")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
argument_index += 1;
|
||||
const arg = arguments[argument_index];
|
||||
try cc_argv.append(context.my_allocator, arg);
|
||||
} else if (byte_equal(argument, "-MF")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
argument_index += 1;
|
||||
const arg = arguments[argument_index];
|
||||
try cc_argv.append(context.my_allocator, arg);
|
||||
} else if (byte_equal(argument, "-isysroot")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
argument_index += 1;
|
||||
const arg = arguments[argument_index];
|
||||
try cc_argv.append(context.my_allocator, arg);
|
||||
} else if (byte_equal(argument, "-isystem")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
argument_index += 1;
|
||||
const arg = arguments[argument_index];
|
||||
try cc_argv.append(context.my_allocator, arg);
|
||||
} else if (byte_equal(argument, "-h")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
} else if (byte_equal(argument, "-framework")) {
|
||||
try ld_argv.append(context.my_allocator, argument);
|
||||
argument_index += 1;
|
||||
const framework = arguments[argument_index];
|
||||
try ld_argv.append(context.my_allocator, framework);
|
||||
} else if (byte_equal(argument, "--coverage")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
} else if (byte_equal(argument, "-pedantic")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
} else if (byte_equal(argument, "-pedantic-errors")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
} else if (byte_equal(argument, "-?")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
} else if (byte_equal(argument, "-v")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
} else if (byte_equal(argument, "-V")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
} else if (byte_equal(argument, "--version")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
} else if (byte_equal(argument, "-version")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
} else if (byte_equal(argument, "-qversion")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
} else if (byte_equal(argument, "-print-resource-dir")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
} else if (byte_equal(argument, "-shared")) {
|
||||
try ld_argv.append(context.my_allocator, argument);
|
||||
} else if (byte_equal(argument, "-compatibility_version")) {
|
||||
try ld_argv.append(context.my_allocator, argument);
|
||||
argument_index += 1;
|
||||
const arg = arguments[argument_index];
|
||||
try ld_argv.append(context.my_allocator, arg);
|
||||
} else if (byte_equal(argument, "-current_version")) {
|
||||
try ld_argv.append(context.my_allocator, argument);
|
||||
argument_index += 1;
|
||||
const arg = arguments[argument_index];
|
||||
try ld_argv.append(context.my_allocator, arg);
|
||||
} else if (byte_equal(argument, "-install_name")) {
|
||||
try ld_argv.append(context.my_allocator, argument);
|
||||
argument_index += 1;
|
||||
const arg = arguments[argument_index];
|
||||
try ld_argv.append(context.my_allocator, arg);
|
||||
} else if (starts_with_slice(argument, "-f")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
} else if (starts_with_slice(argument, "-wd")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
} else if (starts_with_slice(argument, "-D")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
} else if (starts_with_slice(argument, "-I")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
} else if (starts_with_slice(argument, "-W")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
} else if (starts_with_slice(argument, "-l")) {
|
||||
try link_libraries.append(context.my_allocator, .{
|
||||
.path = argument[2..],
|
||||
});
|
||||
} else if (starts_with_slice(argument, "-O")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
} else if (starts_with_slice(argument, "-std=")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
} else if (starts_with_slice(argument, "-rdynamic")) {
|
||||
try ld_argv.append(context.my_allocator, "-export_dynamic");
|
||||
} else if (starts_with_slice(argument, "-dynamiclib")) {
|
||||
try ld_argv.append(context.my_allocator, "-dylib");
|
||||
} else if (starts_with_slice(argument, "-Wl,")) {
|
||||
const wl_arg = argument["-Wl,".len..];
|
||||
if (data_structures.first_byte(wl_arg, ',')) |comma_index| {
|
||||
const key = wl_arg[0..comma_index];
|
||||
const value = wl_arg[comma_index + 1..];
|
||||
try ld_argv.append(context.my_allocator, key);
|
||||
try ld_argv.append(context.my_allocator, value);
|
||||
} else {
|
||||
try ld_argv.append(context.my_allocator, wl_arg);
|
||||
}
|
||||
} else if (starts_with_slice(argument, "-m")) {
|
||||
try cc_argv.append(context.my_allocator, argument);
|
||||
} else {
|
||||
const debug_args = true;
|
||||
if (debug_args) {
|
||||
const home_dir = std.posix.getenv("HOME") orelse unreachable;
|
||||
var list = UnpinnedArray(u8){};
|
||||
for (arguments) |arg| {
|
||||
try list.append_slice(context.my_allocator, arg);
|
||||
try list.append(context.my_allocator, ' ');
|
||||
}
|
||||
try list.append(context.my_allocator, '\n');
|
||||
try list.append_slice(context.my_allocator, "Unhandled argument: ");
|
||||
try list.append_slice(context.my_allocator, argument);
|
||||
try list.append(context.my_allocator, '\n');
|
||||
|
||||
try std.fs.cwd().writeFile(try std.fmt.allocPrint(context.allocator, "{s}/dev/nativity/nat/unhandled_arg_{}", .{home_dir, std.time.milliTimestamp()}), list.slice());
|
||||
}
|
||||
try write(.panic, "unhandled argument: '");
|
||||
try write(.panic, argument);
|
||||
try write(.panic, "'\n");
|
||||
@panic("Unhandled argument");
|
||||
}
|
||||
|
||||
argument_index += 1;
|
||||
}
|
||||
|
||||
if (kind == .c or kind == .cpp) {
|
||||
try clang_args.append(context.my_allocator, "-nostdinc");
|
||||
const link_libcpp = true;
|
||||
const mode = out_mode orelse .link;
|
||||
|
||||
switch (@import("builtin").os.tag) {
|
||||
.linux => {
|
||||
switch (@import("builtin").abi) {
|
||||
.gnu => {
|
||||
try clang_args.append_slice(context.my_allocator, &.{
|
||||
"-isystem", "/usr/lib/clang/17/include",
|
||||
"-isystem", "/usr/include",
|
||||
"-isystem", "/usr/include/linux",
|
||||
});
|
||||
if (c_source_files.length > 0) {
|
||||
for (c_source_files.slice()) |c_source_file| {
|
||||
var argv = UnpinnedArray([]const u8){};
|
||||
try argv.append(context.my_allocator, context.executable_absolute_path);
|
||||
try argv.append(context.my_allocator, "clang");
|
||||
try argv.append(context.my_allocator, "--no-default-config");
|
||||
|
||||
try argv.append(context.my_allocator, c_source_file.path);
|
||||
|
||||
if (c_source_file.extension == .cpp) {
|
||||
try argv.append(context.my_allocator, "-nostdinc++");
|
||||
}
|
||||
|
||||
const caret = true;
|
||||
if (!caret) {
|
||||
try argv.append(context.my_allocator, "-fno-caret-diagnostics");
|
||||
}
|
||||
|
||||
const function_sections = false;
|
||||
if (function_sections) {
|
||||
try argv.append(context.my_allocator, "-ffunction-sections");
|
||||
}
|
||||
|
||||
const data_sections = false;
|
||||
if (data_sections) {
|
||||
try argv.append(context.my_allocator, "-fdata-sections");
|
||||
}
|
||||
|
||||
const builtin = true;
|
||||
if (!builtin) {
|
||||
try argv.append(context.my_allocator, "-fno-builtin");
|
||||
}
|
||||
|
||||
|
||||
if (link_libcpp) {
|
||||
// include paths
|
||||
|
||||
}
|
||||
|
||||
const link_libc = c_source_file.extension == .c;
|
||||
if (link_libc) {
|
||||
}
|
||||
|
||||
const link_libunwind = false;
|
||||
if (link_libunwind) {
|
||||
unreachable;
|
||||
}
|
||||
|
||||
const target_triple = blk: {
|
||||
// Emit target
|
||||
var target_triple_buffer = UnpinnedArray(u8){};
|
||||
switch (@import("builtin").target.cpu.arch) {
|
||||
.x86_64 => {
|
||||
try target_triple_buffer.append_slice(context.my_allocator, "x86_64-");
|
||||
},
|
||||
.musl => {
|
||||
try clang_args.append_slice(context.my_allocator, &.{
|
||||
"-isystem", try context.pathFromCompiler("lib/include"),
|
||||
"-isystem", try context.pathFromCompiler("lib/libc/include/x86_64-linux-gnu"),
|
||||
"-isystem", try context.pathFromCompiler("lib/libc/include/generic-glibc"),
|
||||
"-isystem", try context.pathFromCompiler("lib/libc/include/x86-linux-any"),
|
||||
"-isystem", try context.pathFromCompiler("lib/libc/include/any-linux-any"),
|
||||
});
|
||||
.aarch64 => {
|
||||
try target_triple_buffer.append_slice(context.my_allocator, "aarch64-");
|
||||
},
|
||||
else => @compileError("Abi not supported"),
|
||||
else => @compileError("Architecture not supported"),
|
||||
}
|
||||
},
|
||||
.macos => {
|
||||
try clang_args.append_slice(context.my_allocator, &.{
|
||||
"-iframework", "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks",
|
||||
"-isystem", try context.pathFromCompiler("lib/include"),
|
||||
"-isystem", "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include",
|
||||
});
|
||||
},
|
||||
else => @compileError("Operating system not supported"),
|
||||
}
|
||||
}
|
||||
|
||||
if (kind == .cpp) {
|
||||
switch (@import("builtin").os.tag) {
|
||||
.linux => {
|
||||
switch (@import("builtin").abi) {
|
||||
.gnu => {
|
||||
try clang_args.append(context.my_allocator, "-lstdc++");
|
||||
if (@import("builtin").target.cpu.arch == .aarch64 and @import("builtin").target.os.tag == .macos) {
|
||||
try target_triple_buffer.append_slice(context.my_allocator, "apple-");
|
||||
} else {
|
||||
try target_triple_buffer.append_slice(context.my_allocator, "pc-");
|
||||
}
|
||||
|
||||
switch (@import("builtin").target.os.tag) {
|
||||
.linux => {
|
||||
try target_triple_buffer.append_slice(context.my_allocator, "linux-");
|
||||
},
|
||||
.macos => {
|
||||
try target_triple_buffer.append_slice(context.my_allocator, "macos-");
|
||||
},
|
||||
else => @compileError("OS not supported"),
|
||||
}
|
||||
|
||||
switch (@import("builtin").target.abi) {
|
||||
.musl => {
|
||||
try target_triple_buffer.append_slice(context.my_allocator, "musl");
|
||||
},
|
||||
.gnu => {
|
||||
try target_triple_buffer.append_slice(context.my_allocator, "gnu");
|
||||
},
|
||||
.none => {
|
||||
try target_triple_buffer.append_slice(context.my_allocator, "unknown");
|
||||
},
|
||||
else => @compileError("OS not supported"),
|
||||
}
|
||||
|
||||
break :blk target_triple_buffer.slice();
|
||||
};
|
||||
try argv.append_slice(context.my_allocator, &.{"-target", target_triple});
|
||||
|
||||
const object_path = switch (mode) {
|
||||
.object => out_path.?,
|
||||
.link => try std.mem.concat(context.allocator, u8, &.{if (out_path) |op| op else "a.o", ".o"}),
|
||||
};
|
||||
|
||||
try link_objects.append(context.my_allocator, .{
|
||||
.path = object_path,
|
||||
});
|
||||
|
||||
switch (c_source_file.extension) {
|
||||
.c, .cpp => {
|
||||
try argv.append(context.my_allocator, "-nostdinc");
|
||||
try argv.append(context.my_allocator, "-fno-spell-checking");
|
||||
|
||||
const lto = false;
|
||||
if (lto) {
|
||||
try argv.append(context.my_allocator, "-flto");
|
||||
}
|
||||
|
||||
const mm = false;
|
||||
if (mm) {
|
||||
try argv.append(context.my_allocator, "-ObjC++");
|
||||
}
|
||||
|
||||
const libc_framework_dirs: []const []const u8 = switch (@import("builtin").os.tag) {
|
||||
.macos => &.{"/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks"},
|
||||
else => &.{},
|
||||
};
|
||||
for (libc_framework_dirs) |framework_dir| {
|
||||
try argv.append_slice(context.my_allocator, &.{"-iframework", framework_dir});
|
||||
}
|
||||
|
||||
const framework_dirs = &[_][]const u8{};
|
||||
for (framework_dirs) |framework_dir| {
|
||||
try argv.append_slice(context.my_allocator, &.{"-F", framework_dir});
|
||||
}
|
||||
|
||||
// TODO: c headers dir
|
||||
|
||||
const libc_include_dirs: []const []const u8 = switch (@import("builtin").os.tag) {
|
||||
.macos => &.{
|
||||
"/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/v1",
|
||||
try context.pathFromCompiler("lib/include"),
|
||||
"/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include",
|
||||
},
|
||||
.linux => switch (@import("builtin").abi) {
|
||||
.gnu => &.{
|
||||
"/usr/include/c++/13.2.1",
|
||||
"/usr/include/c++/13.2.1/x86_64-pc-linux-gnu",
|
||||
"/usr/lib/clang/17/include",
|
||||
"/usr/include",
|
||||
"/usr/include/linux",
|
||||
},
|
||||
else => unreachable, //@compileError("ABI not supported"),
|
||||
},
|
||||
else => @compileError("OS not supported"),
|
||||
};
|
||||
|
||||
for (libc_include_dirs) |include_dir| {
|
||||
try argv.append_slice(context.my_allocator, &.{"-isystem", include_dir});
|
||||
}
|
||||
|
||||
// TODO: cpu model
|
||||
// TODO: cpu features
|
||||
// TODO: code model
|
||||
// TODO: OS-specific flags
|
||||
// TODO: sanitize flags
|
||||
// const red_zone = true;
|
||||
// if (red_zone) {
|
||||
// try argv.append(context.my_allocator, "-mred-zone");
|
||||
// } else {
|
||||
// unreachable;
|
||||
// }
|
||||
|
||||
const omit_frame_pointer = false;
|
||||
if (omit_frame_pointer) {
|
||||
try argv.append(context.my_allocator, "-fomit-frame-pointer");
|
||||
} else {
|
||||
try argv.append(context.my_allocator, "-fno-omit-frame-pointer");
|
||||
}
|
||||
|
||||
if (stack_protector orelse false) {
|
||||
try argv.append(context.my_allocator, "-fstack-protector-strong");
|
||||
} else {
|
||||
try argv.append(context.my_allocator, "-fno-stack-protector");
|
||||
}
|
||||
|
||||
const is_debug = true;
|
||||
if (is_debug) {
|
||||
try argv.append(context.my_allocator, "-D_DEBUG");
|
||||
try argv.append(context.my_allocator, "-O0");
|
||||
} else {
|
||||
unreachable;
|
||||
},
|
||||
else => @compileError("Abi not supported"),
|
||||
}
|
||||
},
|
||||
.macos => unreachable,
|
||||
else => @compileError("OS not supported"),
|
||||
}
|
||||
|
||||
const pic = false;
|
||||
if (pic) {
|
||||
try argv.append(context.my_allocator, "-fPIC");
|
||||
}
|
||||
|
||||
const unwind_tables = false;
|
||||
if (unwind_tables) {
|
||||
try argv.append(context.my_allocator, "-funwind-tables");
|
||||
} else {
|
||||
try argv.append(context.my_allocator, "-fno-unwind-tables");
|
||||
}
|
||||
},
|
||||
.assembly => {
|
||||
// TODO:
|
||||
},
|
||||
.object, .static_library, .shared_library => unreachable,
|
||||
}
|
||||
|
||||
const has_debug_info = true;
|
||||
if (has_debug_info) {
|
||||
try argv.append(context.my_allocator, "-g");
|
||||
} else {
|
||||
unreachable;
|
||||
}
|
||||
|
||||
// TODO: machine ABI
|
||||
const freestanding = false;
|
||||
if (freestanding) {
|
||||
try argv.append(context.my_allocator, "-ffrestanding");
|
||||
}
|
||||
|
||||
// TODO: native system include paths
|
||||
// TODO: global cc argv
|
||||
|
||||
try argv.append_slice(context.my_allocator, cc_argv.slice());
|
||||
|
||||
// TODO: extra flags
|
||||
// TODO: cache exempt flags
|
||||
try argv.append_slice(context.my_allocator, &.{"-c", "-o", object_path});
|
||||
// TODO: emit ASM/LLVM IR
|
||||
|
||||
const debug_clang_args = false;
|
||||
if (debug_clang_args) {
|
||||
std.debug.print("Argv: {s}\n", .{argv.slice()});
|
||||
}
|
||||
const result = try clangMain(context.allocator, argv.slice());
|
||||
if (result != 0) {
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
} else if (link_objects.length == 0) {
|
||||
var argv = UnpinnedArray([]const u8){};
|
||||
try argv.append(context.my_allocator, context.executable_absolute_path);
|
||||
try argv.append(context.my_allocator, "clang");
|
||||
try argv.append(context.my_allocator, "--no-default-config");
|
||||
try argv.append_slice(context.my_allocator, cc_argv.slice());
|
||||
const result = try clangMain(context.allocator, argv.slice());
|
||||
if (result != 0) {
|
||||
unreachable;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (arguments) |arg| {
|
||||
try clang_args.append(context.my_allocator, span(arg));
|
||||
if (mode == .link) {
|
||||
assert(link_objects.length > 0);
|
||||
try linker.link(context, .{
|
||||
.backend = .lld,
|
||||
.output_file_path = out_path orelse "a.out",
|
||||
.objects = link_objects.slice(),
|
||||
.libraries = link_libraries.slice(),
|
||||
.extra_arguments = ld_argv.slice(),
|
||||
.link_libc = true,
|
||||
.link_libcpp = link_libcpp,
|
||||
});
|
||||
}
|
||||
|
||||
const result = try clangMain(context.allocator, clang_args.slice());
|
||||
if (result != 0) {
|
||||
unreachable;
|
||||
}
|
||||
// if (kind == .cpp) {
|
||||
// try clang_args.append(context.my_allocator, "-nostdinc++");
|
||||
//
|
||||
// switch (@import("builtin").os.tag) {
|
||||
// .linux => {
|
||||
// switch (@import("builtin").abi) {
|
||||
// .gnu => {
|
||||
// try clang_args.append_slice(context.my_allocator, &.{
|
||||
// "-isystem", "/usr/include/c++/13.2.1",
|
||||
// "-isystem", "/usr/include/c++/13.2.1/x86_64-pc-linux-gnu",
|
||||
// });
|
||||
// },
|
||||
// .musl => {
|
||||
// try clang_args.append_slice(context.my_allocator, &.{
|
||||
// "-isystem", try context.pathFromCompiler("lib/libcxx/include"),
|
||||
// "-isystem", try context.pathFromCompiler("lib/libcxxabi/include"),
|
||||
// "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
|
||||
// "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
|
||||
// "-D_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS",
|
||||
// "-D_LIBCPP_PSTL_CPU_BACKEND_SERIAL",
|
||||
// "-D_LIBCPP_ABI_VERSION=1",
|
||||
// "-D_LIBCPP_ABI_NAMESPACE=__1",
|
||||
// });
|
||||
// },
|
||||
// else => unreachable,
|
||||
// }
|
||||
// },
|
||||
// .macos => {
|
||||
// try clang_args.append_slice(context.my_allocator, &.{
|
||||
// "-isystem", try context.pathFromCompiler("lib/libcxx/include"),
|
||||
// "-isystem", try context.pathFromCompiler("lib/libcxxabi/include"),
|
||||
// "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
|
||||
// "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
|
||||
// "-D_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS",
|
||||
// "-D_LIBCPP_PSTL_CPU_BACKEND_SERIAL",
|
||||
// "-D_LIBCPP_ABI_VERSION=1",
|
||||
// "-D_LIBCPP_ABI_NAMESPACE=__1",
|
||||
// });
|
||||
// },
|
||||
// else => @compileError("Operating system not supported"),
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (kind == .c or kind == .cpp) {
|
||||
// try clang_args.append(context.my_allocator, "-nostdinc");
|
||||
//
|
||||
// switch (@import("builtin").os.tag) {
|
||||
// .linux => {
|
||||
// switch (@import("builtin").abi) {
|
||||
// .gnu => {
|
||||
// try clang_args.append_slice(context.my_allocator, &.{
|
||||
// "-isystem", "/usr/lib/clang/17/include",
|
||||
// "-isystem", "/usr/include",
|
||||
// "-isystem", "/usr/include/linux",
|
||||
// });
|
||||
// },
|
||||
// .musl => {
|
||||
// try clang_args.append_slice(context.my_allocator, &.{
|
||||
// "-isystem", try context.pathFromCompiler("lib/include"),
|
||||
// "-isystem", try context.pathFromCompiler("lib/libc/include/x86_64-linux-gnu"),
|
||||
// "-isystem", try context.pathFromCompiler("lib/libc/include/generic-glibc"),
|
||||
// "-isystem", try context.pathFromCompiler("lib/libc/include/x86-linux-any"),
|
||||
// "-isystem", try context.pathFromCompiler("lib/libc/include/any-linux-any"),
|
||||
// });
|
||||
// },
|
||||
// else => @compileError("Abi not supported"),
|
||||
// }
|
||||
// },
|
||||
// .macos => {
|
||||
// try clang_args.append_slice(context.my_allocator, &.{
|
||||
// "-iframework", "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks",
|
||||
// "-isystem", try context.pathFromCompiler("lib/include"),
|
||||
// "-isystem", "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include",
|
||||
// });
|
||||
// },
|
||||
// else => @compileError("Operating system not supported"),
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (kind == .cpp) {
|
||||
// switch (@import("builtin").os.tag) {
|
||||
// .linux => {
|
||||
// switch (@import("builtin").abi) {
|
||||
// .gnu => {
|
||||
// try clang_args.append(context.my_allocator, "-lstdc++");
|
||||
// },
|
||||
// .musl => {
|
||||
// unreachable;
|
||||
// },
|
||||
// else => @compileError("Abi not supported"),
|
||||
// }
|
||||
// },
|
||||
// .macos => unreachable,
|
||||
// else => @compileError("OS not supported"),
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// for (arguments) |arg| {
|
||||
// try clang_args.append(context.my_allocator, span(arg));
|
||||
// }
|
||||
//
|
||||
// const result = try clangMain(context.allocator, clang_args.slice());
|
||||
// if (result != 0) {
|
||||
// unreachable;
|
||||
// }
|
||||
|
||||
// const output_object_file = "nat/main.o";
|
||||
// const exit_code = try clangMain(context.allocator, &.{ context.executable_absolute_path, "--no-default-config", "-target", "x86_64-unknown-linux-musl", "-nostdinc", "-fno-spell-checking", "-isystem", "lib/include", "-isystem", "lib/libc/include/x86_64-linux-musl", "-isystem", "lib/libc/include/generic-musl", "-isystem", "lib/libc/include/x86-linux-any", "-isystem", "lib/libc/include/any-linux-any", "-c", argument, "-o", output_object_file });
|
||||
@ -2230,7 +2717,7 @@ const musl_arch_files = [_][]const u8{
|
||||
musl_lib_dir_relative_path ++ "src/unistd/x32/lseek.c",
|
||||
};
|
||||
|
||||
fn argsCopyZ(alloc: Allocator, args: []const []const u8) ![:null]?[*:0]u8 {
|
||||
pub fn argsCopyZ(alloc: Allocator, args: []const []const u8) ![:null]?[*:0]u8 {
|
||||
var argv = try alloc.allocSentinel(?[*:0]u8, args.len, null);
|
||||
for (args, 0..) |arg, i| {
|
||||
argv[i] = try alloc.dupeZ(u8, arg); // TODO If there was an argsAllocZ we could avoid this allocation.
|
||||
@ -2246,7 +2733,7 @@ fn arMain(allocator: Allocator, arguments: []const []const u8) !u8 {
|
||||
}
|
||||
|
||||
extern "c" fn NativityClangMain(argc: c_int, argv: [*:null]?[*:0]u8) c_int;
|
||||
fn clangMain(allocator: Allocator, arguments: []const []const u8) !u8 {
|
||||
pub fn clangMain(allocator: Allocator, arguments: []const []const u8) !u8 {
|
||||
const argv = try argsCopyZ(allocator, arguments);
|
||||
const exit_code = NativityClangMain(@as(c_int, @intCast(arguments.len)), argv.ptr);
|
||||
return @as(u8, @bitCast(@as(i8, @truncate(exit_code))));
|
||||
@ -2272,7 +2759,7 @@ const Abi = enum {
|
||||
musl,
|
||||
};
|
||||
|
||||
pub fn buildExecutable(context: *const Context, arguments: [][*:0]u8, options: ExecutableOptions) !void {
|
||||
pub fn buildExecutable(context: *const Context, arguments: []const []const u8, options: ExecutableOptions) !void {
|
||||
var maybe_executable_path: ?[]const u8 = null;
|
||||
var maybe_main_package_path: ?[]const u8 = null;
|
||||
var arch: Arch = undefined;
|
||||
@ -2296,17 +2783,17 @@ pub fn buildExecutable(context: *const Context, arguments: [][*:0]u8, options: E
|
||||
var maybe_only_parse: ?bool = null;
|
||||
var link_libc = false;
|
||||
var maybe_executable_name: ?[]const u8 = null;
|
||||
var c_source_files = UnpinnedArray([*:0]u8){};
|
||||
var c_source_files = UnpinnedArray([]const u8){};
|
||||
const generate_debug_information = true;
|
||||
|
||||
if (arguments.len == 0) return error.InvalidInput;
|
||||
|
||||
var i: usize = 0;
|
||||
while (i < arguments.len) : (i += 1) {
|
||||
const current_argument = span(arguments[i]);
|
||||
const current_argument = arguments[i];
|
||||
if (byte_equal(current_argument, "-o")) {
|
||||
if (i + 1 != arguments.len) {
|
||||
maybe_executable_path = span(arguments[i + 1]);
|
||||
maybe_executable_path = arguments[i + 1];
|
||||
assert(maybe_executable_path.?.len != 0);
|
||||
i += 1;
|
||||
} else {
|
||||
@ -2364,7 +2851,7 @@ pub fn buildExecutable(context: *const Context, arguments: [][*:0]u8, options: E
|
||||
if (i + 1 != arguments.len) {
|
||||
i += 1;
|
||||
|
||||
const arg = span(arguments[i]);
|
||||
const arg = arguments[i];
|
||||
maybe_main_package_path = arg;
|
||||
maybe_only_parse = true;
|
||||
} else {
|
||||
@ -2374,7 +2861,7 @@ pub fn buildExecutable(context: *const Context, arguments: [][*:0]u8, options: E
|
||||
if (i + 1 != arguments.len) {
|
||||
i += 1;
|
||||
|
||||
const arg = span(arguments[i]);
|
||||
const arg = arguments[i];
|
||||
if (byte_equal(arg, "true")) {
|
||||
link_libc = true;
|
||||
} else if (byte_equal(arg, "false")) {
|
||||
@ -2389,7 +2876,7 @@ pub fn buildExecutable(context: *const Context, arguments: [][*:0]u8, options: E
|
||||
if (i + 1 != arguments.len) {
|
||||
i += 1;
|
||||
|
||||
const arg = span(arguments[i]);
|
||||
const arg = arguments[i];
|
||||
maybe_main_package_path = arg;
|
||||
} else {
|
||||
reportUnterminatedArgumentError(current_argument);
|
||||
@ -2398,7 +2885,7 @@ pub fn buildExecutable(context: *const Context, arguments: [][*:0]u8, options: E
|
||||
if (i + 1 != arguments.len) {
|
||||
i += 1;
|
||||
|
||||
const arg = span(arguments[i]);
|
||||
const arg = arguments[i];
|
||||
maybe_executable_name = arg;
|
||||
} else {
|
||||
reportUnterminatedArgumentError(current_argument);
|
||||
@ -2437,11 +2924,20 @@ pub fn buildExecutable(context: *const Context, arguments: [][*:0]u8, options: E
|
||||
break :blk result;
|
||||
};
|
||||
|
||||
const object_file_path = blk: {
|
||||
const slice = try context.allocator.alloc(u8, executable_path.len + 2);
|
||||
@memcpy(slice[0..executable_path.len], executable_path);
|
||||
slice[executable_path.len] = '.';
|
||||
slice[executable_path.len + 1] = 'o';
|
||||
break :blk slice;
|
||||
};
|
||||
|
||||
const unit = try context.allocator.create(Unit);
|
||||
unit.* = .{
|
||||
.descriptor = .{
|
||||
.main_package_path = main_package_path,
|
||||
.executable_path = executable_path,
|
||||
.object_path = object_file_path,
|
||||
.only_parse = only_parse,
|
||||
.arch = arch,
|
||||
.os = os,
|
||||
@ -2452,6 +2948,7 @@ pub fn buildExecutable(context: *const Context, arguments: [][*:0]u8, options: E
|
||||
// .windows => link_libc,
|
||||
// else => unreachable,
|
||||
},
|
||||
.link_libcpp = false,
|
||||
.generate_debug_information = generate_debug_information,
|
||||
.name = executable_name,
|
||||
.is_test = options.is_test,
|
||||
@ -14427,7 +14924,7 @@ pub const Unit = struct {
|
||||
cc_type: Type.Index = .null,
|
||||
test_function_type: Type.Index = .null,
|
||||
descriptor: Descriptor,
|
||||
object_files: UnpinnedArray([*:0]const u8) = .{},
|
||||
// object_files: []const linker.Object,
|
||||
discard_identifiers: usize = 0,
|
||||
anon_i: usize = 0,
|
||||
anon_arr: usize = 0,
|
||||
@ -15157,30 +15654,40 @@ pub const Unit = struct {
|
||||
}
|
||||
|
||||
if (!unit.descriptor.only_parse) {
|
||||
try unit.object_files.ensure_capacity(context.my_allocator, @intCast(unit.descriptor.c_source_files.len));
|
||||
var object_files = try UnpinnedArray(linker.Object).initialize_with_capacity(context.my_allocator, @intCast(unit.descriptor.c_source_files.len + 1));
|
||||
object_files.append_with_capacity(.{
|
||||
.path = unit.descriptor.object_path,
|
||||
});
|
||||
|
||||
for (unit.descriptor.c_source_files) |c_source_file| {
|
||||
const c_src = span(c_source_file);
|
||||
const dot_index = data_structures.last(c_src, '.') orelse unreachable;
|
||||
const path_without_extension = c_src[0..dot_index];
|
||||
const dot_index = data_structures.last_byte(c_source_file, '.') orelse unreachable;
|
||||
const path_without_extension = c_source_file[0..dot_index];
|
||||
const basename = std.fs.path.basename(path_without_extension);
|
||||
const o_file = try std.mem.concat(context.allocator, u8, &.{ basename, ".o" });
|
||||
const basename_z = try std.mem.joinZ(context.allocator, "/", &.{
|
||||
"nat",
|
||||
const object_path = try std.mem.concat(context.allocator, u8, &.{
|
||||
"nat/",
|
||||
o_file,
|
||||
});
|
||||
var c_flag = "-c".*;
|
||||
var o_flag = "-o".*;
|
||||
var g_flag = "-g".*;
|
||||
var stack_protector = "-fno-stack-protector".*;
|
||||
|
||||
var arguments = [_][*:0]u8{ &c_flag, c_source_file, &o_flag, basename_z, &g_flag, &stack_protector };
|
||||
var arguments = [_][]const u8{ "-c", c_source_file, "-o", object_path, "-g", "-fno-stack-protector"};
|
||||
try compileCSourceFile(context, &arguments, .c);
|
||||
unit.object_files.append_with_capacity(basename_z);
|
||||
object_files.append_with_capacity(.{
|
||||
.path = object_path,
|
||||
});
|
||||
}
|
||||
|
||||
try unit.analyze(context);
|
||||
|
||||
try llvm.codegen(unit, context);
|
||||
|
||||
try linker.link(context, .{
|
||||
.output_file_path = unit.descriptor.executable_path,
|
||||
.objects = object_files.slice(),
|
||||
.libraries = &.{},
|
||||
.link_libc = unit.descriptor.link_libc,
|
||||
.link_libcpp = false,
|
||||
.extra_arguments = &.{},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -15241,14 +15748,16 @@ pub const FixedKeyword = enum {
|
||||
pub const Descriptor = struct {
|
||||
main_package_path: []const u8,
|
||||
executable_path: []const u8,
|
||||
object_path: []const u8,
|
||||
arch: Arch,
|
||||
os: Os,
|
||||
abi: Abi,
|
||||
only_parse: bool,
|
||||
link_libc: bool,
|
||||
link_libcpp: bool,
|
||||
is_test: bool,
|
||||
generate_debug_information: bool,
|
||||
c_source_files: []const [*:0]u8,
|
||||
c_source_files: []const []const u8,
|
||||
name: []const u8,
|
||||
};
|
||||
|
||||
|
@ -3173,118 +3173,121 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
||||
const object_file_path = slice[0 .. slice.len - 1 :0];
|
||||
break :blk object_file_path;
|
||||
};
|
||||
const destination_file_path = blk: {
|
||||
const slice = try context.allocator.alloc(u8, file_path.len + 1); // try std.mem.concatWithSentinel(context.allocator, &.{file_path});
|
||||
@memcpy(slice[0..file_path.len], file_path);
|
||||
slice[slice.len - 1] = 0;
|
||||
const destination_file_path = slice[0..file_path.len :0];
|
||||
break :blk destination_file_path;
|
||||
};
|
||||
// const destination_file_path = blk: {
|
||||
// const slice = try context.allocator.alloc(u8, file_path.len + 1); // try std.mem.concatWithSentinel(context.allocator, &.{file_path});
|
||||
// @memcpy(slice[0..file_path.len], file_path);
|
||||
// slice[slice.len - 1] = 0;
|
||||
// const destination_file_path = slice[0..file_path.len :0];
|
||||
// break :blk destination_file_path;
|
||||
// };
|
||||
// _ = destination_file_path; // autofix
|
||||
const disable_verify = false;
|
||||
const result = llvm.module.addPassesToEmitFile(target_machine, object_file_path.ptr, object_file_path.len, LLVM.CodeGenFileType.object, disable_verify);
|
||||
if (!result) {
|
||||
@panic("can't generate machine code");
|
||||
}
|
||||
|
||||
const format: Format = switch (unit.descriptor.os) {
|
||||
// .windows => .coff,
|
||||
.macos => .macho,
|
||||
.linux => .elf,
|
||||
// else => unreachable,
|
||||
};
|
||||
// const format: Format = switch (unit.descriptor.os) {
|
||||
// // .windows => .coff,
|
||||
// .macos => .macho,
|
||||
// .linux => .elf,
|
||||
// // else => unreachable,
|
||||
// };
|
||||
|
||||
const driver_program = switch (format) {
|
||||
.coff => "lld-link",
|
||||
.elf => "ld.lld",
|
||||
.macho => "ld64.lld",
|
||||
};
|
||||
var arguments = UnpinnedArray([*:0]const u8){};
|
||||
try arguments.append(context.my_allocator, driver_program);
|
||||
// const driver_program = switch (format) {
|
||||
// .coff => "lld-link",
|
||||
// .elf => "ld.lld",
|
||||
// .macho => "ld64.lld",
|
||||
// };
|
||||
// _ = driver_program; // autofix
|
||||
|
||||
try arguments.append(context.my_allocator, "--error-limit=0");
|
||||
|
||||
try arguments.append(context.my_allocator, "-o");
|
||||
try arguments.append(context.my_allocator, destination_file_path.ptr);
|
||||
|
||||
try arguments.append(context.my_allocator, object_file_path.ptr);
|
||||
|
||||
try arguments.append_slice(context.my_allocator, unit.object_files.slice());
|
||||
// for (unit.object_files.slice()) |object_file| {
|
||||
// _ = object_file; // autofix
|
||||
// var arguments = UnpinnedArray([]const u8){};
|
||||
// try arguments.append(context.my_allocator, driver_program);
|
||||
//
|
||||
// try arguments.append(context.my_allocator, "--error-limit=0");
|
||||
//
|
||||
// try arguments.append(context.my_allocator, "-o");
|
||||
// try arguments.append(context.my_allocator, destination_file_path.ptr);
|
||||
//
|
||||
// try arguments.append(context.my_allocator, object_file_path.ptr);
|
||||
//
|
||||
// try arguments.append_slice(context.my_allocator, unit.object_files.slice());
|
||||
// // for (unit.object_files.slice()) |object_file| {
|
||||
// // _ = object_file; // autofix
|
||||
// // }
|
||||
//
|
||||
// switch (unit.descriptor.os) {
|
||||
// .macos => {
|
||||
// try arguments.append(context.my_allocator, "-dynamic");
|
||||
// try arguments.append_slice(context.my_allocator, &.{ "-platform_version", "macos", "13.4.1", "13.3" });
|
||||
// try arguments.append(context.my_allocator, "-arch");
|
||||
// try arguments.append(context.my_allocator, switch (unit.descriptor.arch) {
|
||||
// .aarch64 => "arm64",
|
||||
// else => |t| @panic(@tagName(t)),
|
||||
// });
|
||||
// try arguments.append_slice(context.my_allocator, &.{ "-syslibroot", "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk" });
|
||||
// try arguments.append_slice(context.my_allocator, &.{ "-e", "_main" });
|
||||
// try arguments.append(context.my_allocator, "-lSystem");
|
||||
// },
|
||||
// .linux => {
|
||||
// try arguments.append_slice(context.my_allocator, &.{ "--entry", "_start" });
|
||||
// try arguments.append(context.my_allocator, "-m");
|
||||
// try arguments.append(context.my_allocator, switch (unit.descriptor.arch) {
|
||||
// .x86_64 => "elf_x86_64",
|
||||
// else => |t| @panic(@tagName(t)),
|
||||
// });
|
||||
//
|
||||
// if (unit.descriptor.link_libc) {
|
||||
// try arguments.append(context.my_allocator, "/usr/lib/crt1.o");
|
||||
// try arguments.append(context.my_allocator, "/usr/lib/crti.o");
|
||||
// try arguments.append_slice(context.my_allocator, &.{ "-L", "/usr/lib" });
|
||||
// try arguments.append_slice(context.my_allocator, &.{ "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2" });
|
||||
// try arguments.append(context.my_allocator, "--as-needed");
|
||||
// try arguments.append(context.my_allocator, "-lm");
|
||||
// try arguments.append(context.my_allocator, "-lpthread");
|
||||
// try arguments.append(context.my_allocator, "-lc");
|
||||
// try arguments.append(context.my_allocator, "-ldl");
|
||||
// try arguments.append(context.my_allocator, "-lrt");
|
||||
// try arguments.append(context.my_allocator, "-lutil");
|
||||
// try arguments.append(context.my_allocator, "/usr/lib/crtn.o");
|
||||
// }
|
||||
//
|
||||
// // if (unit.descriptor.link_libc) {
|
||||
// // try arguments.append_slice(context.allocator, &.{ "-lc" });
|
||||
// // }
|
||||
// },
|
||||
// // .windows => {},
|
||||
// // else => |t| @panic(@tagName(t)),
|
||||
// }
|
||||
//
|
||||
// var stdout_ptr: [*]const u8 = undefined;
|
||||
// var stdout_len: usize = 0;
|
||||
// var stderr_ptr: [*]const u8 = undefined;
|
||||
// var stderr_len: usize = 0;
|
||||
//
|
||||
// const linking_result = switch (format) {
|
||||
// .elf => bindings.NativityLLDLinkELF(arguments.pointer, arguments.length, &stdout_ptr, &stdout_len, &stderr_ptr, &stderr_len),
|
||||
// .coff => bindings.NativityLLDLinkCOFF(arguments.pointer, arguments.length, &stdout_ptr, &stdout_len, &stderr_ptr, &stderr_len),
|
||||
// .macho => bindings.NativityLLDLinkMachO(arguments.pointer, arguments.length, &stdout_ptr, &stdout_len, &stderr_ptr, &stderr_len),
|
||||
// };
|
||||
//
|
||||
// if (stdout_len > 0) {
|
||||
// // std.debug.print("{s}\n", .{stdout_ptr[0..stdout_len]});
|
||||
// }
|
||||
//
|
||||
// if (stderr_len > 0) {
|
||||
// // std.debug.print("{s}\n", .{stderr_ptr[0..stderr_len]});
|
||||
// }
|
||||
//
|
||||
// if (!linking_result) {
|
||||
// try write(.panic, "\n");
|
||||
// for (arguments.slice()) |argument| {
|
||||
// const arg = data_structures.span(argument);
|
||||
// try write(.panic, arg);
|
||||
// try write(.panic, " ");
|
||||
// }
|
||||
// try write(.panic, "\n");
|
||||
//
|
||||
// @panic(stderr_ptr[0..stderr_len]);
|
||||
// }
|
||||
|
||||
switch (unit.descriptor.os) {
|
||||
.macos => {
|
||||
try arguments.append(context.my_allocator, "-dynamic");
|
||||
try arguments.append_slice(context.my_allocator, &.{ "-platform_version", "macos", "13.4.1", "13.3" });
|
||||
try arguments.append(context.my_allocator, "-arch");
|
||||
try arguments.append(context.my_allocator, switch (unit.descriptor.arch) {
|
||||
.aarch64 => "arm64",
|
||||
else => |t| @panic(@tagName(t)),
|
||||
});
|
||||
try arguments.append_slice(context.my_allocator, &.{ "-syslibroot", "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk" });
|
||||
try arguments.append_slice(context.my_allocator, &.{ "-e", "_main" });
|
||||
try arguments.append(context.my_allocator, "-lSystem");
|
||||
},
|
||||
.linux => {
|
||||
try arguments.append_slice(context.my_allocator, &.{ "--entry", "_start" });
|
||||
try arguments.append(context.my_allocator, "-m");
|
||||
try arguments.append(context.my_allocator, switch (unit.descriptor.arch) {
|
||||
.x86_64 => "elf_x86_64",
|
||||
else => |t| @panic(@tagName(t)),
|
||||
});
|
||||
|
||||
if (unit.descriptor.link_libc) {
|
||||
try arguments.append(context.my_allocator, "/usr/lib/crt1.o");
|
||||
try arguments.append(context.my_allocator, "/usr/lib/crti.o");
|
||||
try arguments.append_slice(context.my_allocator, &.{ "-L", "/usr/lib" });
|
||||
try arguments.append_slice(context.my_allocator, &.{ "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2" });
|
||||
try arguments.append(context.my_allocator, "--as-needed");
|
||||
try arguments.append(context.my_allocator, "-lm");
|
||||
try arguments.append(context.my_allocator, "-lpthread");
|
||||
try arguments.append(context.my_allocator, "-lc");
|
||||
try arguments.append(context.my_allocator, "-ldl");
|
||||
try arguments.append(context.my_allocator, "-lrt");
|
||||
try arguments.append(context.my_allocator, "-lutil");
|
||||
try arguments.append(context.my_allocator, "/usr/lib/crtn.o");
|
||||
}
|
||||
|
||||
// if (unit.descriptor.link_libc) {
|
||||
// try arguments.append_slice(context.allocator, &.{ "-lc" });
|
||||
// }
|
||||
},
|
||||
// .windows => {},
|
||||
// else => |t| @panic(@tagName(t)),
|
||||
}
|
||||
|
||||
var stdout_ptr: [*]const u8 = undefined;
|
||||
var stdout_len: usize = 0;
|
||||
var stderr_ptr: [*]const u8 = undefined;
|
||||
var stderr_len: usize = 0;
|
||||
|
||||
const linking_result = switch (format) {
|
||||
.elf => bindings.NativityLLDLinkELF(arguments.pointer, arguments.length, &stdout_ptr, &stdout_len, &stderr_ptr, &stderr_len),
|
||||
.coff => bindings.NativityLLDLinkCOFF(arguments.pointer, arguments.length, &stdout_ptr, &stdout_len, &stderr_ptr, &stderr_len),
|
||||
.macho => bindings.NativityLLDLinkMachO(arguments.pointer, arguments.length, &stdout_ptr, &stdout_len, &stderr_ptr, &stderr_len),
|
||||
};
|
||||
|
||||
if (stdout_len > 0) {
|
||||
// std.debug.print("{s}\n", .{stdout_ptr[0..stdout_len]});
|
||||
}
|
||||
|
||||
if (stderr_len > 0) {
|
||||
// std.debug.print("{s}\n", .{stderr_ptr[0..stderr_len]});
|
||||
}
|
||||
|
||||
if (!linking_result) {
|
||||
try write(.panic, "\n");
|
||||
for (arguments.slice()) |argument| {
|
||||
const arg = data_structures.span(argument);
|
||||
try write(.panic, arg);
|
||||
try write(.panic, " ");
|
||||
}
|
||||
try write(.panic, "\n");
|
||||
|
||||
@panic(stderr_ptr[0..stderr_len]);
|
||||
}
|
||||
}
|
||||
|
@ -152,7 +152,3 @@ pub extern fn NativityLLVMModuleSetTargetMachineDataLayout(module: *LLVM.Module,
|
||||
pub extern fn NativityLLVMModuleSetTargetTriple(module: *LLVM.Module, target_triple_ptr: [*]const u8, target_triple_len: usize) void;
|
||||
pub extern fn NativityLLVMModuleAddPassesToEmitFile(module: *LLVM.Module, target_machine: *LLVM.Target.Machine, object_file_path_ptr: [*]const u8, object_file_path_len: usize, codegen_file_type: LLVM.CodeGenFileType, disable_verify: bool) bool;
|
||||
pub extern fn NativityLLVMTypeAssertEqual(a: *LLVM.Type, b: *LLVM.Type) void;
|
||||
pub extern fn NativityLLDLinkELF(argument_ptr: [*]const [*:0]const u8, argument_count: usize, stdout_ptr: *[*]const u8, stdout_len: *usize, stderr_ptr: *[*]const u8, stderr_len: *usize) bool;
|
||||
pub extern fn NativityLLDLinkCOFF(argument_ptr: [*]const [*:0]const u8, argument_count: usize, stdout_ptr: *[*]const u8, stdout_len: *usize, stderr_ptr: *[*]const u8, stderr_len: *usize) bool;
|
||||
pub extern fn NativityLLDLinkMachO(argument_ptr: [*]const [*:0]const u8, argument_count: usize, stdout_ptr: *[*]const u8, stdout_len: *usize, stderr_ptr: *[*]const u8, stderr_len: *usize) bool;
|
||||
pub extern fn NativityLLDLinkWasm(argument_ptr: [*]const [*:0]const u8, argument_count: usize, stdout_ptr: *[*]const u8, stdout_len: *usize, stderr_ptr: *[*]const u8, stderr_len: *usize) bool;
|
||||
|
@ -724,7 +724,53 @@ pub fn span(ptr: [*:0]const u8) [:0]const u8 {
|
||||
return ptr[0..len :0];
|
||||
}
|
||||
|
||||
pub fn last(bytes: []const u8, byte: u8) ?usize {
|
||||
pub fn starts_with_slice(bytes: []const u8, slice: []const u8) bool {
|
||||
if (slice.len <= bytes.len) {
|
||||
if (byte_equal(bytes[0..slice.len], slice)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn ends_with_slice(bytes: []const u8, slice: []const u8) bool {
|
||||
if (slice.len <= bytes.len) {
|
||||
if (byte_equal(bytes[bytes.len - slice.len..], slice)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn first_byte(bytes: []const u8, byte: u8) ?usize {
|
||||
for (bytes, 0..) |b, i| {
|
||||
if (b == byte) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn first_slice(bytes: []const u8, slice: []const u8) ?usize {
|
||||
if (slice.len <= bytes.len) {
|
||||
const top = bytes.len - slice.len;
|
||||
var i: usize = 0;
|
||||
|
||||
while (i < top) : (i += 1) {
|
||||
const chunk = bytes[i..][0..slice.len];
|
||||
if (byte_equal(chunk, slice)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn last_byte(bytes: []const u8, byte: u8) ?usize {
|
||||
var i = bytes.len;
|
||||
while (i > 0) {
|
||||
i -= 1;
|
||||
|
30
bootstrap/linker/linker.zig
Normal file
30
bootstrap/linker/linker.zig
Normal file
@ -0,0 +1,30 @@
|
||||
const Compilation = @import("../Compilation.zig");
|
||||
const Context = Compilation.Context;
|
||||
const lld = @import("lld.zig");
|
||||
pub const Options = struct{
|
||||
backend: Backend = .lld,
|
||||
output_file_path: []const u8,
|
||||
objects: []const Object,
|
||||
libraries: []const Library,
|
||||
extra_arguments: []const []const u8,
|
||||
link_libc: bool,
|
||||
link_libcpp: bool,
|
||||
};
|
||||
|
||||
const Backend = enum{
|
||||
lld,
|
||||
};
|
||||
|
||||
pub const Object = struct{
|
||||
path: []const u8,
|
||||
};
|
||||
|
||||
pub const Library = struct{
|
||||
path: []const u8,
|
||||
};
|
||||
|
||||
pub fn link(context: *const Context, options: Options) !void {
|
||||
switch (options.backend) {
|
||||
.lld => try lld.link(context, options),
|
||||
}
|
||||
}
|
126
bootstrap/linker/lld.zig
Normal file
126
bootstrap/linker/lld.zig
Normal file
@ -0,0 +1,126 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const linker = @import("linker.zig");
|
||||
|
||||
const library = @import("../library.zig");
|
||||
const UnpinnedArray = library.UnpinnedArray;
|
||||
|
||||
const Compilation = @import("../Compilation.zig");
|
||||
const write = Compilation.write;
|
||||
|
||||
pub fn link(context: *const Compilation.Context, options: linker.Options) !void {
|
||||
assert(options.backend == .lld);
|
||||
var argv = UnpinnedArray([]const u8){};
|
||||
const driver_program = switch (@import("builtin").os.tag) {
|
||||
.windows => "lld-link",
|
||||
.linux => "ld.lld",
|
||||
.macos => "ld64.lld",
|
||||
else => @compileError("OS not supported"),
|
||||
};
|
||||
try argv.append(context.my_allocator, driver_program);
|
||||
try argv.append(context.my_allocator, "--error-limit=0");
|
||||
|
||||
// const output_path = out_path orelse "a.out";
|
||||
try argv.append(context.my_allocator, "-o");
|
||||
const is_dylib = library.ends_with_slice(options.output_file_path, ".dylib");
|
||||
try argv.append(context.my_allocator, options.output_file_path);
|
||||
if (library.byte_equal(options.output_file_path, "lib/LLVMHello.dylib")) {
|
||||
assert(is_dylib);
|
||||
}
|
||||
|
||||
try argv.append_slice(context.my_allocator, options.extra_arguments);
|
||||
|
||||
for (options.objects) |object| {
|
||||
try argv.append(context.my_allocator, object.path);
|
||||
}
|
||||
|
||||
switch (@import("builtin").os.tag) {
|
||||
.macos => {
|
||||
try argv.append(context.my_allocator, "-dynamic");
|
||||
try argv.append_slice(context.my_allocator, &.{ "-platform_version", "macos", "13.4.1", "13.3" });
|
||||
try argv.append(context.my_allocator, "-arch");
|
||||
try argv.append(context.my_allocator, switch (@import("builtin").cpu.arch) {
|
||||
.aarch64 => "arm64",
|
||||
else => |t| @panic(@tagName(t)),
|
||||
});
|
||||
try argv.append_slice(context.my_allocator, &.{ "-syslibroot", "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk" });
|
||||
|
||||
if (!library.ends_with_slice(options.output_file_path, ".dylib")) {
|
||||
try argv.append_slice(context.my_allocator, &.{ "-e", "_main" });
|
||||
}
|
||||
|
||||
try argv.append(context.my_allocator, "-lSystem");
|
||||
|
||||
if (options.link_libcpp) {
|
||||
try argv.append(context.my_allocator, "-L/Library/Developer/CommandLineTools/SDKs/MacOSX13.3.sdk/usr/lib");
|
||||
try argv.append(context.my_allocator, "-lc++");
|
||||
}
|
||||
},
|
||||
.linux => {
|
||||
if (options.link_libcpp) {
|
||||
assert(options.link_libc);
|
||||
try argv.append(context.my_allocator, "/usr/lib/libstdc++.so" );
|
||||
}
|
||||
|
||||
if (options.link_libc) {
|
||||
try argv.append(context.my_allocator, "/usr/lib/crt1.o");
|
||||
try argv.append(context.my_allocator, "/usr/lib/crti.o");
|
||||
try argv.append_slice(context.my_allocator, &.{ "-L", "/usr/lib" });
|
||||
try argv.append_slice(context.my_allocator, &.{ "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2" });
|
||||
try argv.append(context.my_allocator, "--as-needed");
|
||||
try argv.append(context.my_allocator, "-lm");
|
||||
try argv.append(context.my_allocator, "-lpthread");
|
||||
try argv.append(context.my_allocator, "-lc");
|
||||
try argv.append(context.my_allocator, "-ldl");
|
||||
try argv.append(context.my_allocator, "-lrt");
|
||||
try argv.append(context.my_allocator, "-lutil");
|
||||
try argv.append(context.my_allocator, "/usr/lib/crtn.o");
|
||||
}
|
||||
},
|
||||
else => @compileError("OS not supported"),
|
||||
}
|
||||
|
||||
|
||||
for (options.libraries) |lib| {
|
||||
try argv.append(context.my_allocator, try std.mem.concat(context.allocator, u8, &.{"-l", lib.path}));
|
||||
}
|
||||
|
||||
const argv_zero_terminated = try Compilation.argsCopyZ(context.allocator, argv.slice());
|
||||
|
||||
var stdout_ptr: [*]const u8 = undefined;
|
||||
var stdout_len: usize = 0;
|
||||
var stderr_ptr: [*]const u8 = undefined;
|
||||
var stderr_len: usize = 0;
|
||||
const result = switch (@import("builtin").os.tag) {
|
||||
.linux => NativityLLDLinkELF (argv_zero_terminated.ptr, argv_zero_terminated.len, &stdout_ptr, &stdout_len, &stderr_ptr, &stderr_len),
|
||||
.macos => NativityLLDLinkMachO (argv_zero_terminated.ptr, argv_zero_terminated.len, &stdout_ptr, &stdout_len, &stderr_ptr, &stderr_len),
|
||||
.windows => NativityLLDLinkCOFF(argv_zero_terminated.ptr, argv_zero_terminated.len, &stdout_ptr, &stdout_len, &stderr_ptr, &stderr_len),
|
||||
else => @compileError("OS not supported"),
|
||||
};
|
||||
|
||||
if (!result) {
|
||||
const stdout = stdout_ptr[0..stdout_len];
|
||||
const stderr = stderr_ptr[0..stderr_len];
|
||||
for (argv.slice()) |arg| {
|
||||
try write(.panic, arg);
|
||||
try write(.panic, " ");
|
||||
}
|
||||
try write(.panic, "\n");
|
||||
if (stdout.len > 0) {
|
||||
try write(.panic, stdout);
|
||||
try write(.panic, "\n");
|
||||
}
|
||||
|
||||
if (stderr.len > 0) {
|
||||
try write(.panic, stderr);
|
||||
try write(.panic, "\n");
|
||||
}
|
||||
|
||||
@panic("Linking with LLD failed");
|
||||
}
|
||||
}
|
||||
|
||||
extern fn NativityLLDLinkELF(argument_ptr: [*:null]?[*:0]u8, argument_count: usize, stdout_ptr: *[*]const u8, stdout_len: *usize, stderr_ptr: *[*]const u8, stderr_len: *usize) bool;
|
||||
extern fn NativityLLDLinkCOFF(argument_ptr: [*:null]?[*:0]u8, argument_count: usize, stdout_ptr: *[*]const u8, stdout_len: *usize, stderr_ptr: *[*]const u8, stderr_len: *usize) bool;
|
||||
extern fn NativityLLDLinkMachO(argument_ptr: [*:null]?[*:0]u8, argument_count: usize, stdout_ptr: *[*]const u8, stdout_len: *usize, stderr_ptr: *[*]const u8, stderr_len: *usize) bool;
|
||||
extern fn NativityLLDLinkWasm(argument_ptr: [*:null]?[*:0]u8, argument_count: usize, stdout_ptr: *[*]const u8, stdout_len: *usize, stderr_ptr: *[*]const u8, stderr_len: *usize) bool;
|
@ -1,5 +1,6 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
const assert = std.debug.assert;
|
||||
|
||||
const Compilation = @import("Compilation.zig");
|
||||
pub const panic = Compilation.panic;
|
||||
@ -21,35 +22,53 @@ fn todo() noreturn {
|
||||
}
|
||||
|
||||
var my_allocator = PageAllocator{};
|
||||
pub export fn main(c_argc: c_int, c_argv: [*][*:0]c_char, c_envp: [*:null]?[*:0]c_char) callconv(.C) c_int {
|
||||
_ = c_envp; // autofix
|
||||
const argument_count: usize = @intCast(c_argc);
|
||||
const argument_values: [*][*:0]u8 = @ptrCast(c_argv);
|
||||
const arguments = argument_values[0..argument_count];
|
||||
if (entry_point(arguments)) |_| {
|
||||
return 0;
|
||||
} else |err| {
|
||||
const print_stack_trace = @import("configuration").print_stack_trace;
|
||||
switch (print_stack_trace) {
|
||||
true => if (@errorReturnTrace()) |trace| {
|
||||
std.debug.dumpStackTrace(trace.*);
|
||||
},
|
||||
false => {
|
||||
const error_name: []const u8 = @errorName(err);
|
||||
Compilation.write(.panic, "Error: ") catch {};
|
||||
Compilation.write(.panic, error_name) catch {};
|
||||
Compilation.write(.panic, "\n") catch {};
|
||||
},
|
||||
}
|
||||
// pub export fn main(c_argc: c_int, c_argv: [*][*:0]c_char, c_envp: [*:null]?[*:0]c_char) callconv(.C) c_int {
|
||||
// _ = c_envp; // autofix
|
||||
// // const argument_count: usize = @intCast(c_argc);
|
||||
// // const argument_values: [*][*:0]u8 = @ptrCast(c_argv);
|
||||
// if (entry_point(arguments)) |_| {
|
||||
// return 0;
|
||||
// } else |err| {
|
||||
// const print_stack_trace = @import("configuration").print_stack_trace;
|
||||
// switch (print_stack_trace) {
|
||||
// true => if (@errorReturnTrace()) |trace| {
|
||||
// std.debug.dumpStackTrace(trace.*);
|
||||
// },
|
||||
// false => {
|
||||
// const error_name: []const u8 = @errorName(err);
|
||||
// Compilation.write(.panic, "Error: ") catch {};
|
||||
// Compilation.write(.panic, error_name) catch {};
|
||||
// Compilation.write(.panic, "\n") catch {};
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// return 1;
|
||||
// }
|
||||
// }
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn entry_point(arguments: [][*:0]u8) !void {
|
||||
pub fn main() !void {
|
||||
var arena_allocator = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
const allocator = arena_allocator.allocator();
|
||||
// const arguments = try std.process.argsAlloc(allocator);
|
||||
var arg_it = std.process.ArgIterator.init();
|
||||
var args = library.UnpinnedArray([]const u8){};
|
||||
const context = try Compilation.createContext(allocator, &my_allocator.allocator);
|
||||
while (arg_it.next()) |arg| {
|
||||
try args.append(context.my_allocator, arg);
|
||||
}
|
||||
const arguments = args.slice();
|
||||
const debug_args = true;
|
||||
if (debug_args) {
|
||||
assert(arguments.len > 0);
|
||||
const home_dir = std.posix.getenv("HOME") orelse unreachable;
|
||||
const timestamp = std.time.milliTimestamp();
|
||||
var argument_list = std.ArrayList(u8).init(std.heap.page_allocator);
|
||||
for (arguments) |arg| {
|
||||
argument_list.appendSlice(arg) catch {};
|
||||
argument_list.append(' ') catch {};
|
||||
}
|
||||
argument_list.append('\n') catch {};
|
||||
std.fs.cwd().writeFile(std.fmt.allocPrint(std.heap.page_allocator, "{s}/dev/nativity/nat/invocation_log_{}", .{home_dir, timestamp}) catch unreachable, argument_list.items) catch {};
|
||||
}
|
||||
|
||||
if (arguments.len <= 1) {
|
||||
return error.InvalidInput;
|
||||
@ -59,15 +78,14 @@ pub fn entry_point(arguments: [][*:0]u8) !void {
|
||||
todo();
|
||||
}
|
||||
|
||||
const command = library.span(arguments[1]);
|
||||
const command = arguments[1];
|
||||
const command_arguments = arguments[2..];
|
||||
|
||||
const context = try Compilation.createContext(allocator, &my_allocator.allocator);
|
||||
if (byte_equal(command, "build")) {
|
||||
try Compilation.compileBuildExecutable(context, command_arguments);
|
||||
} else if (byte_equal(command, "clang") or byte_equal(command, "-cc1") or byte_equal(command, "-cc1as")) {
|
||||
// const exit_code = try clangMain(allocator, arguments);
|
||||
// std.process.exit(exit_code);
|
||||
const exit_code = try Compilation.clangMain(allocator, arguments);
|
||||
std.process.exit(exit_code);
|
||||
} else if (byte_equal(command, "cc")) {
|
||||
try Compilation.compileCSourceFile(context, command_arguments, .c);
|
||||
} else if (byte_equal(command, "c++")) {
|
||||
@ -88,3 +106,7 @@ pub fn entry_point(arguments: [][*:0]u8) !void {
|
||||
todo();
|
||||
}
|
||||
}
|
||||
|
||||
pub const std_options = std.Options{
|
||||
.enable_segfault_handler = false,
|
||||
};
|
||||
|
@ -353,10 +353,10 @@ fn runStdTests(allocator: Allocator) !void {
|
||||
if (errors) return error.fail;
|
||||
}
|
||||
|
||||
fn runCmakeTests(allocator: Allocator) !void {
|
||||
fn runCmakeTests(allocator: Allocator, dir_path: []const u8) !void {
|
||||
var errors = false;
|
||||
const original_dir = try std.fs.cwd().realpathAlloc(allocator, ".");
|
||||
const cc_dir = try std.fs.cwd().openDir("test/cc", .{
|
||||
const cc_dir = try std.fs.cwd().openDir(dir_path, .{
|
||||
.iterate = true,
|
||||
});
|
||||
|
||||
@ -379,8 +379,10 @@ fn runCmakeTests(allocator: Allocator) !void {
|
||||
.argv = &.{
|
||||
"cmake",
|
||||
"..",
|
||||
"-G", "Unix Makefiles",
|
||||
"-DCMAKE_VERBOSE_MAKEFILE=On",
|
||||
// "--debug-trycompile",
|
||||
// "--debug-output",
|
||||
// "-G", "Unix Makefiles",
|
||||
// "-DCMAKE_VERBOSE_MAKEFILE=On",
|
||||
try std.mem.concat(allocator, u8, &.{ "-DCMAKE_C_COMPILER=", "nat;cc" }),
|
||||
try std.mem.concat(allocator, u8, &.{ "-DCMAKE_CXX_COMPILER=", "nat;c++" }),
|
||||
try std.mem.concat(allocator, u8, &.{ "-DCMAKE_ASM_COMPILER=", "nat;cc" }),
|
||||
@ -399,13 +401,11 @@ fn runCmakeTests(allocator: Allocator) !void {
|
||||
break :b false;
|
||||
};
|
||||
|
||||
if (!cmake_success) {
|
||||
if (cmake.stdout.len > 0) {
|
||||
std.debug.print("STDOUT:\n\n{s}\n\n", .{cmake.stdout});
|
||||
}
|
||||
if (cmake.stderr.len > 0) {
|
||||
std.debug.print("STDERR:\n\n{s}\n\n", .{cmake.stderr});
|
||||
}
|
||||
if (cmake.stdout.len > 0) {
|
||||
std.debug.print("STDOUT:\n\n{s}\n\n", .{cmake.stdout});
|
||||
}
|
||||
if (cmake.stderr.len > 0) {
|
||||
std.debug.print("STDERR:\n\n{s}\n\n", .{cmake.stderr});
|
||||
}
|
||||
|
||||
var success = cmake_success;
|
||||
@ -414,10 +414,10 @@ fn runCmakeTests(allocator: Allocator) !void {
|
||||
.allocator = allocator,
|
||||
// TODO: delete -main_source_file?
|
||||
.argv = &.{
|
||||
"make"
|
||||
"ninja"
|
||||
},
|
||||
.max_output_bytes = std.math.maxInt(u64),
|
||||
});
|
||||
});
|
||||
const ninja_result: TestError!bool = switch (ninja.term) {
|
||||
.Exited => |exit_code| if (exit_code == 0) true else error.abnormal_exit_code,
|
||||
.Signal => error.signaled,
|
||||
@ -429,6 +429,7 @@ fn runCmakeTests(allocator: Allocator) !void {
|
||||
errors = true;
|
||||
break :b false;
|
||||
};
|
||||
|
||||
if (!ninja_success) {
|
||||
if (ninja.stdout.len > 0) {
|
||||
std.debug.print("STDOUT:\n\n{s}\n\n", .{ninja.stdout});
|
||||
@ -508,15 +509,25 @@ pub fn main() !void {
|
||||
}) catch {
|
||||
errors = true;
|
||||
};
|
||||
|
||||
//
|
||||
runStdTests(allocator) catch {
|
||||
errors = true;
|
||||
};
|
||||
|
||||
runCmakeTests(allocator, "test/cc") catch {
|
||||
errors = true;
|
||||
};
|
||||
runCmakeTests(allocator, "test/c++") catch {
|
||||
errors = true;
|
||||
};
|
||||
|
||||
switch (@import("builtin").os.tag) {
|
||||
.macos => {},
|
||||
// .macos => {},
|
||||
.linux => switch (@import("builtin").abi) {
|
||||
.gnu => try runCmakeTests(allocator),
|
||||
.gnu => runCmakeTests(allocator, "test/cc_linux") catch {
|
||||
errors = true;
|
||||
},
|
||||
.musl => {},
|
||||
else => @compileError("ABI not supported"),
|
||||
},
|
||||
|
6
test/c++/cpp_first/CMakeLists.txt
Normal file
6
test/c++/cpp_first/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(cpp_first CXX)
|
||||
include(CMakePrintHelpers)
|
||||
cmake_print_variables(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES)
|
||||
cmake_print_variables(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES)
|
||||
add_executable(cpp_first main.cpp)
|
@ -1,3 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(c_first C)
|
||||
include(CMakePrintHelpers)
|
||||
cmake_print_variables(CMAKE_C_IMPLICIT_LINK_LIBRARIES)
|
||||
cmake_print_variables(CMAKE_C_IMPLICIT_LINK_DIRECTORIES)
|
||||
add_executable(c_first main.c)
|
||||
|
@ -1,3 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(cpp_first CXX)
|
||||
add_executable(cpp_first main.cpp)
|
2
test/cc_linux/c_asm/.gitignore
vendored
Normal file
2
test/cc_linux/c_asm/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*.o
|
||||
build/
|
3
test/cc_linux/c_asm/CMakeLists.txt
Normal file
3
test/cc_linux/c_asm/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
project(c_asm C ASM)
|
||||
add_executable(c_asm main.c assembly.S)
|
4
test/cc_linux/c_asm/assembly.S
Normal file
4
test/cc_linux/c_asm/assembly.S
Normal file
@ -0,0 +1,4 @@
|
||||
.global foo
|
||||
foo:
|
||||
mov $42, %eax
|
||||
ret
|
7
test/cc_linux/c_asm/main.c
Normal file
7
test/cc_linux/c_asm/main.c
Normal file
@ -0,0 +1,7 @@
|
||||
extern int foo();
|
||||
#include <assert.h>
|
||||
int main()
|
||||
{
|
||||
assert(foo() == 42);
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user