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 build`
* `-ftime-report`

View File

@ -392,15 +392,18 @@ if(ZIG_TEST_COVERAGE)
set(EXE_LDFLAGS "${EXE_LDFLAGS} -fprofile-arcs -ftest-coverage")
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
COMPILE_FLAGS ${EXE_CFLAGS}
)
target_link_libraries(zig_cpp LINK_PUBLIC
opt_c_util
${SOFTFLOAT_LIBRARIES}
${CLANG_LIBRARIES}
${LLD_LIBRARIES}
${LLVM_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
)
if(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}"
)
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)
target_link_libraries(zigcompiler LINK_PUBLIC ${LIBXML2})
target_link_libraries(zig_cpp LINK_PUBLIC ${LIBXML2})
endif()
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()
if(MSVC OR MINGW)
target_link_libraries(zigcompiler LINK_PUBLIC version)
target_link_libraries(zig_cpp LINK_PUBLIC version)
endif()
add_executable(zig0 ${ZIG0_SOURCES})
@ -439,7 +431,7 @@ set_target_properties(zig0 PROPERTIES
COMPILE_FLAGS ${EXE_CFLAGS}
LINK_FLAGS ${EXE_LDFLAGS}
)
target_link_libraries(zig0 zigcompiler)
target_link_libraries(zig0 zig_cpp)
if(MSVC)
set(ZIG1_OBJECT "${CMAKE_BINARY_DIR}/zig1.obj")
@ -493,7 +485,7 @@ set_target_properties(zig PROPERTIES
COMPILE_FLAGS ${EXE_CFLAGS}
LINK_FLAGS ${EXE_LDFLAGS}
)
target_link_libraries(zig zigcompiler "${ZIG1_OBJECT}")
target_link_libraries(zig "${ZIG1_OBJECT}" zig_cpp)
if(MSVC)
target_link_libraries(zig ntdll.lib)
elseif(MINGW)

View File

@ -1005,7 +1005,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
defer tracy.end();
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
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);
if (comp.verbose_cc) {
for (argv.items[0 .. argv.items.len - 1]) |arg| {
std.debug.print("{} ", .{arg});
}
std.debug.print("{}\n", .{argv.items[argv.items.len - 1]});
dump_argv(argv.items);
}
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.
fn addCCArgs(
pub fn addCCArgs(
comp: *Compilation,
arena: *Allocator,
argv: *std.ArrayList([]const u8),
@ -1671,12 +1668,19 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool {
}
fn updateBuiltinZigFile(comp: *Compilation, mod: *Module) !void {
const source = try comp.generateBuiltinZigSource();
const source = try comp.generateBuiltinZigSource(comp.gpa);
defer comp.gpa.free(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);
defer buffer.deinit();

View File

@ -15,6 +15,7 @@ const build_options = @import("build_options");
const warn = std.log.warn;
const introspect = @import("introspect.zig");
const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
const translate_c = @import("translate_c.zig");
pub fn fatal(comptime format: []const u8, args: anytype) noreturn {
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: {
if (root_src_file) |file| {
const basename = fs.path.basename(file);
@ -1175,10 +1180,10 @@ pub fn buildOutputType(
defer comp.destroy();
if (show_builtin) {
const source = try comp.generateBuiltinZigSource();
defer comp.gpa.free(source);
try std.io.getStdOut().writeAll(source);
return;
return std.io.getStdOut().writeAll(try comp.generateBuiltinZigSource(arena));
}
if (arg_mode == .translate_c) {
return cmdTranslateC(comp, arena);
}
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 =
\\Usage: zig libc
\\
@ -1401,8 +1463,9 @@ pub fn cmdFmt(gpa: *Allocator, args: []const []const u8) !void {
process.exit(code);
}
const stdout = io.getStdOut().outStream();
_ = try std.zig.render(gpa, stdout, tree);
var bos = io.bufferedOutStream(io.getStdOut().writer());
_ = try std.zig.render(gpa, bos.writer(), tree);
try bos.flush();
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
fn punt_to_clang(arena: *Allocator, args: []const []const u8) error{OutOfMemory} {
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.
const argv = try arena.alloc(?[*:0]u8, args.len + 1);
for (args) |arg, i| {

View File

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