authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-18 01:33:32-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-18 01:33:32-07:00
logdc79651e6a46dc050976feabbb1b5e25a68dcf3f
tree9a2833b5e06778d60ffcabde7bdba37be2498b53
parenta9b18023a4c33a0563fca2aa20a239e3ee38927a

stage2: add CLI for `zig translate-c`


5 files changed, 93 insertions(+), 35 deletions(-)

BRANCH_TODO-1
......@@ -1,4 +1,3 @@
1 * `zig translate-c`
21 * `zig test`
32 * `zig build`
43 * `-ftime-report`
CMakeLists.txt+9-17
......@@ -392,15 +392,18 @@ if(ZIG_TEST_COVERAGE)
392392 set(EXE_LDFLAGS "${EXE_LDFLAGS} -fprofile-arcs -ftest-coverage")
393393endif()
394394
395add_library(zig_cpp STATIC ${ZIG_CPP_SOURCES})
395add_library(zig_cpp STATIC ${ZIG_SOURCES} ${ZIG_CPP_SOURCES})
396396set_target_properties(zig_cpp PROPERTIES
397397 COMPILE_FLAGS ${EXE_CFLAGS}
398398)
399399
400400target_link_libraries(zig_cpp LINK_PUBLIC
401 opt_c_util
402 ${SOFTFLOAT_LIBRARIES}
401403 ${CLANG_LIBRARIES}
402404 ${LLD_LIBRARIES}
403405 ${LLVM_LIBRARIES}
406 ${CMAKE_THREAD_LIBS_INIT}
404407)
405408if(ZIG_WORKAROUND_POLLY_SO)
406409 target_link_libraries(zig_cpp LINK_PUBLIC "-Wl,${ZIG_WORKAROUND_POLLY_SO}")
......@@ -411,27 +414,16 @@ set_target_properties(opt_c_util PROPERTIES
411414 COMPILE_FLAGS "${OPTIMIZED_C_FLAGS}"
412415)
413416
414add_library(zigcompiler STATIC ${ZIG_SOURCES})
415set_target_properties(zigcompiler PROPERTIES
416 COMPILE_FLAGS ${EXE_CFLAGS}
417 LINK_FLAGS ${EXE_LDFLAGS}
418)
419target_link_libraries(zigcompiler LINK_PUBLIC
420 zig_cpp
421 opt_c_util
422 ${SOFTFLOAT_LIBRARIES}
423 ${CMAKE_THREAD_LIBS_INIT}
424)
425417if(NOT MSVC)
426 target_link_libraries(zigcompiler LINK_PUBLIC ${LIBXML2})
418 target_link_libraries(zig_cpp LINK_PUBLIC ${LIBXML2})
427419endif()
428420
429421if(ZIG_DIA_GUIDS_LIB)
430 target_link_libraries(zigcompiler LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB})
422 target_link_libraries(zig_cpp LINK_PUBLIC ${ZIG_DIA_GUIDS_LIB})
431423endif()
432424
433425if(MSVC OR MINGW)
434 target_link_libraries(zigcompiler LINK_PUBLIC version)
426 target_link_libraries(zig_cpp LINK_PUBLIC version)
435427endif()
436428
437429add_executable(zig0 ${ZIG0_SOURCES})
......@@ -439,7 +431,7 @@ set_target_properties(zig0 PROPERTIES
439431 COMPILE_FLAGS ${EXE_CFLAGS}
440432 LINK_FLAGS ${EXE_LDFLAGS}
441433)
442target_link_libraries(zig0 zigcompiler)
434target_link_libraries(zig0 zig_cpp)
443435
444436if(MSVC)
445437 set(ZIG1_OBJECT "${CMAKE_BINARY_DIR}/zig1.obj")
......@@ -493,7 +485,7 @@ set_target_properties(zig PROPERTIES
493485 COMPILE_FLAGS ${EXE_CFLAGS}
494486 LINK_FLAGS ${EXE_LDFLAGS}
495487)
496target_link_libraries(zig zigcompiler "${ZIG1_OBJECT}")
488target_link_libraries(zig "${ZIG1_OBJECT}" zig_cpp)
497489if(MSVC)
498490 target_link_libraries(zig ntdll.lib)
499491elseif(MINGW)
src-self-hosted/Compilation.zig+12-8
......@@ -1005,7 +1005,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
10051005 defer tracy.end();
10061006
10071007 if (!build_options.have_llvm) {
1008 return comp.failCObj(c_object, "clang not available: compiler not built with LLVM extensions enabled", .{});
1008 return comp.failCObj(c_object, "clang not available: compiler built without LLVM extensions", .{});
10091009 }
10101010 const self_exe_path = comp.self_exe_path orelse
10111011 return comp.failCObj(c_object, "clang compilation disabled", .{});
......@@ -1081,10 +1081,7 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
10811081 try argv.appendSlice(c_object.src.extra_flags);
10821082
10831083 if (comp.verbose_cc) {
1084 for (argv.items[0 .. argv.items.len - 1]) |arg| {
1085 std.debug.print("{} ", .{arg});
1086 }
1087 std.debug.print("{}\n", .{argv.items[argv.items.len - 1]});
1084 dump_argv(argv.items);
10881085 }
10891086
10901087 const child = try std.ChildProcess.init(argv.items, arena);
......@@ -1190,7 +1187,7 @@ fn tmpFilePath(comp: *Compilation, arena: *Allocator, suffix: []const u8) error{
11901187}
11911188
11921189/// Add common C compiler args between translate-c and C object compilation.
1193fn addCCArgs(
1190pub fn addCCArgs(
11941191 comp: *Compilation,
11951192 arena: *Allocator,
11961193 argv: *std.ArrayList([]const u8),
......@@ -1671,12 +1668,19 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool {
16711668}
16721669
16731670fn updateBuiltinZigFile(comp: *Compilation, mod: *Module) !void {
1674 const source = try comp.generateBuiltinZigSource();
1671 const source = try comp.generateBuiltinZigSource(comp.gpa);
16751672 defer comp.gpa.free(source);
16761673 try mod.zig_cache_artifact_directory.handle.writeFile("builtin.zig", source);
16771674}
16781675
1679pub fn generateBuiltinZigSource(comp: *Compilation) ![]u8 {
1676pub fn dump_argv(argv: []const []const u8) void {
1677 for (argv[0 .. argv.len - 1]) |arg| {
1678 std.debug.print("{} ", .{arg});
1679 }
1680 std.debug.print("{}\n", .{argv[argv.len - 1]});
1681}
1682
1683pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 {
16801684 var buffer = std.ArrayList(u8).init(comp.gpa);
16811685 defer buffer.deinit();
16821686
src-self-hosted/main.zig+70-7
......@@ -15,6 +15,7 @@ const build_options = @import("build_options");
1515const warn = std.log.warn;
1616const introspect = @import("introspect.zig");
1717const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
18const translate_c = @import("translate_c.zig");
1819
1920pub fn fatal(comptime format: []const u8, args: anytype) noreturn {
2021 std.log.emerg(format, args);
......@@ -864,6 +865,10 @@ pub fn buildOutputType(
864865 }
865866 }
866867
868 if (arg_mode == .translate_c and c_source_files.items.len != 1) {
869 fatal("translate-c expects exactly 1 source file (found {})", .{c_source_files.items.len});
870 }
871
867872 const root_name = if (provided_name) |n| n else blk: {
868873 if (root_src_file) |file| {
869874 const basename = fs.path.basename(file);
......@@ -1175,10 +1180,10 @@ pub fn buildOutputType(
11751180 defer comp.destroy();
11761181
11771182 if (show_builtin) {
1178 const source = try comp.generateBuiltinZigSource();
1179 defer comp.gpa.free(source);
1180 try std.io.getStdOut().writeAll(source);
1181 return;
1183 return std.io.getStdOut().writeAll(try comp.generateBuiltinZigSource(arena));
1184 }
1185 if (arg_mode == .translate_c) {
1186 return cmdTranslateC(comp, arena);
11821187 }
11831188
11841189 try updateModule(gpa, comp, zir_out_path);
......@@ -1248,6 +1253,63 @@ fn updateModule(gpa: *Allocator, comp: *Compilation, zir_out_path: ?[]const u8)
12481253 }
12491254}
12501255
1256fn cmdTranslateC(comp: *Compilation, arena: *Allocator) !void {
1257 if (!build_options.have_llvm)
1258 fatal("cannot translate-c: compiler built without LLVM extensions", .{});
1259
1260 assert(comp.c_source_files.len == 1);
1261
1262 var argv = std.ArrayList([]const u8).init(arena);
1263
1264 const c_source_file = comp.c_source_files[0];
1265 const file_ext = Compilation.classifyFileExt(c_source_file.src_path);
1266 try comp.addCCArgs(arena, &argv, file_ext, true, null);
1267 try argv.append(c_source_file.src_path);
1268
1269 if (comp.verbose_cc) {
1270 std.debug.print("clang ", .{});
1271 Compilation.dump_argv(argv.items);
1272 }
1273
1274 // Convert to null terminated args.
1275 const new_argv_with_sentinel = try arena.alloc(?[*:0]const u8, argv.items.len + 1);
1276 new_argv_with_sentinel[argv.items.len] = null;
1277 const new_argv = new_argv_with_sentinel[0..argv.items.len :null];
1278 for (argv.items) |arg, i| {
1279 new_argv[i] = try arena.dupeZ(u8, arg);
1280 }
1281
1282 const c_headers_dir_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{"include"});
1283 const c_headers_dir_path_z = try arena.dupeZ(u8, c_headers_dir_path);
1284 var clang_errors: []translate_c.ClangErrMsg = &[0]translate_c.ClangErrMsg{};
1285 const tree = translate_c.translate(
1286 comp.gpa,
1287 new_argv.ptr,
1288 new_argv.ptr + new_argv.len,
1289 &clang_errors,
1290 c_headers_dir_path_z,
1291 ) catch |err| switch (err) {
1292 error.OutOfMemory => return error.OutOfMemory,
1293 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", .{}),
1294 error.SemanticAnalyzeFail => {
1295 for (clang_errors) |clang_err| {
1296 std.debug.print("{}:{}:{}: {}\n", .{
1297 if (clang_err.filename_ptr) |p| p[0..clang_err.filename_len] else "(no file)",
1298 clang_err.line + 1,
1299 clang_err.column + 1,
1300 clang_err.msg_ptr[0..clang_err.msg_len],
1301 });
1302 }
1303 process.exit(1);
1304 },
1305 };
1306 defer tree.deinit();
1307
1308 var bos = io.bufferedOutStream(io.getStdOut().writer());
1309 _ = try std.zig.render(comp.gpa, bos.writer(), tree);
1310 try bos.flush();
1311}
1312
12511313pub const usage_libc =
12521314 \\Usage: zig libc
12531315 \\
......@@ -1401,8 +1463,9 @@ pub fn cmdFmt(gpa: *Allocator, args: []const []const u8) !void {
14011463 process.exit(code);
14021464 }
14031465
1404 const stdout = io.getStdOut().outStream();
1405 _ = try std.zig.render(gpa, stdout, tree);
1466 var bos = io.bufferedOutStream(io.getStdOut().writer());
1467 _ = try std.zig.render(gpa, bos.writer(), tree);
1468 try bos.flush();
14061469 return;
14071470 }
14081471
......@@ -1644,7 +1707,7 @@ extern "c" fn ZigClang_main(argc: c_int, argv: [*:null]?[*:0]u8) c_int;
16441707/// TODO https://github.com/ziglang/zig/issues/3257
16451708fn punt_to_clang(arena: *Allocator, args: []const []const u8) error{OutOfMemory} {
16461709 if (!build_options.have_llvm)
1647 fatal("`zig cc` and `zig c++` unavailable: compiler not built with LLVM extensions enabled", .{});
1710 fatal("`zig cc` and `zig c++` unavailable: compiler built without LLVM extensions", .{});
16481711 // Convert the args to the format Clang expects.
16491712 const argv = try arena.alloc(?[*:0]u8, args.len + 1);
16501713 for (args) |arg, i| {
src-self-hosted/translate_c.zig+2-2
......@@ -1,5 +1,5 @@
1// This is the userland implementation of translate-c which is used by both stage1
2// and stage2.
1//! This is the userland implementation of translate-c which is used by both stage1
2//! and stage2.
33
44const std = @import("std");
55const assert = std.debug.assert;