stage2: add CLI for `zig translate-c`

master
Andrew Kelley 2020-09-18 01:33:32 -07:00
parent a9b18023a4
commit dc79651e6a
5 changed files with 93 additions and 35 deletions

View File

@ -1,4 +1,3 @@
* `zig translate-c`
* `zig test` * `zig test`
* `zig build` * `zig build`
* `-ftime-report` * `-ftime-report`

View File

@ -392,15 +392,18 @@ if(ZIG_TEST_COVERAGE)
set(EXE_LDFLAGS "${EXE_LDFLAGS} -fprofile-arcs -ftest-coverage") set(EXE_LDFLAGS "${EXE_LDFLAGS} -fprofile-arcs -ftest-coverage")
endif() endif()
add_library(zig_cpp STATIC ${ZIG_CPP_SOURCES}) add_library(zig_cpp STATIC ${ZIG_SOURCES} ${ZIG_CPP_SOURCES})
set_target_properties(zig_cpp PROPERTIES set_target_properties(zig_cpp PROPERTIES
COMPILE_FLAGS ${EXE_CFLAGS} COMPILE_FLAGS ${EXE_CFLAGS}
) )
target_link_libraries(zig_cpp LINK_PUBLIC target_link_libraries(zig_cpp LINK_PUBLIC
opt_c_util
${SOFTFLOAT_LIBRARIES}
${CLANG_LIBRARIES} ${CLANG_LIBRARIES}
${LLD_LIBRARIES} ${LLD_LIBRARIES}
${LLVM_LIBRARIES} ${LLVM_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
) )
if(ZIG_WORKAROUND_POLLY_SO) if(ZIG_WORKAROUND_POLLY_SO)
target_link_libraries(zig_cpp LINK_PUBLIC "-Wl,${ZIG_WORKAROUND_POLLY_SO}") target_link_libraries(zig_cpp LINK_PUBLIC "-Wl,${ZIG_WORKAROUND_POLLY_SO}")
@ -411,27 +414,16 @@ set_target_properties(opt_c_util PROPERTIES
COMPILE_FLAGS "${OPTIMIZED_C_FLAGS}" COMPILE_FLAGS "${OPTIMIZED_C_FLAGS}"
) )
add_library(zigcompiler STATIC ${ZIG_SOURCES})
set_target_properties(zigcompiler PROPERTIES
COMPILE_FLAGS ${EXE_CFLAGS}
LINK_FLAGS ${EXE_LDFLAGS}
)
target_link_libraries(zigcompiler LINK_PUBLIC
zig_cpp
opt_c_util
${SOFTFLOAT_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
)
if(NOT MSVC) if(NOT MSVC)
target_link_libraries(zigcompiler LINK_PUBLIC ${LIBXML2}) target_link_libraries(zig_cpp LINK_PUBLIC ${LIBXML2})
endif() endif()
if(ZIG_DIA_GUIDS_LIB) if(ZIG_DIA_GUIDS_LIB)
target_link_libraries(zigcompiler LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB}) target_link_libraries(zig_cpp LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB})
endif() endif()
if(MSVC OR MINGW) if(MSVC OR MINGW)
target_link_libraries(zigcompiler LINK_PUBLIC version) target_link_libraries(zig_cpp LINK_PUBLIC version)
endif() endif()
add_executable(zig0 ${ZIG0_SOURCES}) add_executable(zig0 ${ZIG0_SOURCES})
@ -439,7 +431,7 @@ set_target_properties(zig0 PROPERTIES
COMPILE_FLAGS ${EXE_CFLAGS} COMPILE_FLAGS ${EXE_CFLAGS}
LINK_FLAGS ${EXE_LDFLAGS} LINK_FLAGS ${EXE_LDFLAGS}
) )
target_link_libraries(zig0 zigcompiler) target_link_libraries(zig0 zig_cpp)
if(MSVC) if(MSVC)
set(ZIG1_OBJECT "${CMAKE_BINARY_DIR}/zig1.obj") set(ZIG1_OBJECT "${CMAKE_BINARY_DIR}/zig1.obj")
@ -493,7 +485,7 @@ set_target_properties(zig PROPERTIES
COMPILE_FLAGS ${EXE_CFLAGS} COMPILE_FLAGS ${EXE_CFLAGS}
LINK_FLAGS ${EXE_LDFLAGS} LINK_FLAGS ${EXE_LDFLAGS}
) )
target_link_libraries(zig zigcompiler "${ZIG1_OBJECT}") target_link_libraries(zig "${ZIG1_OBJECT}" zig_cpp)
if(MSVC) if(MSVC)
target_link_libraries(zig ntdll.lib) target_link_libraries(zig ntdll.lib)
elseif(MINGW) elseif(MINGW)

View File

@ -1005,7 +1005,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
defer tracy.end(); defer tracy.end();
if (!build_options.have_llvm) { if (!build_options.have_llvm) {
return comp.failCObj(c_object, "clang not available: compiler not built with LLVM extensions enabled", .{}); return comp.failCObj(c_object, "clang not available: compiler built without LLVM extensions", .{});
} }
const self_exe_path = comp.self_exe_path orelse const self_exe_path = comp.self_exe_path orelse
return comp.failCObj(c_object, "clang compilation disabled", .{}); return comp.failCObj(c_object, "clang compilation disabled", .{});
@ -1081,10 +1081,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
try argv.appendSlice(c_object.src.extra_flags); try argv.appendSlice(c_object.src.extra_flags);
if (comp.verbose_cc) { if (comp.verbose_cc) {
for (argv.items[0 .. argv.items.len - 1]) |arg| { dump_argv(argv.items);
std.debug.print("{} ", .{arg});
}
std.debug.print("{}\n", .{argv.items[argv.items.len - 1]});
} }
const child = try std.ChildProcess.init(argv.items, arena); const child = try std.ChildProcess.init(argv.items, arena);
@ -1190,7 +1187,7 @@ fn tmpFilePath(comp: *Compilation, arena: *Allocator, suffix: []const u8) error{
} }
/// Add common C compiler args between translate-c and C object compilation. /// Add common C compiler args between translate-c and C object compilation.
fn addCCArgs( pub fn addCCArgs(
comp: *Compilation, comp: *Compilation,
arena: *Allocator, arena: *Allocator,
argv: *std.ArrayList([]const u8), argv: *std.ArrayList([]const u8),
@ -1671,12 +1668,19 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool {
} }
fn updateBuiltinZigFile(comp: *Compilation, mod: *Module) !void { fn updateBuiltinZigFile(comp: *Compilation, mod: *Module) !void {
const source = try comp.generateBuiltinZigSource(); const source = try comp.generateBuiltinZigSource(comp.gpa);
defer comp.gpa.free(source); defer comp.gpa.free(source);
try mod.zig_cache_artifact_directory.handle.writeFile("builtin.zig", source); try mod.zig_cache_artifact_directory.handle.writeFile("builtin.zig", source);
} }
pub fn generateBuiltinZigSource(comp: *Compilation) ![]u8 { pub fn dump_argv(argv: []const []const u8) void {
for (argv[0 .. argv.len - 1]) |arg| {
std.debug.print("{} ", .{arg});
}
std.debug.print("{}\n", .{argv[argv.len - 1]});
}
pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 {
var buffer = std.ArrayList(u8).init(comp.gpa); var buffer = std.ArrayList(u8).init(comp.gpa);
defer buffer.deinit(); defer buffer.deinit();

View File

@ -15,6 +15,7 @@ const build_options = @import("build_options");
const warn = std.log.warn; const warn = std.log.warn;
const introspect = @import("introspect.zig"); const introspect = @import("introspect.zig");
const LibCInstallation = @import("libc_installation.zig").LibCInstallation; const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
const translate_c = @import("translate_c.zig");
pub fn fatal(comptime format: []const u8, args: anytype) noreturn { pub fn fatal(comptime format: []const u8, args: anytype) noreturn {
std.log.emerg(format, args); std.log.emerg(format, args);
@ -864,6 +865,10 @@ pub fn buildOutputType(
} }
} }
if (arg_mode == .translate_c and c_source_files.items.len != 1) {
fatal("translate-c expects exactly 1 source file (found {})", .{c_source_files.items.len});
}
const root_name = if (provided_name) |n| n else blk: { const root_name = if (provided_name) |n| n else blk: {
if (root_src_file) |file| { if (root_src_file) |file| {
const basename = fs.path.basename(file); const basename = fs.path.basename(file);
@ -1175,10 +1180,10 @@ pub fn buildOutputType(
defer comp.destroy(); defer comp.destroy();
if (show_builtin) { if (show_builtin) {
const source = try comp.generateBuiltinZigSource(); return std.io.getStdOut().writeAll(try comp.generateBuiltinZigSource(arena));
defer comp.gpa.free(source); }
try std.io.getStdOut().writeAll(source); if (arg_mode == .translate_c) {
return; return cmdTranslateC(comp, arena);
} }
try updateModule(gpa, comp, zir_out_path); try updateModule(gpa, comp, zir_out_path);
@ -1248,6 +1253,63 @@ fn updateModule(gpa: *Allocator, comp: *Compilation, zir_out_path: ?[]const u8)
} }
} }
fn cmdTranslateC(comp: *Compilation, arena: *Allocator) !void {
if (!build_options.have_llvm)
fatal("cannot translate-c: compiler built without LLVM extensions", .{});
assert(comp.c_source_files.len == 1);
var argv = std.ArrayList([]const u8).init(arena);
const c_source_file = comp.c_source_files[0];
const file_ext = Compilation.classifyFileExt(c_source_file.src_path);
try comp.addCCArgs(arena, &argv, file_ext, true, null);
try argv.append(c_source_file.src_path);
if (comp.verbose_cc) {
std.debug.print("clang ", .{});
Compilation.dump_argv(argv.items);
}
// Convert to null terminated args.
const new_argv_with_sentinel = try arena.alloc(?[*:0]const u8, argv.items.len + 1);
new_argv_with_sentinel[argv.items.len] = null;
const new_argv = new_argv_with_sentinel[0..argv.items.len :null];
for (argv.items) |arg, i| {
new_argv[i] = try arena.dupeZ(u8, arg);
}
const c_headers_dir_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{"include"});
const c_headers_dir_path_z = try arena.dupeZ(u8, c_headers_dir_path);
var clang_errors: []translate_c.ClangErrMsg = &[0]translate_c.ClangErrMsg{};
const tree = translate_c.translate(
comp.gpa,
new_argv.ptr,
new_argv.ptr + new_argv.len,
&clang_errors,
c_headers_dir_path_z,
) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
error.ASTUnitFailure => fatal("clang API returned errors but due to a clang bug, it is not exposing the errors for zig to see. For more details: https://github.com/ziglang/zig/issues/4455", .{}),
error.SemanticAnalyzeFail => {
for (clang_errors) |clang_err| {
std.debug.print("{}:{}:{}: {}\n", .{
if (clang_err.filename_ptr) |p| p[0..clang_err.filename_len] else "(no file)",
clang_err.line + 1,
clang_err.column + 1,
clang_err.msg_ptr[0..clang_err.msg_len],
});
}
process.exit(1);
},
};
defer tree.deinit();
var bos = io.bufferedOutStream(io.getStdOut().writer());
_ = try std.zig.render(comp.gpa, bos.writer(), tree);
try bos.flush();
}
pub const usage_libc = pub const usage_libc =
\\Usage: zig libc \\Usage: zig libc
\\ \\
@ -1401,8 +1463,9 @@ pub fn cmdFmt(gpa: *Allocator, args: []const []const u8) !void {
process.exit(code); process.exit(code);
} }
const stdout = io.getStdOut().outStream(); var bos = io.bufferedOutStream(io.getStdOut().writer());
_ = try std.zig.render(gpa, stdout, tree); _ = try std.zig.render(gpa, bos.writer(), tree);
try bos.flush();
return; return;
} }
@ -1644,7 +1707,7 @@ extern "c" fn ZigClang_main(argc: c_int, argv: [*:null]?[*:0]u8) c_int;
/// TODO https://github.com/ziglang/zig/issues/3257 /// TODO https://github.com/ziglang/zig/issues/3257
fn punt_to_clang(arena: *Allocator, args: []const []const u8) error{OutOfMemory} { fn punt_to_clang(arena: *Allocator, args: []const []const u8) error{OutOfMemory} {
if (!build_options.have_llvm) if (!build_options.have_llvm)
fatal("`zig cc` and `zig c++` unavailable: compiler not built with LLVM extensions enabled", .{}); fatal("`zig cc` and `zig c++` unavailable: compiler built without LLVM extensions", .{});
// Convert the args to the format Clang expects. // Convert the args to the format Clang expects.
const argv = try arena.alloc(?[*:0]u8, args.len + 1); const argv = try arena.alloc(?[*:0]u8, args.len + 1);
for (args) |arg, i| { for (args) |arg, i| {

View File

@ -1,5 +1,5 @@
// This is the userland implementation of translate-c which is used by both stage1 //! This is the userland implementation of translate-c which is used by both stage1
// and stage2. //! and stage2.
const std = @import("std"); const std = @import("std");
const assert = std.debug.assert; const assert = std.debug.assert;