From 6b3f59c3a735ddbda3b3a62a0dfb5d55fa045f57 Mon Sep 17 00:00:00 2001 From: Motiejus Jakštys Date: Mon, 14 Nov 2022 04:15:04 +0200 Subject: zig run/cc: recognize "-x language" This commit adds support for "-x language" for a couple of hand-picked supported languages. There is no reason the list of supported languages to not grow (e.g. add "c-header"), but I'd like to keep it small at the start. Alternative 1 ------------- I first tried to add a new type "Language", and then add that to the `CSourceFile`. But oh boy what a change it turns out to be. So I am keeping myself tied to FileExt and see what you folks think. Alternative 2 ------------- I tried adding `Language: ?[]const u8` to `CSourceFile`. However, the language/ext, whatever we want to call it, still needs to be interpreted in the main loop: one kind of handling for source files, other kind of handling for everything else. Test case --------- *standalone.c* #include int main() { std::cout << "elho\n"; } Compile and run: $ ./zig run -x c++ -lc++ standalone.c elho $ ./zig c++ -x c++ standalone.c -o standalone && ./standalone elho Fixes #10915 --- src/Compilation.zig | 56 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 14 deletions(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index cd0761315a..b0af925e29 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -192,12 +192,30 @@ pub const CRTFile = struct { } }; +// supported languages for "zig clang -x ". +// Loosely based on llvm-project/clang/include/clang/Driver/Types.def +pub const LangToExt = std.ComptimeStringMap(FileExt, .{ + .{ "c", .c }, + .{ "c-header", .h }, + .{ "c++", .cpp }, + .{ "c++-header", .h }, + .{ "objective-c", .m }, + .{ "objective-c-header", .h }, + .{ "objective-c++", .mm }, + .{ "objective-c++-header", .h }, + .{ "assembler", .assembly }, + .{ "assembler-with-cpp", .assembly_with_cpp }, + .{ "cuda", .cu }, +}); + /// For passing to a C compiler. pub const CSourceFile = struct { src_path: []const u8, extra_flags: []const []const u8 = &.{}, /// Same as extra_flags except they are not added to the Cache hash. cache_exempt_flags: []const []const u8 = &.{}, + // this field is non-null iff language was explicitly set with "-x lang". + ext: ?FileExt = null, }; const Job = union(enum) { @@ -2612,6 +2630,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes for (comp.c_object_table.keys()) |key| { _ = try man.addFile(key.src.src_path, null); + man.hash.addOptional(key.src.ext); man.hash.addListOfBytes(key.src.extra_flags); } @@ -3926,14 +3945,23 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P break :e o_ext; }; const o_basename = try std.fmt.allocPrint(arena, "{s}{s}", .{ o_basename_noext, out_ext }); - - try argv.appendSlice(&[_][]const u8{ - self_exe_path, - "clang", - c_object.src.src_path, - }); - - const ext = classifyFileExt(c_object.src.src_path); + const ext = c_object.src.ext orelse classifyFileExt(c_object.src.src_path); + + try argv.appendSlice(&[_][]const u8{ self_exe_path, "clang" }); + // if "ext" is explicit, add "-x ". Otherwise let clang do its thing. + if (c_object.src.ext != null) { + try argv.appendSlice(&[_][]const u8{ "-x", switch (ext) { + .assembly => "assembler", + .assembly_with_cpp => "assembler-with-cpp", + .c => "c", + .cpp => "c++", + .cu => "cuda", + .m => "objective-c", + .mm => "objective-c++", + else => fatal("language '{s}' is unsupported in this context", .{@tagName(ext)}), + } }); + } + try argv.append(c_object.src.src_path); // When all these flags are true, it means that the entire purpose of // this compilation is to perform a single zig cc operation. This means @@ -4395,7 +4423,7 @@ pub fn addCCArgs( } }, .shared_library, .ll, .bc, .unknown, .static_library, .object, .def, .zig => {}, - .assembly => { + .assembly, .assembly_with_cpp => { // The Clang assembler does not accept the list of CPU features like the // compiler frontend does. Therefore we must hard-code the -m flags for // all CPU features here. @@ -4535,6 +4563,7 @@ pub const FileExt = enum { ll, bc, assembly, + assembly_with_cpp, shared_library, object, static_library, @@ -4549,6 +4578,7 @@ pub const FileExt = enum { .ll, .bc, .assembly, + .assembly_with_cpp, .shared_library, .object, .static_library, @@ -4588,10 +4618,6 @@ pub fn hasObjCppExt(filename: []const u8) bool { return mem.endsWith(u8, filename, ".mm"); } -pub fn hasAsmExt(filename: []const u8) bool { - return mem.endsWith(u8, filename, ".s") or mem.endsWith(u8, filename, ".S"); -} - pub fn hasSharedLibraryExt(filename: []const u8) bool { if (mem.endsWith(u8, filename, ".so") or mem.endsWith(u8, filename, ".dll") or @@ -4632,8 +4658,10 @@ pub fn classifyFileExt(filename: []const u8) FileExt { return .ll; } else if (mem.endsWith(u8, filename, ".bc")) { return .bc; - } else if (hasAsmExt(filename)) { + } else if (mem.endsWith(u8, filename, ".s")) { return .assembly; + } else if (mem.endsWith(u8, filename, ".S")) { + return .assembly_with_cpp; } else if (mem.endsWith(u8, filename, ".h")) { return .h; } else if (mem.endsWith(u8, filename, ".zig")) { -- cgit v1.2.3