aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-03-04 22:15:53 -0500
committerAndrew Kelley <andrew@ziglang.org>2019-03-04 22:15:53 -0500
commitaeb16010f37df3c702481c9bd98b8cc838418ee1 (patch)
tree92194b8c0d4576efede7f29b2fee8b1bed1b2654 /src/codegen.cpp
parent9c5852aa8674320d2912627708f32fea37d7cd08 (diff)
downloadzig-aeb16010f37df3c702481c9bd98b8cc838418ee1.tar.gz
zig-aeb16010f37df3c702481c9bd98b8cc838418ee1.zip
initial glibc support
Diffstat (limited to 'src/codegen.cpp')
-rw-r--r--src/codegen.cpp458
1 files changed, 298 insertions, 160 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 9a8864b87a..2054663fc6 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -89,7 +89,8 @@ static const char *symbols_that_llvm_depends_on[] = {
};
CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target,
- OutType out_type, BuildMode build_mode, Buf *zig_lib_dir, Buf *override_std_dir, ZigLibCInstallation *libc)
+ OutType out_type, BuildMode build_mode, Buf *zig_lib_dir, Buf *override_std_dir,
+ ZigLibCInstallation *libc, Buf *cache_dir)
{
CodeGen *g = allocate<CodeGen>(1);
@@ -98,6 +99,7 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
g->libc = libc;
g->zig_lib_dir = zig_lib_dir;
g->zig_target = target;
+ g->cache_dir = cache_dir;
if (override_std_dir == nullptr) {
g->zig_std_dir = buf_alloc();
@@ -7912,12 +7914,27 @@ static void detect_libc(CodeGen *g) {
if (g->libc != nullptr || g->libc_link_lib == nullptr)
return;
+ if (g->zig_target->os == OsLinux && target_abi_is_gnu(g->zig_target->abi)) {
+ // we have glibc headers and can build glibc start files from source
+ if (g->is_static && g->out_type == OutTypeExe) {
+ fprintf(stderr, "glibc does not support static linking\n");
+ exit(1);
+ }
+
+ Buf *libc_dir = buf_alloc();
+ os_path_join(g->zig_lib_dir, buf_create_from_str("libc"), libc_dir);
+
+ g->libc_include_dir = buf_alloc();
+ os_path_join(libc_dir, buf_create_from_str("glibc-include"), g->libc_include_dir);
+ return;
+ }
+
if (g->zig_target->is_native) {
g->libc = allocate<ZigLibCInstallation>(1);
// Look for zig-cache/native_libc.txt
Buf *native_libc_txt = buf_alloc();
- os_path_join(&g->cache_dir, buf_create_from_str("native_libc.txt"), native_libc_txt);
+ os_path_join(g->cache_dir, buf_create_from_str("native_libc.txt"), native_libc_txt);
if ((err = zig_libc_parse(g->libc, native_libc_txt, g->zig_target, false))) {
if ((err = zig_libc_find_native(g->libc, true))) {
fprintf(stderr,
@@ -7925,9 +7942,9 @@ static void detect_libc(CodeGen *g) {
"See `zig libc --help` for more details.\n", err_str(err));
exit(1);
}
- if ((err = os_make_path(&g->cache_dir))) {
+ if ((err = os_make_path(g->cache_dir))) {
fprintf(stderr, "Unable to create %s directory: %s\n",
- buf_ptr(&g->cache_dir), err_str(err));
+ buf_ptr(g->cache_dir), err_str(err));
exit(1);
}
Buf *native_libc_tmp = buf_sprintf("%s.tmp", buf_ptr(native_libc_txt));
@@ -7946,6 +7963,7 @@ static void detect_libc(CodeGen *g) {
exit(1);
}
}
+ g->libc_include_dir = &g->libc->include_dir;
} else if ((g->out_type == OutTypeExe || (g->out_type == OutTypeLib && !g->is_static)) &&
!target_is_darwin(g->zig_target))
{
@@ -8190,140 +8208,253 @@ static void print_zig_cc_cmd(const char *zig_exe, ZigList<const char *> *args) {
fprintf(stderr, "\n");
}
+// Caller should delete the file when done or rename it into a better location.
+static Error get_tmp_filename(CodeGen *g, Buf *out, Buf *suffix) {
+ Error err;
+ buf_resize(out, 0);
+ os_path_join(g->cache_dir, buf_create_from_str("tmp" OS_SEP), out);
+ if ((err = os_make_path(out))) {
+ return err;
+ }
+ const char base64[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
+ assert(array_length(base64) == 64 + 1);
+ for (size_t i = 0; i < 12; i += 1) {
+ buf_append_char(out, base64[rand() % 64]);
+ }
+ buf_append_char(out, '-');
+ buf_append_buf(out, suffix);
+ return ErrorNone;
+}
+
static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
Error err;
+ Buf *artifact_dir;
+ Buf *o_final_path;
+
+ Buf *o_dir = buf_alloc();
+ os_path_join(g->cache_dir, buf_create_from_str("o"), o_dir);
+
Buf *c_source_file = buf_create_from_str(c_file->source_path);
Buf *c_source_basename = buf_alloc();
os_path_split(c_source_file, nullptr, c_source_basename);
- Buf *out_obj_name = buf_sprintf("%s%s", buf_ptr(c_source_basename), target_o_file_ext(g->zig_target));
- Buf *out_obj_path = buf_alloc();
- os_path_join(&g->cache_dir, out_obj_name, out_obj_path);
- Buf *out_dep_name = buf_sprintf("%s.d", buf_ptr(c_source_file));
- Buf *out_dep_path = buf_alloc();
- os_path_join(&g->cache_dir, out_dep_name, out_dep_path);
+ Buf *final_o_basename = buf_alloc();
+ os_path_extname(c_source_basename, final_o_basename, nullptr);
+ buf_append_str(final_o_basename, target_o_file_ext(g->zig_target));
- Termination term;
- ZigList<const char *> args = {};
- args.append("cc");
+ CacheHash *cache_hash = allocate<CacheHash>(1);
+ Buf *manifest_dir = buf_alloc();
+ os_path_join(g->cache_dir, buf_create_from_str("c"), manifest_dir);
+ cache_init(cache_hash, manifest_dir);
- if (g->enable_cache) {
+ Buf *compiler_id;
+ if ((err = get_compiler_id(&compiler_id))) {
+ fprintf(stderr, "unable to get compiler id: %s\n", err_str(err));
+ exit(1);
+ }
+ cache_buf(cache_hash, compiler_id);
+ cache_int(cache_hash, g->err_color);
+ cache_buf(cache_hash, g->zig_c_headers_dir);
+ cache_buf_opt(cache_hash, g->libc_include_dir);
+ if (g->libc != nullptr) {
+ cache_buf(cache_hash, &g->libc->sys_include_dir);
+ }
+ cache_int(cache_hash, g->zig_target->is_native);
+ cache_int(cache_hash, g->zig_target->arch);
+ cache_int(cache_hash, g->zig_target->sub_arch);
+ cache_int(cache_hash, g->zig_target->vendor);
+ cache_int(cache_hash, g->zig_target->os);
+ cache_int(cache_hash, g->zig_target->abi);
+ cache_bool(cache_hash, g->strip_debug_symbols);
+ cache_int(cache_hash, g->build_mode);
+ cache_file(cache_hash, c_source_file);
+ cache_bool(cache_hash, g->disable_pic);
+ for (size_t arg_i = 0; arg_i < g->clang_argv_len; arg_i += 1) {
+ cache_str(cache_hash, g->clang_argv[arg_i]);
+ }
+ // Note: not directory args, just args that always have a file next
+ static const char *file_args[] = {
+ "-include",
+ };
+ for (size_t arg_i = 0; arg_i < c_file->args.length; arg_i += 1) {
+ const char *arg = c_file->args.at(arg_i);
+ cache_str(cache_hash, arg);
+ for (size_t file_arg_i = 0; file_arg_i < array_length(file_args); file_arg_i += 1) {
+ if (strcmp(arg, file_args[file_arg_i]) == 0 && arg_i + 1 < c_file->args.length) {
+ arg_i += 1;
+ cache_file(cache_hash, buf_create_from_str(c_file->args.at(arg_i)));
+ }
+ }
+ }
+
+ Buf digest = BUF_INIT;
+ buf_resize(&digest, 0);
+ if ((err = cache_hit(cache_hash, &digest))) {
+ if (err == ErrorCacheUnavailable) {
+ // already printed error
+ } else {
+ fprintf(stderr, "unable to check cache when compiling C object: %s\n", err_str(err));
+ }
+ exit(1);
+ }
+ if (buf_len(&digest) == 0) {
+ // cache miss
+ // we can't know the digest until we do the C compiler invocation, so we
+ // need a tmp filename.
+ Buf *out_obj_path = buf_alloc();
+ if ((err = get_tmp_filename(g, out_obj_path, final_o_basename))) {
+ fprintf(stderr, "unable to create tmp dir: %s\n", err_str(err));
+ exit(1);
+ }
+
+ Termination term;
+ ZigList<const char *> args = {};
+ args.append("cc");
+
+ Buf *out_dep_path = buf_sprintf("%s.d", buf_ptr(out_obj_path));
args.append("-MD");
args.append("-MF");
args.append(buf_ptr(out_dep_path));
- }
-
- args.append("-nostdinc");
- args.append("-fno-spell-checking");
- switch (g->err_color) {
- case ErrColorAuto:
- break;
- case ErrColorOff:
- args.append("-fno-color-diagnostics");
- args.append("-fno-caret-diagnostics");
- break;
- case ErrColorOn:
- args.append("-fcolor-diagnostics");
- args.append("-fcaret-diagnostics");
- break;
- }
+ args.append("-nostdinc");
+ args.append("-fno-spell-checking");
- args.append("-isystem");
- args.append(buf_ptr(g->zig_c_headers_dir));
+ switch (g->err_color) {
+ case ErrColorAuto:
+ break;
+ case ErrColorOff:
+ args.append("-fno-color-diagnostics");
+ args.append("-fno-caret-diagnostics");
+ break;
+ case ErrColorOn:
+ args.append("-fcolor-diagnostics");
+ args.append("-fcaret-diagnostics");
+ break;
+ }
- if (g->libc != nullptr) {
args.append("-isystem");
- args.append(buf_ptr(&g->libc->include_dir));
+ args.append(buf_ptr(g->zig_c_headers_dir));
- if (!buf_eql_buf(&g->libc->include_dir, &g->libc->sys_include_dir)) {
+ if (g->libc_include_dir != nullptr) {
args.append("-isystem");
- args.append(buf_ptr(&g->libc->sys_include_dir));
+ args.append(buf_ptr(g->libc_include_dir));
+ }
+ if (g->libc != nullptr) {
+ if (!buf_eql_buf(&g->libc->include_dir, &g->libc->sys_include_dir)) {
+ args.append("-isystem");
+ args.append(buf_ptr(&g->libc->sys_include_dir));
+ }
}
- }
- if (g->zig_target->is_native) {
- args.append("-march=native");
- } else {
- args.append("-target");
- args.append(buf_ptr(&g->triple_str));
- }
+ if (g->zig_target->is_native) {
+ args.append("-march=native");
+ } else {
+ args.append("-target");
+ args.append(buf_ptr(&g->triple_str));
+ }
- if (!g->strip_debug_symbols) {
- args.append("-g");
- }
- switch (g->build_mode) {
- case BuildModeDebug:
- if (g->libc_link_lib != nullptr) {
- args.append("-fstack-protector-strong");
- args.append("--param");
- args.append("ssp-buffer-size=4");
- } else {
+ if (!g->strip_debug_symbols) {
+ args.append("-g");
+ }
+
+ switch (g->build_mode) {
+ case BuildModeDebug:
+ if (g->libc_link_lib != nullptr) {
+ args.append("-fstack-protector-strong");
+ args.append("--param");
+ args.append("ssp-buffer-size=4");
+ } else {
+ args.append("-fno-stack-protector");
+ }
+ break;
+ case BuildModeSafeRelease:
+ args.append("-O2");
+ if (g->libc_link_lib != nullptr) {
+ args.append("-D_FORTIFY_SOURCE=2");
+ args.append("-fstack-protector-strong");
+ args.append("--param");
+ args.append("ssp-buffer-size=4");
+ } else {
+ args.append("-fno-stack-protector");
+ }
+ break;
+ case BuildModeFastRelease:
+ args.append("-O2");
args.append("-fno-stack-protector");
- }
- break;
- case BuildModeSafeRelease:
- args.append("-O2");
- if (g->libc_link_lib != nullptr) {
- args.append("-D_FORTIFY_SOURCE=2");
- args.append("-fstack-protector-strong");
- args.append("--param");
- args.append("ssp-buffer-size=4");
- } else {
+ break;
+ case BuildModeSmallRelease:
+ args.append("-Os");
args.append("-fno-stack-protector");
- }
- break;
- case BuildModeFastRelease:
- args.append("-O2");
- args.append("-fno-stack-protector");
- break;
- case BuildModeSmallRelease:
- args.append("-Os");
- args.append("-fno-stack-protector");
- break;
- }
+ break;
+ }
- args.append("-o");
- args.append(buf_ptr(out_obj_path));
+ args.append("-o");
+ args.append(buf_ptr(out_obj_path));
- args.append("-c");
- args.append(buf_ptr(c_source_file));
+ args.append("-c");
+ args.append(buf_ptr(c_source_file));
- if (!g->disable_pic && target_supports_fpic(g->zig_target)) {
- args.append("-fPIC");
- }
+ if (target_supports_fpic(g->zig_target) && !g->disable_pic) {
+ args.append("-fPIC");
+ }
- for (size_t arg_i = 0; arg_i < g->clang_argv_len; arg_i += 1) {
- args.append(g->clang_argv[arg_i]);
- }
+ for (size_t arg_i = 0; arg_i < g->clang_argv_len; arg_i += 1) {
+ args.append(g->clang_argv[arg_i]);
+ }
- for (size_t arg_i = 0; arg_i < c_file->args.length; arg_i += 1) {
- args.append(c_file->args.at(arg_i));
- }
+ for (size_t arg_i = 0; arg_i < c_file->args.length; arg_i += 1) {
+ args.append(c_file->args.at(arg_i));
+ }
- if (g->verbose_cc) {
- print_zig_cc_cmd("zig", &args);
- }
- os_spawn_process(buf_ptr(self_exe_path), args, &term);
- if (term.how != TerminationIdClean || term.code != 0) {
- fprintf(stderr, "\nThe following command failed:\n");
- print_zig_cc_cmd(buf_ptr(self_exe_path), &args);
- exit(1);
- }
- g->link_objects.append(out_obj_path);
+ if (g->verbose_cc) {
+ print_zig_cc_cmd("zig", &args);
+ }
+ os_spawn_process(buf_ptr(self_exe_path), args, &term);
+ if (term.how != TerminationIdClean || term.code != 0) {
+ fprintf(stderr, "\nThe following command failed:\n");
+ print_zig_cc_cmd(buf_ptr(self_exe_path), &args);
+ exit(1);
+ }
- if (g->enable_cache) {
// add the files depended on to the cache system
- if ((err = cache_add_file(&g->cache_hash, c_source_file))) {
- fprintf(stderr, "unable to add %s to cache: %s\n", buf_ptr(c_source_file), err_str(err));
+ if ((err = cache_add_dep_file(cache_hash, out_dep_path, true))) {
+ fprintf(stderr, "Failed to add C source dependencies to cache: %s\n", err_str(err));
+ exit(1);
+ }
+ os_delete_file(out_dep_path);
+
+ if ((err = cache_final(cache_hash, &digest))) {
+ fprintf(stderr, "Unable to finalize cache hash: %s\n", err_str(err));
+ exit(1);
+ }
+ artifact_dir = buf_alloc();
+ os_path_join(o_dir, &digest, artifact_dir);
+ if ((err = os_make_path(artifact_dir))) {
+ fprintf(stderr, "Unable to create output directory '%s': %s",
+ buf_ptr(artifact_dir), err_str(err));
exit(1);
}
- if ((err = cache_add_dep_file(&g->cache_hash, out_dep_path, true))) {
- fprintf(stderr, "failed to add C source dependencies to cache: %s\n", err_str(err));
+ o_final_path = buf_alloc();
+ os_path_join(artifact_dir, final_o_basename, o_final_path);
+ if ((err = os_rename(out_obj_path, o_final_path))) {
+ fprintf(stderr, "Unable to rename object: %s\n", err_str(err));
exit(1);
}
+ } else {
+ // cache hit
+ artifact_dir = buf_alloc();
+ os_path_join(o_dir, &digest, artifact_dir);
+ o_final_path = buf_alloc();
+ os_path_join(artifact_dir, final_o_basename, o_final_path);
+ }
+
+ if (g->enable_cache) {
+ cache_buf(&g->cache_hash, &digest);
}
+
+ g->link_objects.append(o_final_path);
+ g->caches_to_release.append(cache_hash);
}
static void gen_c_objects(CodeGen *g) {
@@ -8338,6 +8469,8 @@ static void gen_c_objects(CodeGen *g) {
exit(1);
}
+ codegen_add_time_event(g, "Compile C Code");
+
for (size_t c_file_i = 0; c_file_i < g->c_source_files.length; c_file_i += 1) {
CFile *c_file = g->c_source_files.at(c_file_i);
gen_c_object(g, self_exe_path, c_file);
@@ -8862,13 +8995,6 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_list_of_buf(ch, g->forbidden_libs.items, g->forbidden_libs.length);
cache_list_of_file(ch, g->link_objects.items, g->link_objects.length);
cache_list_of_file(ch, g->assembly_files.items, g->assembly_files.length);
- for (size_t c_file_i = 0; c_file_i < g->c_source_files.length; c_file_i += 1) {
- CFile *c_file = g->c_source_files.at(c_file_i);
- cache_file(ch, buf_create_from_str(c_file->source_path));
- for (size_t opt_i = 0; opt_i < c_file->args.length; opt_i += 1) {
- cache_buf(ch, buf_create_from_str(c_file->args.at(opt_i)));
- }
- }
cache_int(ch, g->emit_file_type);
cache_int(ch, g->build_mode);
cache_int(ch, g->out_type);
@@ -8908,13 +9034,27 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_buf(ch, &g->libc->dynamic_linker_path);
}
+ gen_c_objects(g);
+
buf_resize(digest, 0);
if ((err = cache_hit(ch, digest)))
return err;
+ if (ch->manifest_file_path != nullptr) {
+ g->caches_to_release.append(ch);
+ }
+
return ErrorNone;
}
+static bool need_llvm_module(CodeGen *g) {
+ return g->assembly_files.length != 0 || buf_len(&g->root_package->root_src_path) != 0;
+}
+
+static bool compilation_is_already_done(CodeGen *g) {
+ return !need_llvm_module(g) && g->link_objects.length == 1 && g->out_type == OutTypeObj;
+}
+
static void resolve_out_paths(CodeGen *g) {
Buf *o_basename = buf_create_from_buf(g->root_out_name);
@@ -8941,7 +9081,9 @@ static void resolve_out_paths(CodeGen *g) {
zig_unreachable();
}
- if (g->enable_cache || g->out_type != OutTypeObj) {
+ if (compilation_is_already_done(g)) {
+ buf_init_from_str(&g->o_file_output_path, buf_ptr(g->link_objects.at(0)));
+ } else if (g->enable_cache || g->out_type != OutTypeObj) {
os_path_join(&g->artifact_dir, o_basename, &g->o_file_output_path);
} else if (g->wanted_output_file_path != nullptr && g->out_type == OutTypeObj) {
buf_init_from_buf(&g->o_file_output_path, g->wanted_output_file_path);
@@ -8949,39 +9091,41 @@ static void resolve_out_paths(CodeGen *g) {
buf_init_from_buf(&g->o_file_output_path, o_basename);
}
- if (g->out_type == OutTypeObj) {
+ if (!g->enable_cache && g->wanted_output_file_path != nullptr) {
+ buf_init_from_buf(&g->output_file_path, g->wanted_output_file_path);
+ return;
+ }
+
+ if (compilation_is_already_done(g)) {
buf_init_from_buf(&g->output_file_path, &g->o_file_output_path);
- } else if (g->out_type == OutTypeExe) {
- if (!g->enable_cache && g->wanted_output_file_path != nullptr) {
- buf_init_from_buf(&g->output_file_path, g->wanted_output_file_path);
- } else {
- assert(g->root_out_name);
+ return;
+ }
- Buf basename = BUF_INIT;
- buf_init_from_buf(&basename, g->root_out_name);
- buf_append_str(&basename, target_exe_file_ext(g->zig_target));
- if (g->enable_cache || g->is_test_build) {
- os_path_join(&g->artifact_dir, &basename, &g->output_file_path);
- } else {
- buf_init_from_buf(&g->output_file_path, &basename);
- }
- }
- } else if (g->out_type == OutTypeLib) {
- if (!g->enable_cache && g->wanted_output_file_path != nullptr) {
- buf_init_from_buf(&g->output_file_path, g->wanted_output_file_path);
- } else {
- Buf basename = BUF_INIT;
- buf_init_from_buf(&basename, g->root_out_name);
- buf_append_str(&basename, target_lib_file_ext(g->zig_target, g->is_static,
- g->version_major, g->version_minor, g->version_patch));
- if (g->enable_cache) {
- os_path_join(&g->artifact_dir, &basename, &g->output_file_path);
- } else {
- buf_init_from_buf(&g->output_file_path, &basename);
- }
- }
+ const char *extname;
+ switch (g->out_type) {
+ case OutTypeUnknown:
+ zig_unreachable();
+ case OutTypeObj:
+ extname = target_o_file_ext(g->zig_target);
+ break;
+ case OutTypeExe:
+ extname = target_exe_file_ext(g->zig_target);
+ break;
+ case OutTypeLib:
+ extname = target_lib_file_ext(g->zig_target, g->is_static,
+ g->version_major, g->version_minor, g->version_patch);
+ break;
+ }
+
+ assert(g->root_out_name);
+
+ Buf basename = BUF_INIT;
+ buf_init_from_buf(&basename, g->root_out_name);
+ buf_append_str(&basename, extname);
+ if (g->enable_cache || g->is_test_build) {
+ os_path_join(&g->artifact_dir, &basename, &g->output_file_path);
} else {
- zig_unreachable();
+ buf_init_from_buf(&g->output_file_path, &basename);
}
}
@@ -8991,14 +9135,11 @@ void codegen_build_and_link(CodeGen *g) {
detect_libc(g);
- Buf *stage1_dir = get_stage1_cache_path();
Buf *artifact_dir = buf_alloc();
Buf digest = BUF_INIT;
if (g->enable_cache) {
- codegen_add_time_event(g, "Check Cache");
-
Buf *manifest_dir = buf_alloc();
- os_path_join(stage1_dir, buf_create_from_str("build"), manifest_dir);
+ os_path_join(g->cache_dir, buf_create_from_str("build"), manifest_dir);
if ((err = check_cache(g, manifest_dir, &digest))) {
if (err == ErrorCacheUnavailable) {
@@ -9009,7 +9150,10 @@ void codegen_build_and_link(CodeGen *g) {
exit(1);
}
- os_path_join(stage1_dir, buf_create_from_str("artifact"), artifact_dir);
+ os_path_join(g->cache_dir, buf_create_from_str("artifact"), artifact_dir);
+ } else {
+ // There is a call to this in check_cache
+ gen_c_objects(g);
}
if (g->enable_cache && buf_len(&digest) != 0) {
@@ -9022,7 +9166,6 @@ void codegen_build_and_link(CodeGen *g) {
gen_global_asm(g);
gen_root_source(g);
- gen_c_objects(g);
if (g->enable_cache) {
if ((err = cache_final(&g->cache_hash, &digest))) {
@@ -9031,7 +9174,7 @@ void codegen_build_and_link(CodeGen *g) {
}
os_path_join(artifact_dir, &digest, &g->artifact_dir);
} else {
- buf_init_from_buf(&g->artifact_dir, &g->cache_dir);
+ buf_init_from_buf(&g->artifact_dir, g->cache_dir);
}
if ((err = os_make_path(&g->artifact_dir))) {
fprintf(stderr, "Unable to create artifact directory: %s\n", err_str(err));
@@ -9040,14 +9183,8 @@ void codegen_build_and_link(CodeGen *g) {
resolve_out_paths(g);
codegen_add_time_event(g, "Code Generation");
- if (g->out_type == OutTypeObj && g->c_source_files.length == 1) {
- assert(g->link_objects.length == 1);
- if ((err = os_rename(g->link_objects.pop(), &g->o_file_output_path))) {
- fprintf(stderr, "unable to move object to '%s': %s\n",
- buf_ptr(&g->o_file_output_path), err_str(err));
- exit(1);
- }
- } else {
+
+ if (need_llvm_module(g)) {
do_code_gen(g);
codegen_add_time_event(g, "LLVM Emit Output");
zig_llvm_emit_output(g);
@@ -9056,14 +9193,15 @@ void codegen_build_and_link(CodeGen *g) {
codegen_add_time_event(g, "Generate .h");
gen_h_file(g);
}
- if (g->out_type != OutTypeObj && g->emit_file_type == EmitFileTypeBinary) {
- codegen_link(g);
- }
+ }
+
+ if (g->emit_file_type == EmitFileTypeBinary && !compilation_is_already_done(g)) {
+ codegen_link(g);
}
}
- if (g->enable_cache) {
- cache_release(&g->cache_hash);
+ while (g->caches_to_release.length != 0) {
+ cache_release(g->caches_to_release.pop());
}
codegen_add_time_event(g, "Done");
}