sm
This commit is contained in:
80
src/main.zig
80
src/main.zig
@@ -34,7 +34,25 @@ pub fn main(init: std.process.Init) !void {
|
||||
if (std.mem.eql(u8, arg, "--target")) {
|
||||
i += 1;
|
||||
if (i >= args.len) { std.debug.print("error: --target requires a value\n", .{}); return; }
|
||||
target_config.triple = (try allocator.dupeZ(u8, args[i])).ptr;
|
||||
const raw = args[i];
|
||||
// Shorthand aliases for common targets
|
||||
const expanded = if (std.mem.eql(u8, raw, "wasm") or std.mem.eql(u8, raw, "wasm32") or std.mem.eql(u8, raw, "emscripten"))
|
||||
"wasm32-unknown-emscripten"
|
||||
else if (std.mem.eql(u8, raw, "wasm64"))
|
||||
"wasm64-unknown-emscripten"
|
||||
else if (std.mem.eql(u8, raw, "macos") or std.mem.eql(u8, raw, "macos-arm"))
|
||||
"aarch64-apple-macos"
|
||||
else if (std.mem.eql(u8, raw, "macos-x86"))
|
||||
"x86_64-apple-macos"
|
||||
else if (std.mem.eql(u8, raw, "linux") or std.mem.eql(u8, raw, "linux-x86"))
|
||||
"x86_64-unknown-linux-gnu"
|
||||
else if (std.mem.eql(u8, raw, "linux-arm"))
|
||||
"aarch64-unknown-linux-gnu"
|
||||
else if (std.mem.eql(u8, raw, "windows"))
|
||||
"x86_64-windows-msvc"
|
||||
else
|
||||
raw;
|
||||
target_config.triple = (try allocator.dupeZ(u8, expanded)).ptr;
|
||||
} else if (std.mem.eql(u8, arg, "--cpu")) {
|
||||
i += 1;
|
||||
if (i >= args.len) { std.debug.print("error: --cpu requires a value\n", .{}); return; }
|
||||
@@ -100,7 +118,6 @@ pub fn main(init: std.process.Init) !void {
|
||||
break :blk base;
|
||||
};
|
||||
compile(allocator, io, path, output_name, target_config, show_timing, enable_cache) catch return;
|
||||
std.debug.print("compiled: {s}\n", .{output_name});
|
||||
} else if (std.mem.eql(u8, command, "ir")) {
|
||||
emitIR(allocator, io, path, target_config) catch return;
|
||||
} else if (std.mem.eql(u8, command, "ir-dump")) {
|
||||
@@ -219,17 +236,17 @@ fn compileCForJIT(allocator: std.mem.Allocator, io: std.Io, comp: *sx.core.Compi
|
||||
}
|
||||
|
||||
/// Compile C sources from #import c blocks to .o files for linking.
|
||||
fn compileCForBuild(allocator: std.mem.Allocator, io: std.Io, comp: *sx.core.Compilation) ![]const []const u8 {
|
||||
fn compileCForBuild(allocator: std.mem.Allocator, io: std.Io, comp: *sx.core.Compilation, tmp_dir: []const u8) ![]const []const u8 {
|
||||
const c_infos = try comp.collectCImportSources();
|
||||
if (c_infos.len == 0) return &.{};
|
||||
|
||||
// For Emscripten targets, use emcc to cross-compile C sources
|
||||
if (comp.target_config.isEmscripten()) {
|
||||
return try sx.c_import.compileCWithEmcc(allocator, io, c_infos);
|
||||
return try sx.c_import.compileCWithEmcc(allocator, io, c_infos, comp.target_config, tmp_dir);
|
||||
}
|
||||
|
||||
const obj_bufs = try sx.c_import.compileCToObjects(allocator, c_infos);
|
||||
return try sx.c_import.writeCObjectFiles(allocator, io, obj_bufs);
|
||||
return try sx.c_import.writeCObjectFiles(allocator, io, obj_bufs, tmp_dir);
|
||||
}
|
||||
|
||||
fn parseOptLevel(s: []const u8) ?sx.target.TargetConfig.OptLevel {
|
||||
@@ -252,7 +269,7 @@ fn printUsage() void {
|
||||
\\ lsp Start language server (LSP)
|
||||
\\
|
||||
\\Options:
|
||||
\\ --target <triple> Target triple (default: host)
|
||||
\\ --target <target> Target triple or shorthand: wasm, macos, linux, windows (default: host)
|
||||
\\ --cpu <name> CPU name (default: generic)
|
||||
\\ --opt <level> Optimization: none/0, less/1, default/2, aggressive/3
|
||||
\\ -o <path> Output path
|
||||
@@ -408,7 +425,11 @@ fn compileWithTimer(allocator: std.mem.Allocator, io: std.Io, input_path: []cons
|
||||
const root = comp.resolved_root orelse comp.root orelse return error.CompileError;
|
||||
const libs = try extractLibraries(allocator, root);
|
||||
|
||||
const obj_path = try std.fmt.allocPrintSentinel(allocator, "{s}.o", .{output_path}, 0);
|
||||
// Create temp directory for build artifacts
|
||||
const tmp_dir: []const u8 = ".sx-tmp";
|
||||
std.Io.Dir.createDirPath(.cwd(), io, tmp_dir) catch {};
|
||||
|
||||
const obj_path = try std.fmt.allocPrintSentinel(allocator, "{s}/main.o", .{tmp_dir}, 0);
|
||||
|
||||
// Cache: compute key and check for cached binary/.o
|
||||
const key = computeCacheKey(source, &comp.import_sources, target_config);
|
||||
@@ -453,15 +474,37 @@ fn compileWithTimer(allocator: std.mem.Allocator, io: std.Io, input_path: []cons
|
||||
|
||||
// Compile C sources from #import c blocks to .o files
|
||||
timer.mark();
|
||||
const c_obj_paths = compileCForBuild(allocator, io, &comp) catch {
|
||||
const c_obj_paths = compileCForBuild(allocator, io, &comp, tmp_dir) catch {
|
||||
std.debug.print("error: C import compilation failed\n", .{});
|
||||
return error.CompileError;
|
||||
};
|
||||
timer.record("c-import");
|
||||
|
||||
// Merge build config (from #run blocks) with CLI config
|
||||
var merged_config = target_config;
|
||||
const build_flags = comp.getBuildLinkFlags();
|
||||
if (build_flags.len > 0) {
|
||||
var all_flags: std.ArrayList([]const u8) = .empty;
|
||||
for (target_config.extra_link_flags) |f| try all_flags.append(allocator, f);
|
||||
for (build_flags) |f| try all_flags.append(allocator, f);
|
||||
merged_config.extra_link_flags = try all_flags.toOwnedSlice(allocator);
|
||||
}
|
||||
// Override output path from #run if set (and no explicit -o was given on CLI)
|
||||
const final_output = if (target_config.output_path == null)
|
||||
(comp.getBuildOutputPath() orelse output_path)
|
||||
else
|
||||
output_path;
|
||||
|
||||
// Ensure output directory exists
|
||||
if (std.mem.lastIndexOfScalar(u8, final_output, '/')) |sep| {
|
||||
if (sep > 0) {
|
||||
std.Io.Dir.createDirPath(.cwd(), io, final_output[0..sep]) catch {};
|
||||
}
|
||||
}
|
||||
|
||||
// Link (sx .o + C .o files)
|
||||
timer.mark();
|
||||
sx.target.link(allocator, io, obj_path, c_obj_paths, output_path, libs, target_config) catch {
|
||||
sx.target.link(allocator, io, obj_path, c_obj_paths, final_output, libs, merged_config) catch {
|
||||
std.debug.print("error: linking failed\n", .{});
|
||||
return error.CompileError;
|
||||
};
|
||||
@@ -472,11 +515,16 @@ fn compileWithTimer(allocator: std.mem.Allocator, io: std.Io, input_path: []cons
|
||||
std.Io.Dir.copyFile(.cwd(), output_path, .cwd(), cache_bin, io, .{ .make_path = true }) catch {};
|
||||
}
|
||||
|
||||
// Clean up object files
|
||||
std.debug.print("compiled: {s}\n", .{final_output});
|
||||
|
||||
// Clean up temp directory and all build artifacts
|
||||
std.Io.Dir.deleteFile(.cwd(), io, obj_path) catch {};
|
||||
const shell_tmp = std.fmt.allocPrint(allocator, "{s}.shell.html", .{obj_path}) catch null;
|
||||
if (shell_tmp) |sp| std.Io.Dir.deleteFile(.cwd(), io, sp) catch {};
|
||||
for (c_obj_paths) |cop| {
|
||||
std.Io.Dir.deleteFile(.cwd(), io, cop) catch {};
|
||||
}
|
||||
std.Io.Dir.deleteDir(.cwd(), io, tmp_dir) catch {};
|
||||
}
|
||||
|
||||
fn runAOT(allocator: std.mem.Allocator, io: std.Io, input_path: []const u8, target_config: sx.target.TargetConfig, timer: *Timing, enable_cache: bool) !void {
|
||||
@@ -556,13 +604,21 @@ fn hasTopLevelRun(root: *const sx.ast.Node) bool {
|
||||
|
||||
fn extractLibraries(allocator: std.mem.Allocator, root: *const sx.ast.Node) ![]const []const u8 {
|
||||
var libs = std.ArrayList([]const u8).empty;
|
||||
var seen = std.StringHashMap(void).init(allocator);
|
||||
const addLib = struct {
|
||||
fn f(l: *std.ArrayList([]const u8), s: *std.StringHashMap(void), a: std.mem.Allocator, name: []const u8) !void {
|
||||
if (s.contains(name)) return;
|
||||
try s.put(name, {});
|
||||
try l.append(a, name);
|
||||
}
|
||||
}.f;
|
||||
for (root.data.root.decls) |decl| {
|
||||
switch (decl.data) {
|
||||
.library_decl => |ld| try libs.append(allocator, ld.lib_name),
|
||||
.library_decl => |ld| try addLib(&libs, &seen, allocator, ld.lib_name),
|
||||
.namespace_decl => |ns| {
|
||||
for (ns.decls) |nd| {
|
||||
switch (nd.data) {
|
||||
.library_decl => |ld| try libs.append(allocator, ld.lib_name),
|
||||
.library_decl => |ld| try addLib(&libs, &seen, allocator, ld.lib_name),
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user