Commit 4b0ddb817b
Changed files (9)
src/all_types.hpp
@@ -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;
src/codegen.cpp
@@ -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);
src/main.cpp
@@ -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, '/', '\\');
src/os.cpp
@@ -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;
src/os.hpp
@@ -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);
src/stage2.h
@@ -333,6 +333,7 @@ enum Stage2ClangArg {
Stage2ClangArgShared,
Stage2ClangArgRDynamic,
Stage2ClangArgWL,
+ Stage2ClangArgPreprocess,
};
// ABI warning
src-self-hosted/clang_options_data.zig
@@ -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,
src-self-hosted/stage2.zig
@@ -1247,6 +1247,7 @@ pub const ClangArgIterator = extern struct {
shared,
rdynamic,
wl,
+ preprocess,
};
fn init(argv: []const [*:0]const u8) ClangArgIterator {
tools/update_clang_options.zig
@@ -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{};