zig cc: better support for the preprocessor option (-E)

This commit is contained in:
Andrew Kelley 2020-03-21 20:32:48 -04:00
parent 28ad78cb7f
commit 4b0ddb817b
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
9 changed files with 115 additions and 14 deletions

View File

@ -7,7 +7,7 @@ flagpd1("CC"),
.{
.name = "E",
.syntax = .flag,
.zig_equivalent = .driver_punt,
.zig_equivalent = .preprocess,
.pd1 = true,
.pd2 = false,
.psl = false,
@ -133,7 +133,7 @@ flagpd1("###"),
.{
.name = "E",
.syntax = .flag,
.zig_equivalent = .driver_punt,
.zig_equivalent = .preprocess,
.pd1 = true,
.pd2 = false,
.psl = true,
@ -1421,7 +1421,7 @@ flagpd1("###"),
.{
.name = "assemble",
.syntax = .flag,
.zig_equivalent = .other,
.zig_equivalent = .driver_punt,
.pd1 = false,
.pd2 = true,
.psl = false,
@ -1749,7 +1749,7 @@ flagpd1("###"),
.{
.name = "preprocess",
.syntax = .flag,
.zig_equivalent = .other,
.zig_equivalent = .preprocess,
.pd1 = false,
.pd2 = true,
.psl = false,

View File

@ -1247,6 +1247,7 @@ pub const ClangArgIterator = extern struct {
shared,
rdynamic,
wl,
preprocess,
};
fn init(argv: []const [*:0]const u8) ClangArgIterator {

View File

@ -2003,6 +2003,7 @@ enum WantCSanitize {
struct CFile {
ZigList<const char *> args;
const char *source_path;
const char *preprocessor_only_basename;
};
// When adding fields, check if they should be added to the hash computation in build_with_cache
@ -2147,6 +2148,7 @@ struct CodeGen {
// As an input parameter, mutually exclusive with enable_cache. But it gets
// populated in codegen_build_and_link.
Buf *output_dir;
Buf *c_artifact_dir;
const char **libc_include_dir_list;
size_t libc_include_dir_len;

View File

@ -9723,13 +9723,17 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
buf_len(c_source_basename), 0);
Buf *final_o_basename = buf_alloc();
// We special case when doing build-obj for just one C file
if (main_output_dir_is_just_one_c_object_pre(g)) {
buf_init_from_buf(final_o_basename, g->root_out_name);
if (c_file->preprocessor_only_basename == nullptr) {
// We special case when doing build-obj for just one C file
if (main_output_dir_is_just_one_c_object_pre(g)) {
buf_init_from_buf(final_o_basename, g->root_out_name);
} else {
os_path_extname(c_source_basename, final_o_basename, nullptr);
}
buf_append_str(final_o_basename, target_o_file_ext(g->zig_target));
} else {
os_path_extname(c_source_basename, final_o_basename, nullptr);
buf_init_from_str(final_o_basename, c_file->preprocessor_only_basename);
}
buf_append_str(final_o_basename, target_o_file_ext(g->zig_target));
CacheHash *cache_hash;
if ((err = create_c_object_cache(g, &cache_hash, true))) {
@ -9780,13 +9784,18 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
args.append(buf_ptr(self_exe_path));
args.append("clang");
if (c_file->preprocessor_only_basename != nullptr) {
args.append("-E");
} else {
args.append("-c");
}
Buf *out_dep_path = buf_sprintf("%s.d", buf_ptr(out_obj_path));
add_cc_args(g, args, buf_ptr(out_dep_path), false);
args.append("-o");
args.append(buf_ptr(out_obj_path));
args.append("-c");
args.append(buf_ptr(c_source_file));
for (size_t arg_i = 0; arg_i < c_file->args.length; arg_i += 1) {
@ -9841,6 +9850,7 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
os_path_join(artifact_dir, final_o_basename, o_final_path);
}
g->c_artifact_dir = artifact_dir;
g->link_objects.append(o_final_path);
g->caches_to_release.append(cache_hash);

View File

@ -453,6 +453,7 @@ static int main0(int argc, char **argv) {
const char *mcpu = nullptr;
CodeModel code_model = CodeModelDefault;
const char *override_soname = nullptr;
bool only_preprocess = false;
ZigList<const char *> llvm_argv = {0};
llvm_argv.append("zig (LLVM option parsing)");
@ -660,6 +661,9 @@ static int main0(int argc, char **argv) {
}
break;
}
case Stage2ClangArgPreprocess:
only_preprocess = true;
break;
}
}
// Parse linker args
@ -715,7 +719,28 @@ static int main0(int argc, char **argv) {
have_libc = true;
link_libs.append("c");
}
if (!c_arg) {
if (only_preprocess) {
cmd = CmdBuild;
out_type = OutTypeObj;
emit_bin = false;
// Transfer "objects" into c_source_files
for (size_t i = 0; i < objects.length; i += 1) {
CFile *c_file = heap::c_allocator.create<CFile>();
c_file->source_path = objects.at(i);
c_source_files.append(c_file);
}
for (size_t i = 0; i < c_source_files.length; i += 1) {
Buf *src_path;
if (emit_bin_override_path != nullptr) {
src_path = buf_create_from_str(emit_bin_override_path);
} else {
src_path = buf_create_from_str(c_source_files.at(i)->source_path);
}
Buf basename = BUF_INIT;
os_path_split(src_path, nullptr, &basename);
c_source_files.at(i)->preprocessor_only_basename = buf_ptr(&basename);
}
} else if (!c_arg) {
cmd = CmdBuild;
if (is_shared_lib) {
out_type = OutTypeLib;
@ -1464,12 +1489,41 @@ static int main0(int argc, char **argv) {
return term.code;
} else if (cmd == CmdBuild) {
if (emit_bin_override_path != nullptr) {
#if defined(ZIG_OS_WINDOWS)
buf_replace(g->output_dir, '/', '\\');
#endif
Buf *dest_path = buf_create_from_str(emit_bin_override_path);
if ((err = os_update_file(&g->bin_file_output_path, dest_path))) {
fprintf(stderr, "unable to copy %s to %s: %s\n", buf_ptr(&g->bin_file_output_path),
Buf *source_path;
if (only_preprocess) {
source_path = buf_alloc();
Buf *pp_only_basename = buf_create_from_str(
c_source_files.at(0)->preprocessor_only_basename);
os_path_join(g->output_dir, pp_only_basename, source_path);
} else {
source_path = &g->bin_file_output_path;
}
if ((err = os_update_file(source_path, dest_path))) {
fprintf(stderr, "unable to copy %s to %s: %s\n", buf_ptr(source_path),
buf_ptr(dest_path), err_str(err));
return main_exit(root_progress_node, EXIT_FAILURE);
}
} else if (only_preprocess) {
#if defined(ZIG_OS_WINDOWS)
buf_replace(g->c_artifact_dir, '/', '\\');
#endif
// dump the preprocessed output to stdout
for (size_t i = 0; i < c_source_files.length; i += 1) {
Buf *source_path = buf_alloc();
Buf *pp_only_basename = buf_create_from_str(
c_source_files.at(i)->preprocessor_only_basename);
os_path_join(g->c_artifact_dir, pp_only_basename, source_path);
if ((err = os_dump_file(source_path, stdout))) {
fprintf(stderr, "unable to read %s: %s\n", buf_ptr(source_path),
err_str(err));
return main_exit(root_progress_node, EXIT_FAILURE);
}
}
} else if (g->enable_cache) {
#if defined(ZIG_OS_WINDOWS)
buf_replace(&g->bin_file_output_path, '/', '\\');

View File

@ -1051,6 +1051,30 @@ static Error copy_open_files(FILE *src_f, FILE *dest_f) {
}
}
Error os_dump_file(Buf *src_path, FILE *dest_file) {
Error err;
FILE *src_f = fopen(buf_ptr(src_path), "rb");
if (!src_f) {
int err = errno;
if (err == ENOENT) {
return ErrorFileNotFound;
} else if (err == EACCES || err == EPERM) {
return ErrorAccess;
} else {
return ErrorFileSystem;
}
}
copy_open_files(src_f, dest_file);
if ((err = copy_open_files(src_f, dest_file))) {
fclose(src_f);
return err;
}
fclose(src_f);
return ErrorNone;
}
#if defined(ZIG_OS_WINDOWS)
static void windows_filetime_to_os_timestamp(FILETIME *ft, OsTimeStamp *mtime) {
mtime->sec = (((ULONGLONG) ft->dwHighDateTime) << 32) + ft->dwLowDateTime;

View File

@ -129,6 +129,7 @@ void os_file_close(OsFile *file);
Error ATTRIBUTE_MUST_USE os_write_file(Buf *full_path, Buf *contents);
Error ATTRIBUTE_MUST_USE os_copy_file(Buf *src_path, Buf *dest_path);
Error ATTRIBUTE_MUST_USE os_update_file(Buf *src_path, Buf *dest_path);
Error ATTRIBUTE_MUST_USE os_dump_file(Buf *src_path, FILE *dest_file);
Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents);
Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents);

View File

@ -333,6 +333,7 @@ enum Stage2ClangArg {
Stage2ClangArgShared,
Stage2ClangArgRDynamic,
Stage2ClangArgWL,
Stage2ClangArgPreprocess,
};
// ABI warning

View File

@ -76,12 +76,20 @@ const known_options = [_]KnownOpt{
},
.{
.name = "E",
.ident = "driver_punt",
.ident = "preprocess",
},
.{
.name = "preprocess",
.ident = "preprocess",
},
.{
.name = "S",
.ident = "driver_punt",
},
.{
.name = "assemble",
.ident = "driver_punt",
},
};
const blacklisted_options = [_][]const u8{};