mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 22:35:24 +00:00
caching is working
* add almost all the input parameter state to the hash
- missing items are the detected MSVC installation on Windows
and detected libc installation on POSIX
- also missing are C files and .h files that libclang finds
* artifacts are created in global cache directory instead of
zig-cache.
- exception: builtin.zig is still in zig-cache
* zig run uses the new cache correctly
* zig run uses execv on posix systems
This commit is contained in:
parent
fbe5737c84
commit
32be6e9b2a
@ -1554,6 +1554,40 @@ struct CodeGen {
|
||||
ZigLLVMDICompileUnit *compile_unit;
|
||||
ZigLLVMDIFile *compile_unit_file;
|
||||
LinkLib *libc_link_lib;
|
||||
LLVMTargetDataRef target_data_ref;
|
||||
LLVMTargetMachineRef target_machine;
|
||||
ZigLLVMDIFile *dummy_di_file;
|
||||
LLVMValueRef cur_ret_ptr;
|
||||
LLVMValueRef cur_fn_val;
|
||||
LLVMValueRef cur_err_ret_trace_val_arg;
|
||||
LLVMValueRef cur_err_ret_trace_val_stack;
|
||||
LLVMValueRef memcpy_fn_val;
|
||||
LLVMValueRef memset_fn_val;
|
||||
LLVMValueRef trap_fn_val;
|
||||
LLVMValueRef return_address_fn_val;
|
||||
LLVMValueRef frame_address_fn_val;
|
||||
LLVMValueRef coro_destroy_fn_val;
|
||||
LLVMValueRef coro_id_fn_val;
|
||||
LLVMValueRef coro_alloc_fn_val;
|
||||
LLVMValueRef coro_size_fn_val;
|
||||
LLVMValueRef coro_begin_fn_val;
|
||||
LLVMValueRef coro_suspend_fn_val;
|
||||
LLVMValueRef coro_end_fn_val;
|
||||
LLVMValueRef coro_free_fn_val;
|
||||
LLVMValueRef coro_resume_fn_val;
|
||||
LLVMValueRef coro_save_fn_val;
|
||||
LLVMValueRef coro_promise_fn_val;
|
||||
LLVMValueRef coro_alloc_helper_fn_val;
|
||||
LLVMValueRef coro_frame_fn_val;
|
||||
LLVMValueRef merge_err_ret_traces_fn_val;
|
||||
LLVMValueRef add_error_return_trace_addr_fn_val;
|
||||
LLVMValueRef stacksave_fn_val;
|
||||
LLVMValueRef stackrestore_fn_val;
|
||||
LLVMValueRef write_register_fn_val;
|
||||
LLVMValueRef sp_md_node;
|
||||
LLVMValueRef err_name_table;
|
||||
LLVMValueRef safety_crash_err_fn;
|
||||
LLVMValueRef return_err_fn;
|
||||
|
||||
// reminder: hash tables must be initialized before use
|
||||
HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table;
|
||||
@ -1576,8 +1610,23 @@ struct CodeGen {
|
||||
size_t resolve_queue_index;
|
||||
ZigList<AstNode *> use_queue;
|
||||
size_t use_queue_index;
|
||||
ZigList<TimeEvent> timing_events;
|
||||
ZigList<ZigLLVMDIType **> error_di_types;
|
||||
ZigList<AstNode *> tld_ref_source_node_stack;
|
||||
ZigList<ZigFn *> inline_fns;
|
||||
ZigList<ZigFn *> test_fns;
|
||||
ZigList<ZigLLVMDIEnumerator *> err_enumerators;
|
||||
ZigList<ErrorTableEntry *> errors_by_index;
|
||||
size_t largest_err_name_len;
|
||||
|
||||
uint32_t next_unresolved_index;
|
||||
PackageTableEntry *std_package;
|
||||
PackageTableEntry *panic_package;
|
||||
PackageTableEntry *test_runner_package;
|
||||
PackageTableEntry *compile_var_package;
|
||||
ImportTableEntry *compile_var_import;
|
||||
ImportTableEntry *root_import;
|
||||
ImportTableEntry *bootstrap_import;
|
||||
ImportTableEntry *test_runner_import;
|
||||
|
||||
struct {
|
||||
ZigType *entry_bool;
|
||||
@ -1613,30 +1662,45 @@ struct CodeGen {
|
||||
ZigType *entry_arg_tuple;
|
||||
ZigType *entry_promise;
|
||||
} builtin_types;
|
||||
ZigType *align_amt_type;
|
||||
ZigType *stack_trace_type;
|
||||
ZigType *ptr_to_stack_trace_type;
|
||||
ZigType *err_tag_type;
|
||||
ZigType *test_fn_type;
|
||||
|
||||
Buf triple_str;
|
||||
Buf global_asm;
|
||||
Buf *out_h_path;
|
||||
Buf cache_dir;
|
||||
Buf artifact_dir;
|
||||
Buf output_file_path;
|
||||
Buf o_file_output_path;
|
||||
Buf *wanted_output_file_path;
|
||||
|
||||
IrInstruction *invalid_instruction;
|
||||
|
||||
ConstExprValue const_void_val;
|
||||
ConstExprValue panic_msg_vals[PanicMsgIdCount];
|
||||
|
||||
// The function definitions this module includes.
|
||||
ZigList<ZigFn *> fn_defs;
|
||||
size_t fn_defs_index;
|
||||
ZigList<TldVar *> global_vars;
|
||||
|
||||
ZigFn *cur_fn;
|
||||
ZigFn *main_fn;
|
||||
ZigFn *panic_fn;
|
||||
AstNode *root_export_decl;
|
||||
|
||||
CacheHash cache_hash;
|
||||
|
||||
//////////////////////////// Participates in Input Parameter Cache Hash
|
||||
Buf *compiler_id;
|
||||
ZigList<LinkLib *> link_libs_list;
|
||||
// add -framework [name] args to linker
|
||||
ZigList<Buf *> darwin_frameworks;
|
||||
// add -rpath [name] args to linker
|
||||
ZigList<Buf *> rpath_list;
|
||||
|
||||
EmitFileType emit_file_type;
|
||||
BuildMode build_mode;
|
||||
OutType out_type;
|
||||
|
||||
|
||||
//////////////////////////// Unsorted
|
||||
|
||||
ZigTarget zig_target;
|
||||
LLVMTargetDataRef target_data_ref;
|
||||
ErrColor err_color;
|
||||
uint32_t next_unresolved_index;
|
||||
unsigned pointer_size_bytes;
|
||||
uint32_t target_os_index;
|
||||
uint32_t target_arch_index;
|
||||
uint32_t target_environ_index;
|
||||
uint32_t target_oformat_index;
|
||||
bool is_big_endian;
|
||||
bool is_static;
|
||||
bool strip_debug_symbols;
|
||||
bool want_h_file;
|
||||
bool have_pub_main;
|
||||
bool have_c_main;
|
||||
@ -1644,6 +1708,64 @@ struct CodeGen {
|
||||
bool have_winmain_crt_startup;
|
||||
bool have_dllmain_crt_startup;
|
||||
bool have_pub_panic;
|
||||
bool have_err_ret_tracing;
|
||||
bool c_want_stdint;
|
||||
bool c_want_stdbool;
|
||||
bool verbose_tokenize;
|
||||
bool verbose_ast;
|
||||
bool verbose_link;
|
||||
bool verbose_ir;
|
||||
bool verbose_llvm_ir;
|
||||
bool verbose_cimport;
|
||||
bool error_during_imports;
|
||||
bool generate_error_name_table;
|
||||
|
||||
//////////////////////////// Participates in Input Parameter Cache Hash
|
||||
ZigList<LinkLib *> link_libs_list;
|
||||
// add -framework [name] args to linker
|
||||
ZigList<Buf *> darwin_frameworks;
|
||||
// add -rpath [name] args to linker
|
||||
ZigList<Buf *> rpath_list;
|
||||
ZigList<Buf *> forbidden_libs;
|
||||
ZigList<Buf *> link_objects;
|
||||
ZigList<Buf *> assembly_files;
|
||||
ZigList<const char *> lib_dirs;
|
||||
|
||||
Buf *compiler_id;
|
||||
size_t version_major;
|
||||
size_t version_minor;
|
||||
size_t version_patch;
|
||||
const char *linker_script;
|
||||
|
||||
EmitFileType emit_file_type;
|
||||
BuildMode build_mode;
|
||||
OutType out_type;
|
||||
ZigTarget zig_target;
|
||||
bool is_static;
|
||||
bool strip_debug_symbols;
|
||||
bool is_test_build;
|
||||
bool is_native_target;
|
||||
bool windows_subsystem_windows;
|
||||
bool windows_subsystem_console;
|
||||
bool linker_rdynamic;
|
||||
bool no_rosegment_workaround;
|
||||
bool each_lib_rpath;
|
||||
|
||||
Buf *mmacosx_version_min;
|
||||
Buf *mios_version_min;
|
||||
Buf *root_out_name;
|
||||
Buf *test_filter;
|
||||
Buf *test_name_prefix;
|
||||
PackageTableEntry *root_package;
|
||||
|
||||
const char **llvm_argv;
|
||||
size_t llvm_argv_len;
|
||||
|
||||
const char **clang_argv;
|
||||
size_t clang_argv_len;
|
||||
|
||||
//////////////////////////// Unsorted
|
||||
|
||||
Buf *libc_lib_dir;
|
||||
Buf *libc_static_lib_dir;
|
||||
Buf *libc_include_dir;
|
||||
@ -1654,138 +1776,7 @@ struct CodeGen {
|
||||
Buf *zig_c_headers_dir;
|
||||
Buf *zig_std_special_dir;
|
||||
Buf *dynamic_linker;
|
||||
Buf *ar_path;
|
||||
ZigWindowsSDK *win_sdk;
|
||||
Buf triple_str;
|
||||
bool is_test_build;
|
||||
bool have_err_ret_tracing;
|
||||
uint32_t target_os_index;
|
||||
uint32_t target_arch_index;
|
||||
uint32_t target_environ_index;
|
||||
uint32_t target_oformat_index;
|
||||
LLVMTargetMachineRef target_machine;
|
||||
ZigLLVMDIFile *dummy_di_file;
|
||||
bool is_native_target;
|
||||
PackageTableEntry *root_package; // participates in cache hash
|
||||
PackageTableEntry *std_package;
|
||||
PackageTableEntry *panic_package;
|
||||
PackageTableEntry *test_runner_package;
|
||||
PackageTableEntry *compile_var_package;
|
||||
ImportTableEntry *compile_var_import;
|
||||
Buf *root_out_name; // participates in cache hash
|
||||
bool windows_subsystem_windows;
|
||||
bool windows_subsystem_console;
|
||||
Buf *mmacosx_version_min;
|
||||
Buf *mios_version_min;
|
||||
bool linker_rdynamic;
|
||||
const char *linker_script;
|
||||
|
||||
// The function definitions this module includes.
|
||||
ZigList<ZigFn *> fn_defs;
|
||||
size_t fn_defs_index;
|
||||
ZigList<TldVar *> global_vars;
|
||||
|
||||
ZigFn *cur_fn;
|
||||
ZigFn *main_fn;
|
||||
ZigFn *panic_fn;
|
||||
LLVMValueRef cur_ret_ptr;
|
||||
LLVMValueRef cur_fn_val;
|
||||
LLVMValueRef cur_err_ret_trace_val_arg;
|
||||
LLVMValueRef cur_err_ret_trace_val_stack;
|
||||
bool c_want_stdint;
|
||||
bool c_want_stdbool;
|
||||
AstNode *root_export_decl;
|
||||
size_t version_major;
|
||||
size_t version_minor;
|
||||
size_t version_patch;
|
||||
bool verbose_tokenize;
|
||||
bool verbose_ast;
|
||||
bool verbose_link;
|
||||
bool verbose_ir;
|
||||
bool verbose_llvm_ir;
|
||||
bool verbose_cimport;
|
||||
ErrColor err_color;
|
||||
ImportTableEntry *root_import;
|
||||
ImportTableEntry *bootstrap_import;
|
||||
ImportTableEntry *test_runner_import;
|
||||
LLVMValueRef memcpy_fn_val;
|
||||
LLVMValueRef memset_fn_val;
|
||||
LLVMValueRef trap_fn_val;
|
||||
LLVMValueRef return_address_fn_val;
|
||||
LLVMValueRef frame_address_fn_val;
|
||||
LLVMValueRef coro_destroy_fn_val;
|
||||
LLVMValueRef coro_id_fn_val;
|
||||
LLVMValueRef coro_alloc_fn_val;
|
||||
LLVMValueRef coro_size_fn_val;
|
||||
LLVMValueRef coro_begin_fn_val;
|
||||
LLVMValueRef coro_suspend_fn_val;
|
||||
LLVMValueRef coro_end_fn_val;
|
||||
LLVMValueRef coro_free_fn_val;
|
||||
LLVMValueRef coro_resume_fn_val;
|
||||
LLVMValueRef coro_save_fn_val;
|
||||
LLVMValueRef coro_promise_fn_val;
|
||||
LLVMValueRef coro_alloc_helper_fn_val;
|
||||
LLVMValueRef coro_frame_fn_val;
|
||||
LLVMValueRef merge_err_ret_traces_fn_val;
|
||||
LLVMValueRef add_error_return_trace_addr_fn_val;
|
||||
LLVMValueRef stacksave_fn_val;
|
||||
LLVMValueRef stackrestore_fn_val;
|
||||
LLVMValueRef write_register_fn_val;
|
||||
bool error_during_imports;
|
||||
|
||||
LLVMValueRef sp_md_node;
|
||||
|
||||
const char **clang_argv;
|
||||
size_t clang_argv_len;
|
||||
ZigList<const char *> lib_dirs;
|
||||
|
||||
const char **llvm_argv;
|
||||
size_t llvm_argv_len;
|
||||
|
||||
ZigList<ZigFn *> test_fns;
|
||||
ZigType *test_fn_type;
|
||||
|
||||
bool each_lib_rpath;
|
||||
|
||||
ZigType *err_tag_type;
|
||||
ZigList<ZigLLVMDIEnumerator *> err_enumerators;
|
||||
ZigList<ErrorTableEntry *> errors_by_index;
|
||||
bool generate_error_name_table;
|
||||
LLVMValueRef err_name_table;
|
||||
size_t largest_err_name_len;
|
||||
LLVMValueRef safety_crash_err_fn;
|
||||
|
||||
LLVMValueRef return_err_fn;
|
||||
|
||||
IrInstruction *invalid_instruction;
|
||||
ConstExprValue const_void_val;
|
||||
|
||||
ConstExprValue panic_msg_vals[PanicMsgIdCount];
|
||||
|
||||
Buf global_asm;
|
||||
ZigList<Buf *> link_objects;
|
||||
ZigList<Buf *> assembly_files;
|
||||
|
||||
Buf *test_filter;
|
||||
Buf *test_name_prefix;
|
||||
|
||||
ZigList<TimeEvent> timing_events;
|
||||
|
||||
Buf cache_dir;
|
||||
Buf *out_h_path;
|
||||
|
||||
ZigList<ZigFn *> inline_fns;
|
||||
ZigList<AstNode *> tld_ref_source_node_stack;
|
||||
|
||||
ZigType *align_amt_type;
|
||||
ZigType *stack_trace_type;
|
||||
ZigType *ptr_to_stack_trace_type;
|
||||
|
||||
ZigList<ZigLLVMDIType **> error_di_types;
|
||||
|
||||
ZigList<Buf *> forbidden_libs;
|
||||
|
||||
bool no_rosegment_workaround;
|
||||
};
|
||||
|
||||
enum VarLinkage {
|
||||
|
||||
@ -37,6 +37,20 @@ void cache_int(CacheHash *ch, int x) {
|
||||
blake2b_update(&ch->blake, buf, sizeof(int) + 1);
|
||||
}
|
||||
|
||||
void cache_usize(CacheHash *ch, size_t x) {
|
||||
assert(ch->manifest_file_path == nullptr);
|
||||
// + 1 to include the null byte
|
||||
uint8_t buf[sizeof(size_t) + 1];
|
||||
memcpy(buf, &x, sizeof(size_t));
|
||||
buf[sizeof(size_t)] = 0;
|
||||
blake2b_update(&ch->blake, buf, sizeof(size_t) + 1);
|
||||
}
|
||||
|
||||
void cache_bool(CacheHash *ch, bool x) {
|
||||
assert(ch->manifest_file_path == nullptr);
|
||||
blake2b_update(&ch->blake, &x, 1);
|
||||
}
|
||||
|
||||
void cache_buf(CacheHash *ch, Buf *buf) {
|
||||
assert(ch->manifest_file_path == nullptr);
|
||||
assert(buf != nullptr);
|
||||
@ -74,6 +88,26 @@ void cache_list_of_buf(CacheHash *ch, Buf **ptr, size_t len) {
|
||||
cache_str(ch, "");
|
||||
}
|
||||
|
||||
void cache_list_of_file(CacheHash *ch, Buf **ptr, size_t len) {
|
||||
assert(ch->manifest_file_path == nullptr);
|
||||
|
||||
for (size_t i = 0; i < len; i += 1) {
|
||||
Buf *buf = ptr[i];
|
||||
cache_file(ch, buf);
|
||||
}
|
||||
cache_str(ch, "");
|
||||
}
|
||||
|
||||
void cache_list_of_str(CacheHash *ch, const char **ptr, size_t len) {
|
||||
assert(ch->manifest_file_path == nullptr);
|
||||
|
||||
for (size_t i = 0; i < len; i += 1) {
|
||||
const char *s = ptr[i];
|
||||
cache_str(ch, s);
|
||||
}
|
||||
cache_str(ch, "");
|
||||
}
|
||||
|
||||
void cache_file(CacheHash *ch, Buf *file_path) {
|
||||
assert(ch->manifest_file_path == nullptr);
|
||||
assert(file_path != nullptr);
|
||||
@ -154,9 +188,13 @@ static Error base64_decode(Slice<uint8_t> dest, Slice<uint8_t> source) {
|
||||
return ErrorNone;
|
||||
}
|
||||
|
||||
static Error hash_file(uint8_t *digest, OsFile handle) {
|
||||
static Error hash_file(uint8_t *digest, OsFile handle, Buf *contents) {
|
||||
Error err;
|
||||
|
||||
if (contents) {
|
||||
buf_resize(contents, 0);
|
||||
}
|
||||
|
||||
blake2b_state blake;
|
||||
int rc = blake2b_init(&blake, 48);
|
||||
assert(rc == 0);
|
||||
@ -172,10 +210,13 @@ static Error hash_file(uint8_t *digest, OsFile handle) {
|
||||
return ErrorNone;
|
||||
}
|
||||
blake2b_update(&blake, buf, amt);
|
||||
if (contents) {
|
||||
buf_append_mem(contents, (char*)buf, amt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Error populate_file_hash(CacheHash *ch, CacheHashFile *chf) {
|
||||
static Error populate_file_hash(CacheHash *ch, CacheHashFile *chf, Buf *contents) {
|
||||
Error err;
|
||||
|
||||
assert(chf->path != nullptr);
|
||||
@ -189,7 +230,7 @@ static Error populate_file_hash(CacheHash *ch, CacheHashFile *chf) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if ((err = hash_file(chf->bin_digest, this_file))) {
|
||||
if ((err = hash_file(chf->bin_digest, this_file, contents))) {
|
||||
os_file_close(this_file);
|
||||
return err;
|
||||
}
|
||||
@ -323,7 +364,7 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
|
||||
chf->mtime = actual_mtime;
|
||||
|
||||
uint8_t actual_digest[48];
|
||||
if ((err = hash_file(actual_digest, this_file))) {
|
||||
if ((err = hash_file(actual_digest, this_file, nullptr))) {
|
||||
os_file_close(this_file);
|
||||
os_file_close(ch->manifest_file);
|
||||
return err;
|
||||
@ -344,7 +385,7 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
|
||||
ch->manifest_dirty = true;
|
||||
for (; file_i < input_file_count; file_i += 1) {
|
||||
CacheHashFile *chf = &ch->files.at(file_i);
|
||||
if ((err = populate_file_hash(ch, chf))) {
|
||||
if ((err = populate_file_hash(ch, chf, nullptr))) {
|
||||
os_file_close(ch->manifest_file);
|
||||
return err;
|
||||
}
|
||||
@ -355,13 +396,13 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
|
||||
return cache_final(ch, out_digest);
|
||||
}
|
||||
|
||||
Error cache_add_file(CacheHash *ch, Buf *path) {
|
||||
Error cache_add_file_fetch(CacheHash *ch, Buf *resolved_path, Buf *contents) {
|
||||
Error err;
|
||||
|
||||
assert(ch->manifest_file_path != nullptr);
|
||||
CacheHashFile *chf = ch->files.add_one();
|
||||
chf->path = path;
|
||||
if ((err = populate_file_hash(ch, chf))) {
|
||||
chf->path = resolved_path;
|
||||
if ((err = populate_file_hash(ch, chf, contents))) {
|
||||
os_file_close(ch->manifest_file);
|
||||
return err;
|
||||
}
|
||||
@ -369,6 +410,12 @@ Error cache_add_file(CacheHash *ch, Buf *path) {
|
||||
return ErrorNone;
|
||||
}
|
||||
|
||||
Error cache_add_file(CacheHash *ch, Buf *path) {
|
||||
Buf *resolved_path = buf_alloc();
|
||||
*resolved_path = os_path_resolve(&path, 1);
|
||||
return cache_add_file_fetch(ch, resolved_path, nullptr);
|
||||
}
|
||||
|
||||
static Error write_manifest_file(CacheHash *ch) {
|
||||
Error err;
|
||||
Buf contents = BUF_INIT;
|
||||
@ -398,7 +445,8 @@ Error cache_final(CacheHash *ch, Buf *out_digest) {
|
||||
buf_ptr(ch->manifest_file_path), err_str(err));
|
||||
}
|
||||
}
|
||||
os_file_close(ch->manifest_file);
|
||||
// We don't close the manifest file yet, because we want to
|
||||
// keep it locked until the API user is done using it.
|
||||
|
||||
uint8_t bin_digest[48];
|
||||
int rc = blake2b_final(&ch->blake, bin_digest, 48);
|
||||
@ -408,3 +456,7 @@ Error cache_final(CacheHash *ch, Buf *out_digest) {
|
||||
|
||||
return ErrorNone;
|
||||
}
|
||||
|
||||
void cache_release(CacheHash *ch) {
|
||||
os_file_close(ch->manifest_file);
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ struct CacheHashFile {
|
||||
Buf *path;
|
||||
OsTimeStamp mtime;
|
||||
uint8_t bin_digest[48];
|
||||
Buf *contents;
|
||||
};
|
||||
|
||||
struct CacheHash {
|
||||
@ -34,24 +35,36 @@ void cache_init(CacheHash *ch, Buf *manifest_dir);
|
||||
// Next, use the hash population functions to add the initial parameters.
|
||||
void cache_str(CacheHash *ch, const char *ptr);
|
||||
void cache_int(CacheHash *ch, int x);
|
||||
void cache_bool(CacheHash *ch, bool x);
|
||||
void cache_usize(CacheHash *ch, size_t x);
|
||||
void cache_buf(CacheHash *ch, Buf *buf);
|
||||
void cache_buf_opt(CacheHash *ch, Buf *buf);
|
||||
void cache_list_of_link_lib(CacheHash *ch, LinkLib **ptr, size_t len);
|
||||
void cache_list_of_buf(CacheHash *ch, Buf **ptr, size_t len);
|
||||
void cache_list_of_file(CacheHash *ch, Buf **ptr, size_t len);
|
||||
void cache_list_of_str(CacheHash *ch, const char **ptr, size_t len);
|
||||
void cache_file(CacheHash *ch, Buf *path);
|
||||
void cache_file_opt(CacheHash *ch, Buf *path);
|
||||
|
||||
// Then call cache_hit when you're ready to see if you can skip the next step.
|
||||
// out_b64_digest will be left unchanged if it was a cache miss
|
||||
// out_b64_digest will be left unchanged if it was a cache miss.
|
||||
// If you got a cache hit, the next step is cache_release.
|
||||
// From this point on, there is a lock on the input params. Release
|
||||
// the lock with cache_release.
|
||||
Error ATTRIBUTE_MUST_USE cache_hit(CacheHash *ch, Buf *out_b64_digest);
|
||||
|
||||
// If you got a cache hit, the flow is done. No more functions to call.
|
||||
// Next call this function for every file that is depended on.
|
||||
// If you did not get a cache hit, call this function for every file
|
||||
// that is depended on, and then finish with cache_final.
|
||||
Error ATTRIBUTE_MUST_USE cache_add_file(CacheHash *ch, Buf *path);
|
||||
|
||||
// If you did not get a cache hit, use the hash population functions again
|
||||
// and do all the actual work. When done use cache_final to save the cache
|
||||
// for next time.
|
||||
Error ATTRIBUTE_MUST_USE cache_final(CacheHash *ch, Buf *out_digest);
|
||||
// This variant of cache_add_file returns the file contents.
|
||||
// Also the file path argument must be already resolved.
|
||||
Error ATTRIBUTE_MUST_USE cache_add_file_fetch(CacheHash *ch, Buf *resolved_path, Buf *contents);
|
||||
|
||||
// out_b64_digest will be the same thing that cache_hit returns if you got a cache hit
|
||||
Error ATTRIBUTE_MUST_USE cache_final(CacheHash *ch, Buf *out_b64_digest);
|
||||
|
||||
// Until this function is called, no one will be able to get a lock on your input params.
|
||||
void cache_release(CacheHash *ch);
|
||||
|
||||
#endif
|
||||
|
||||
199
src/codegen.cpp
199
src/codegen.cpp
@ -13,7 +13,6 @@
|
||||
#include "error.hpp"
|
||||
#include "hash_map.hpp"
|
||||
#include "ir.hpp"
|
||||
#include "link.hpp"
|
||||
#include "os.hpp"
|
||||
#include "translate_c.hpp"
|
||||
#include "target.hpp"
|
||||
@ -188,6 +187,10 @@ void codegen_set_output_h_path(CodeGen *g, Buf *h_path) {
|
||||
g->out_h_path = h_path;
|
||||
}
|
||||
|
||||
void codegen_set_output_path(CodeGen *g, Buf *path) {
|
||||
g->wanted_output_file_path = path;
|
||||
}
|
||||
|
||||
void codegen_set_clang_argv(CodeGen *g, const char **args, size_t len) {
|
||||
g->clang_argv = args;
|
||||
g->clang_argv_len = len;
|
||||
@ -5756,8 +5759,6 @@ static void validate_inline_fns(CodeGen *g) {
|
||||
static void do_code_gen(CodeGen *g) {
|
||||
assert(!g->errors.length);
|
||||
|
||||
codegen_add_time_event(g, "Code Generation");
|
||||
|
||||
{
|
||||
// create debug type for error sets
|
||||
assert(g->err_enumerators.length == g->errors_by_index.length);
|
||||
@ -6068,38 +6069,10 @@ static void do_code_gen(CodeGen *g) {
|
||||
|
||||
codegen_add_time_event(g, "LLVM Emit Output");
|
||||
|
||||
char *err_msg = nullptr;
|
||||
Buf *o_basename = buf_create_from_buf(g->root_out_name);
|
||||
|
||||
switch (g->emit_file_type) {
|
||||
case EmitFileTypeBinary:
|
||||
{
|
||||
const char *o_ext = target_o_file_ext(&g->zig_target);
|
||||
buf_append_str(o_basename, o_ext);
|
||||
break;
|
||||
}
|
||||
case EmitFileTypeAssembly:
|
||||
{
|
||||
const char *asm_ext = target_asm_file_ext(&g->zig_target);
|
||||
buf_append_str(o_basename, asm_ext);
|
||||
break;
|
||||
}
|
||||
case EmitFileTypeLLVMIr:
|
||||
{
|
||||
const char *llvm_ir_ext = target_llvm_ir_file_ext(&g->zig_target);
|
||||
buf_append_str(o_basename, llvm_ir_ext);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
Buf *output_path = buf_alloc();
|
||||
os_path_join(&g->cache_dir, o_basename, output_path);
|
||||
ensure_cache_dir(g);
|
||||
|
||||
bool is_small = g->build_mode == BuildModeSmallRelease;
|
||||
|
||||
Buf *output_path = &g->o_file_output_path;
|
||||
char *err_msg = nullptr;
|
||||
switch (g->emit_file_type) {
|
||||
case EmitFileTypeBinary:
|
||||
if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
|
||||
@ -6118,7 +6091,6 @@ static void do_code_gen(CodeGen *g) {
|
||||
zig_panic("unable to write assembly file %s: %s", buf_ptr(output_path), err_msg);
|
||||
}
|
||||
validate_inline_fns(g);
|
||||
g->link_objects.append(output_path);
|
||||
break;
|
||||
|
||||
case EmitFileTypeLLVMIr:
|
||||
@ -6128,7 +6100,6 @@ static void do_code_gen(CodeGen *g) {
|
||||
zig_panic("unable to write llvm-ir file %s: %s", buf_ptr(output_path), err_msg);
|
||||
}
|
||||
validate_inline_fns(g);
|
||||
g->link_objects.append(output_path);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -7035,8 +7006,8 @@ static ImportTableEntry *add_special_code(CodeGen *g, PackageTableEntry *package
|
||||
Buf *resolved_path = buf_alloc();
|
||||
*resolved_path = os_path_resolve(resolve_paths, 1);
|
||||
Buf *import_code = buf_alloc();
|
||||
int err;
|
||||
if ((err = os_fetch_file_path(resolved_path, import_code, false))) {
|
||||
Error err;
|
||||
if ((err = cache_add_file_fetch(&g->cache_hash, resolved_path, import_code))) {
|
||||
zig_panic("unable to open '%s': %s\n", buf_ptr(&path_to_code_src), err_str(err));
|
||||
}
|
||||
|
||||
@ -7131,6 +7102,8 @@ static void gen_root_source(CodeGen *g) {
|
||||
|
||||
Buf *source_code = buf_alloc();
|
||||
int err;
|
||||
// No need for using the caching system for this file fetch because it is handled
|
||||
// separately.
|
||||
if ((err = os_fetch_file_path(resolved_path, source_code, true))) {
|
||||
fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(resolved_path), err_str(err));
|
||||
exit(1);
|
||||
@ -7197,6 +7170,8 @@ static void gen_global_asm(CodeGen *g) {
|
||||
int err;
|
||||
for (size_t i = 0; i < g->assembly_files.length; i += 1) {
|
||||
Buf *asm_file = g->assembly_files.at(i);
|
||||
// No need to use the caching system for these fetches because they
|
||||
// are handled separately.
|
||||
if ((err = os_fetch_file_path(asm_file, &contents, false))) {
|
||||
zig_panic("Unable to read %s: %s", buf_ptr(asm_file), err_str(err));
|
||||
}
|
||||
@ -7460,14 +7435,9 @@ static Buf *preprocessor_mangle(Buf *src) {
|
||||
}
|
||||
|
||||
static void gen_h_file(CodeGen *g) {
|
||||
if (!g->want_h_file)
|
||||
return;
|
||||
|
||||
GenH gen_h_data = {0};
|
||||
GenH *gen_h = &gen_h_data;
|
||||
|
||||
codegen_add_time_event(g, "Generate .h");
|
||||
|
||||
assert(!g->is_test_build);
|
||||
|
||||
if (!g->out_h_path) {
|
||||
@ -7675,6 +7645,24 @@ void codegen_add_time_event(CodeGen *g, const char *name) {
|
||||
g->timing_events.append({os_get_time(), name});
|
||||
}
|
||||
|
||||
static void add_cache_pkg(CodeGen *g, CacheHash *ch, PackageTableEntry *pkg) {
|
||||
if (buf_len(&pkg->root_src_path) == 0)
|
||||
return;
|
||||
|
||||
Buf *rel_full_path = buf_alloc();
|
||||
os_path_join(&pkg->root_src_dir, &pkg->root_src_path, rel_full_path);
|
||||
cache_file(ch, rel_full_path);
|
||||
|
||||
auto it = pkg->package_table.entry_iterator();
|
||||
for (;;) {
|
||||
auto *entry = it.next();
|
||||
if (!entry)
|
||||
break;
|
||||
|
||||
cache_buf(ch, entry->key);
|
||||
add_cache_pkg(g, ch, entry->value);
|
||||
}
|
||||
}
|
||||
|
||||
// Called before init()
|
||||
static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
|
||||
@ -7683,16 +7671,46 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
|
||||
CacheHash *ch = &g->cache_hash;
|
||||
cache_init(ch, manifest_dir);
|
||||
|
||||
add_cache_pkg(g, ch, g->root_package);
|
||||
if (g->linker_script != nullptr) {
|
||||
cache_file(ch, buf_create_from_str(g->linker_script));
|
||||
}
|
||||
cache_buf(ch, g->compiler_id);
|
||||
cache_buf(ch, g->root_out_name);
|
||||
cache_file(ch, get_resolved_root_src_path(g)); // Root source file
|
||||
cache_list_of_link_lib(ch, g->link_libs_list.items, g->link_libs_list.length);
|
||||
cache_list_of_buf(ch, g->darwin_frameworks.items, g->darwin_frameworks.length);
|
||||
cache_list_of_buf(ch, g->rpath_list.items, g->rpath_list.length);
|
||||
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);
|
||||
cache_int(ch, g->emit_file_type);
|
||||
cache_int(ch, g->build_mode);
|
||||
cache_int(ch, g->out_type);
|
||||
// TODO the rest of the struct CodeGen fields
|
||||
cache_int(ch, g->zig_target.arch.arch);
|
||||
cache_int(ch, g->zig_target.arch.sub_arch);
|
||||
cache_int(ch, g->zig_target.vendor);
|
||||
cache_int(ch, g->zig_target.os);
|
||||
cache_int(ch, g->zig_target.env_type);
|
||||
cache_int(ch, g->zig_target.oformat);
|
||||
cache_bool(ch, g->is_static);
|
||||
cache_bool(ch, g->strip_debug_symbols);
|
||||
cache_bool(ch, g->is_test_build);
|
||||
cache_bool(ch, g->is_native_target);
|
||||
cache_bool(ch, g->windows_subsystem_windows);
|
||||
cache_bool(ch, g->windows_subsystem_console);
|
||||
cache_bool(ch, g->linker_rdynamic);
|
||||
cache_bool(ch, g->no_rosegment_workaround);
|
||||
cache_bool(ch, g->each_lib_rpath);
|
||||
cache_buf_opt(ch, g->mmacosx_version_min);
|
||||
cache_buf_opt(ch, g->mios_version_min);
|
||||
cache_usize(ch, g->version_major);
|
||||
cache_usize(ch, g->version_minor);
|
||||
cache_usize(ch, g->version_patch);
|
||||
cache_buf_opt(ch, g->test_filter);
|
||||
cache_buf_opt(ch, g->test_name_prefix);
|
||||
cache_list_of_str(ch, g->llvm_argv, g->llvm_argv_len);
|
||||
cache_list_of_str(ch, g->clang_argv, g->clang_argv_len);
|
||||
cache_list_of_str(ch, g->lib_dirs.items, g->lib_dirs.length);
|
||||
|
||||
buf_resize(digest, 0);
|
||||
if ((err = cache_hit(ch, digest)))
|
||||
@ -7701,10 +7719,53 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
|
||||
return ErrorNone;
|
||||
}
|
||||
|
||||
void codegen_build(CodeGen *g) {
|
||||
static void resolve_out_paths(CodeGen *g) {
|
||||
Buf *o_basename = buf_create_from_buf(g->root_out_name);
|
||||
|
||||
switch (g->emit_file_type) {
|
||||
case EmitFileTypeBinary:
|
||||
{
|
||||
const char *o_ext = target_o_file_ext(&g->zig_target);
|
||||
buf_append_str(o_basename, o_ext);
|
||||
break;
|
||||
}
|
||||
case EmitFileTypeAssembly:
|
||||
{
|
||||
const char *asm_ext = target_asm_file_ext(&g->zig_target);
|
||||
buf_append_str(o_basename, asm_ext);
|
||||
break;
|
||||
}
|
||||
case EmitFileTypeLLVMIr:
|
||||
{
|
||||
const char *llvm_ir_ext = target_llvm_ir_file_ext(&g->zig_target);
|
||||
buf_append_str(o_basename, llvm_ir_ext);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
zig_unreachable();
|
||||
}
|
||||
|
||||
os_path_join(&g->artifact_dir, o_basename, &g->o_file_output_path);
|
||||
|
||||
if (g->out_type == OutTypeObj) {
|
||||
buf_init_from_buf(&g->output_file_path, &g->o_file_output_path);
|
||||
} else if (g->out_type == OutTypeExe) {
|
||||
assert(g->root_out_name);
|
||||
|
||||
Buf basename = BUF_INIT;
|
||||
buf_init_from_buf(&basename, g->root_out_name);
|
||||
buf_append_str(&basename, target_exe_file_ext(&g->zig_target));
|
||||
os_path_join(&g->artifact_dir, &basename, &g->output_file_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void codegen_build_and_link(CodeGen *g) {
|
||||
Error err;
|
||||
assert(g->out_type != OutTypeUnknown);
|
||||
|
||||
codegen_add_time_event(g, "Check Cache");
|
||||
|
||||
Buf app_data_dir = BUF_INIT;
|
||||
if ((err = os_get_app_data_dir(&app_data_dir, "zig"))) {
|
||||
fprintf(stderr, "Unable to get app data dir: %s\n", err_str(err));
|
||||
@ -7721,25 +7782,45 @@ void codegen_build(CodeGen *g) {
|
||||
fprintf(stderr, "Unable to check cache: %s\n", err_str(err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Buf *artifact_dir = buf_alloc();
|
||||
os_path_join(stage1_dir, buf_create_from_str("artifact"), artifact_dir);
|
||||
|
||||
if (buf_len(&digest) != 0) {
|
||||
Buf *artifact_dir = buf_alloc();
|
||||
os_path_join(stage1_dir, buf_create_from_str("artifact"), artifact_dir);
|
||||
os_path_join(artifact_dir, &digest, &g->artifact_dir);
|
||||
resolve_out_paths(g);
|
||||
} else {
|
||||
init(g);
|
||||
|
||||
Buf *this_artifact_dir = buf_alloc();
|
||||
os_path_join(artifact_dir, &digest, this_artifact_dir);
|
||||
codegen_add_time_event(g, "Semantic Analysis");
|
||||
|
||||
fprintf(stderr, "copy artifacts from %s\n", buf_ptr(this_artifact_dir));
|
||||
return;
|
||||
gen_global_asm(g);
|
||||
gen_root_source(g);
|
||||
|
||||
if ((err = cache_final(&g->cache_hash, &digest))) {
|
||||
fprintf(stderr, "Unable to finalize cache hash: %s\n", err_str(err));
|
||||
exit(1);
|
||||
}
|
||||
os_path_join(artifact_dir, &digest, &g->artifact_dir);
|
||||
if ((err = os_make_path(&g->artifact_dir))) {
|
||||
fprintf(stderr, "Unable to create artifact directory: %s\n", err_str(err));
|
||||
exit(1);
|
||||
}
|
||||
resolve_out_paths(g);
|
||||
|
||||
codegen_add_time_event(g, "Code Generation");
|
||||
do_code_gen(g);
|
||||
if (g->want_h_file) {
|
||||
codegen_add_time_event(g, "Generate .h");
|
||||
gen_h_file(g);
|
||||
}
|
||||
if (g->out_type != OutTypeObj) {
|
||||
codegen_link(g);
|
||||
}
|
||||
}
|
||||
// TODO hard link output_file_path to wanted_output_file_path
|
||||
|
||||
init(g);
|
||||
|
||||
codegen_add_time_event(g, "Semantic Analysis");
|
||||
|
||||
gen_global_asm(g);
|
||||
gen_root_source(g);
|
||||
do_code_gen(g);
|
||||
gen_h_file(g);
|
||||
codegen_add_time_event(g, "Done");
|
||||
}
|
||||
|
||||
PackageTableEntry *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path) {
|
||||
|
||||
@ -48,9 +48,11 @@ void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);
|
||||
void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch);
|
||||
void codegen_set_cache_dir(CodeGen *g, Buf cache_dir);
|
||||
void codegen_set_output_h_path(CodeGen *g, Buf *h_path);
|
||||
void codegen_set_output_path(CodeGen *g, Buf *path);
|
||||
void codegen_add_time_event(CodeGen *g, const char *name);
|
||||
void codegen_print_timing_report(CodeGen *g, FILE *f);
|
||||
void codegen_build(CodeGen *g);
|
||||
void codegen_link(CodeGen *g);
|
||||
void codegen_build_and_link(CodeGen *g);
|
||||
|
||||
PackageTableEntry *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path);
|
||||
void codegen_add_assembly(CodeGen *g, Buf *path);
|
||||
|
||||
@ -29,6 +29,7 @@ const char *err_str(int err) {
|
||||
case ErrorCCompileErrors: return "C compile errors";
|
||||
case ErrorEndOfFile: return "end of file";
|
||||
case ErrorIsDir: return "is directory";
|
||||
case ErrorUnsupportedOperatingSystem: return "unsupported operating system";
|
||||
}
|
||||
return "(invalid error)";
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@ enum Error {
|
||||
ErrorCCompileErrors,
|
||||
ErrorEndOfFile,
|
||||
ErrorIsDir,
|
||||
ErrorUnsupportedOperatingSystem,
|
||||
};
|
||||
|
||||
const char *err_str(int err);
|
||||
|
||||
11
src/ir.cpp
11
src/ir.cpp
@ -16232,6 +16232,8 @@ static ZigType *ir_analyze_instruction_union_tag(IrAnalyze *ira, IrInstructionUn
|
||||
}
|
||||
|
||||
static ZigType *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructionImport *import_instruction) {
|
||||
Error err;
|
||||
|
||||
IrInstruction *name_value = import_instruction->name->other;
|
||||
Buf *import_target_str = ir_resolve_str(ira, name_value);
|
||||
if (!import_target_str)
|
||||
@ -16275,8 +16277,7 @@ static ZigType *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructionImpor
|
||||
return ira->codegen->builtin_types.entry_namespace;
|
||||
}
|
||||
|
||||
int err;
|
||||
if ((err = os_fetch_file_path(resolved_path, import_code, true))) {
|
||||
if ((err = cache_add_file_fetch(&ira->codegen->cache_hash, resolved_path, import_code))) {
|
||||
if (err == ErrorFileNotFound) {
|
||||
ir_add_error_node(ira, source_node,
|
||||
buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
|
||||
@ -16287,6 +16288,7 @@ static ZigType *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructionImpor
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
}
|
||||
|
||||
ImportTableEntry *target_import = add_source_file(ira->codegen, target_package, resolved_path, import_code);
|
||||
|
||||
scan_import(ira->codegen, target_import);
|
||||
@ -18106,7 +18108,7 @@ static ZigType *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstructionE
|
||||
// load from file system into const expr
|
||||
Buf *file_contents = buf_alloc();
|
||||
int err;
|
||||
if ((err = os_fetch_file_path(&file_path, file_contents, false))) {
|
||||
if ((err = cache_add_file_fetch(&ira->codegen->cache_hash, &file_path, file_contents))) {
|
||||
if (err == ErrorFileNotFound) {
|
||||
ir_add_error(ira, instruction->name, buf_sprintf("unable to find '%s'", buf_ptr(&file_path)));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
@ -18116,9 +18118,6 @@ static ZigType *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstructionE
|
||||
}
|
||||
}
|
||||
|
||||
// TODO add dependency on the file we embedded so that we know if it changes
|
||||
// we'll have to invalidate the cache
|
||||
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
|
||||
init_const_str_lit(ira->codegen, out_val, file_contents);
|
||||
|
||||
|
||||
74
src/link.cpp
74
src/link.cpp
@ -5,7 +5,6 @@
|
||||
* See http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "link.hpp"
|
||||
#include "os.hpp"
|
||||
#include "config.h"
|
||||
#include "codegen.hpp"
|
||||
@ -13,7 +12,6 @@
|
||||
|
||||
struct LinkJob {
|
||||
CodeGen *codegen;
|
||||
Buf out_file;
|
||||
ZigList<const char *> args;
|
||||
bool link_in_crt;
|
||||
HashMap<Buf *, bool, buf_hash, buf_eql_buf> rpath_table;
|
||||
@ -62,14 +60,8 @@ static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path)
|
||||
new_link_lib->provided_explicitly = link_lib->provided_explicitly;
|
||||
}
|
||||
|
||||
codegen_build(child_gen);
|
||||
const char *o_ext = target_o_file_ext(&child_gen->zig_target);
|
||||
Buf *o_out_name = buf_sprintf("%s%s", oname, o_ext);
|
||||
Buf *output_path = buf_alloc();
|
||||
os_path_join(&parent_gen->cache_dir, o_out_name, output_path);
|
||||
codegen_link(child_gen, buf_ptr(output_path));
|
||||
|
||||
return output_path;
|
||||
codegen_build_and_link(child_gen);
|
||||
return &child_gen->output_file_path;
|
||||
}
|
||||
|
||||
static Buf *build_o(CodeGen *parent_gen, const char *oname) {
|
||||
@ -237,15 +229,15 @@ static void construct_linker_job_elf(LinkJob *lj) {
|
||||
} else if (shared) {
|
||||
lj->args.append("-shared");
|
||||
|
||||
if (buf_len(&lj->out_file) == 0) {
|
||||
buf_appendf(&lj->out_file, "lib%s.so.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize "",
|
||||
if (buf_len(&g->output_file_path) == 0) {
|
||||
buf_appendf(&g->output_file_path, "lib%s.so.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize "",
|
||||
buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch);
|
||||
}
|
||||
soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize "", buf_ptr(g->root_out_name), g->version_major);
|
||||
}
|
||||
|
||||
lj->args.append("-o");
|
||||
lj->args.append(buf_ptr(&lj->out_file));
|
||||
lj->args.append(buf_ptr(&g->output_file_path));
|
||||
|
||||
if (lj->link_in_crt) {
|
||||
const char *crt1o;
|
||||
@ -397,7 +389,7 @@ static void construct_linker_job_wasm(LinkJob *lj) {
|
||||
|
||||
lj->args.append("--relocatable"); // So lld doesn't look for _start.
|
||||
lj->args.append("-o");
|
||||
lj->args.append(buf_ptr(&lj->out_file));
|
||||
lj->args.append(buf_ptr(&g->output_file_path));
|
||||
|
||||
// .o files
|
||||
for (size_t i = 0; i < g->link_objects.length; i += 1) {
|
||||
@ -478,7 +470,7 @@ static void construct_linker_job_coff(LinkJob *lj) {
|
||||
// }
|
||||
//}
|
||||
|
||||
lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&lj->out_file))));
|
||||
lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));
|
||||
|
||||
if (g->libc_link_lib != nullptr) {
|
||||
lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->msvc_lib_dir))));
|
||||
@ -585,11 +577,11 @@ static void construct_linker_job_coff(LinkJob *lj) {
|
||||
buf_appendf(def_contents, "\n");
|
||||
|
||||
Buf *def_path = buf_alloc();
|
||||
os_path_join(&g->cache_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path);
|
||||
os_path_join(&g->artifact_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path);
|
||||
os_write_file(def_path, def_contents);
|
||||
|
||||
Buf *generated_lib_path = buf_alloc();
|
||||
os_path_join(&g->cache_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path);
|
||||
os_path_join(&g->artifact_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path);
|
||||
|
||||
gen_lib_args.resize(0);
|
||||
gen_lib_args.append("link");
|
||||
@ -797,8 +789,8 @@ static void construct_linker_job_macho(LinkJob *lj) {
|
||||
//lj->args.append("-install_name");
|
||||
//lj->args.append(buf_ptr(dylib_install_name));
|
||||
|
||||
if (buf_len(&lj->out_file) == 0) {
|
||||
buf_appendf(&lj->out_file, "lib%s.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib",
|
||||
if (buf_len(&g->output_file_path) == 0) {
|
||||
buf_appendf(&g->output_file_path, "lib%s.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib",
|
||||
buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch);
|
||||
}
|
||||
}
|
||||
@ -832,13 +824,13 @@ static void construct_linker_job_macho(LinkJob *lj) {
|
||||
}
|
||||
|
||||
lj->args.append("-o");
|
||||
lj->args.append(buf_ptr(&lj->out_file));
|
||||
lj->args.append(buf_ptr(&g->output_file_path));
|
||||
|
||||
for (size_t i = 0; i < g->rpath_list.length; i += 1) {
|
||||
Buf *rpath = g->rpath_list.at(i);
|
||||
add_rpath(lj, rpath);
|
||||
}
|
||||
add_rpath(lj, &lj->out_file);
|
||||
add_rpath(lj, &g->output_file_path);
|
||||
|
||||
if (shared) {
|
||||
lj->args.append("-headerpad_max_install_names");
|
||||
@ -942,7 +934,8 @@ static void construct_linker_job(LinkJob *lj) {
|
||||
}
|
||||
}
|
||||
|
||||
void codegen_link(CodeGen *g, const char *out_file) {
|
||||
void codegen_link(CodeGen *g) {
|
||||
assert(g->out_type != OutTypeObj);
|
||||
codegen_add_time_event(g, "Build Dependencies");
|
||||
|
||||
LinkJob lj = {0};
|
||||
@ -953,11 +946,6 @@ void codegen_link(CodeGen *g, const char *out_file) {
|
||||
|
||||
lj.rpath_table.init(4);
|
||||
lj.codegen = g;
|
||||
if (out_file) {
|
||||
buf_init_from_str(&lj.out_file, out_file);
|
||||
} else {
|
||||
buf_resize(&lj.out_file, 0);
|
||||
}
|
||||
|
||||
if (g->verbose_llvm_ir) {
|
||||
fprintf(stderr, "\nOptimization:\n");
|
||||
@ -966,35 +954,9 @@ void codegen_link(CodeGen *g, const char *out_file) {
|
||||
LLVMDumpModule(g->module);
|
||||
}
|
||||
|
||||
bool override_out_file = (buf_len(&lj.out_file) != 0);
|
||||
if (!override_out_file) {
|
||||
assert(g->root_out_name);
|
||||
|
||||
buf_init_from_buf(&lj.out_file, g->root_out_name);
|
||||
if (g->out_type == OutTypeExe) {
|
||||
buf_append_str(&lj.out_file, target_exe_file_ext(&g->zig_target));
|
||||
}
|
||||
}
|
||||
|
||||
if (g->out_type == OutTypeObj) {
|
||||
if (override_out_file) {
|
||||
assert(g->link_objects.length == 1);
|
||||
Buf *o_file_path = g->link_objects.at(0);
|
||||
int err;
|
||||
if ((err = os_rename(o_file_path, &lj.out_file))) {
|
||||
zig_panic("unable to rename object file %s into final output %s: %s", buf_ptr(o_file_path), buf_ptr(&lj.out_file), err_str(err));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (g->out_type == OutTypeLib && g->is_static) {
|
||||
// invoke `ar`
|
||||
// example:
|
||||
// # static link into libfoo.a
|
||||
// ar rcs libfoo.a foo1.o foo2.o
|
||||
zig_panic("TODO invoke ar");
|
||||
return;
|
||||
fprintf(stderr, "Zig does not yet support creating static libraries\nSee https://github.com/ziglang/zig/issues/1493\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
lj.link_in_crt = (g->libc_link_lib != nullptr && g->out_type == OutTypeExe);
|
||||
@ -1017,6 +979,4 @@ void codegen_link(CodeGen *g, const char *out_file) {
|
||||
fprintf(stderr, "%s\n", buf_ptr(&diag));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
codegen_add_time_event(g, "Done");
|
||||
}
|
||||
|
||||
17
src/link.hpp
17
src/link.hpp
@ -1,17 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Andrew Kelley
|
||||
*
|
||||
* This file is part of zig, which is MIT licensed.
|
||||
* See http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#ifndef ZIG_LINK_HPP
|
||||
#define ZIG_LINK_HPP
|
||||
|
||||
#include "all_types.hpp"
|
||||
|
||||
void codegen_link(CodeGen *g, const char *out_file);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
64
src/main.cpp
64
src/main.cpp
@ -10,7 +10,6 @@
|
||||
#include "codegen.hpp"
|
||||
#include "config.h"
|
||||
#include "error.hpp"
|
||||
#include "link.hpp"
|
||||
#include "os.hpp"
|
||||
#include "target.hpp"
|
||||
#include "cache_hash.hpp"
|
||||
@ -385,8 +384,7 @@ int main(int argc, char **argv) {
|
||||
CliPkg *cur_pkg = allocate<CliPkg>(1);
|
||||
BuildMode build_mode = BuildModeDebug;
|
||||
ZigList<const char *> test_exec_args = {0};
|
||||
int comptime_args_end = 0;
|
||||
int runtime_args_start = argc;
|
||||
int runtime_args_start = -1;
|
||||
bool no_rosegment_workaround = false;
|
||||
|
||||
if (argc >= 2 && strcmp(argv[1], "build") == 0) {
|
||||
@ -454,8 +452,6 @@ int main(int argc, char **argv) {
|
||||
full_cache_dir = os_path_resolve(&cache_dir_buf, 1);
|
||||
}
|
||||
|
||||
Buf *path_to_build_exe = buf_alloc();
|
||||
os_path_join(&full_cache_dir, buf_create_from_str("build"), path_to_build_exe);
|
||||
codegen_set_cache_dir(g, full_cache_dir);
|
||||
|
||||
args.items[1] = buf_ptr(&build_file_dirname);
|
||||
@ -525,14 +521,13 @@ int main(int argc, char **argv) {
|
||||
PackageTableEntry *build_pkg = codegen_create_package(g, buf_ptr(&build_file_dirname),
|
||||
buf_ptr(&build_file_basename));
|
||||
g->root_package->package_table.put(buf_create_from_str("@build"), build_pkg);
|
||||
codegen_build(g);
|
||||
codegen_link(g, buf_ptr(path_to_build_exe));
|
||||
codegen_build_and_link(g);
|
||||
|
||||
Termination term;
|
||||
os_spawn_process(buf_ptr(path_to_build_exe), args, &term);
|
||||
os_spawn_process(buf_ptr(&g->output_file_path), args, &term);
|
||||
if (term.how != TerminationIdClean || term.code != 0) {
|
||||
fprintf(stderr, "\nBuild failed. The following command failed:\n");
|
||||
fprintf(stderr, "%s", buf_ptr(path_to_build_exe));
|
||||
fprintf(stderr, "%s", buf_ptr(&g->output_file_path));
|
||||
for (size_t i = 0; i < args.length; i += 1) {
|
||||
fprintf(stderr, " %s", args.at(i));
|
||||
}
|
||||
@ -541,15 +536,11 @@ int main(int argc, char **argv) {
|
||||
return (term.how == TerminationIdClean) ? term.code : -1;
|
||||
}
|
||||
|
||||
for (int i = 1; i < argc; i += 1, comptime_args_end += 1) {
|
||||
for (int i = 1; i < argc; i += 1) {
|
||||
char *arg = argv[i];
|
||||
|
||||
if (arg[0] == '-') {
|
||||
if (strcmp(arg, "--") == 0) {
|
||||
// ignore -- from both compile and runtime arg sets
|
||||
runtime_args_start = i + 1;
|
||||
break;
|
||||
} else if (strcmp(arg, "--release-fast") == 0) {
|
||||
if (strcmp(arg, "--release-fast") == 0) {
|
||||
build_mode = BuildModeFastRelease;
|
||||
} else if (strcmp(arg, "--release-safe") == 0) {
|
||||
build_mode = BuildModeSafeRelease;
|
||||
@ -746,6 +737,10 @@ int main(int argc, char **argv) {
|
||||
case CmdTest:
|
||||
if (!in_file) {
|
||||
in_file = arg;
|
||||
if (cmd == CmdRun) {
|
||||
runtime_args_start = i + 1;
|
||||
break; // rest of the args are for the program
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Unexpected extra parameter: %s\n", arg);
|
||||
return usage(arg0);
|
||||
@ -856,19 +851,10 @@ int main(int argc, char **argv) {
|
||||
Buf *zig_root_source_file = (cmd == CmdTranslateC) ? nullptr : in_file_buf;
|
||||
|
||||
Buf full_cache_dir = BUF_INIT;
|
||||
Buf *run_exec_path = buf_alloc();
|
||||
if (cmd == CmdRun) {
|
||||
if (buf_out_name == nullptr) {
|
||||
buf_out_name = buf_create_from_str("run");
|
||||
}
|
||||
|
||||
Buf *global_cache_dir = buf_alloc();
|
||||
os_get_global_cache_directory(global_cache_dir);
|
||||
os_path_join(global_cache_dir, buf_out_name, run_exec_path);
|
||||
full_cache_dir = os_path_resolve(&global_cache_dir, 1);
|
||||
|
||||
out_file = buf_ptr(run_exec_path);
|
||||
} else {
|
||||
if (cmd == CmdRun && buf_out_name == nullptr) {
|
||||
buf_out_name = buf_create_from_str("run");
|
||||
}
|
||||
{
|
||||
Buf *resolve_paths = buf_create_from_str((cache_dir == nullptr) ? default_zig_cache_name : cache_dir);
|
||||
full_cache_dir = os_path_resolve(&resolve_paths, 1);
|
||||
}
|
||||
@ -957,6 +943,8 @@ int main(int argc, char **argv) {
|
||||
codegen_set_test_name_prefix(g, buf_create_from_str(test_name_prefix));
|
||||
}
|
||||
|
||||
if (out_file)
|
||||
codegen_set_output_path(g, buf_create_from_str(out_file));
|
||||
if (out_file_h)
|
||||
codegen_set_output_h_path(g, buf_create_from_str(out_file_h));
|
||||
|
||||
@ -976,8 +964,7 @@ int main(int argc, char **argv) {
|
||||
if (cmd == CmdBuild || cmd == CmdRun) {
|
||||
codegen_set_emit_file_type(g, emit_file_type);
|
||||
|
||||
codegen_build(g);
|
||||
codegen_link(g, out_file);
|
||||
codegen_build_and_link(g);
|
||||
if (timing_info)
|
||||
codegen_print_timing_report(g, stdout);
|
||||
|
||||
@ -987,8 +974,14 @@ int main(int argc, char **argv) {
|
||||
args.append(argv[i]);
|
||||
}
|
||||
|
||||
const char *exec_path = buf_ptr(&g->output_file_path);
|
||||
args.append(nullptr);
|
||||
|
||||
os_execv(exec_path, args.items);
|
||||
|
||||
args.pop();
|
||||
Termination term;
|
||||
os_spawn_process(buf_ptr(run_exec_path), args, &term);
|
||||
os_spawn_process(exec_path, args, &term);
|
||||
return term.code;
|
||||
}
|
||||
|
||||
@ -1005,11 +998,8 @@ int main(int argc, char **argv) {
|
||||
ZigTarget native;
|
||||
get_native_target(&native);
|
||||
|
||||
ZigTarget *non_null_target = target ? target : &native;
|
||||
|
||||
Buf *test_exe_name = buf_sprintf("test%s", target_exe_file_ext(non_null_target));
|
||||
Buf *test_exe_path = buf_alloc();
|
||||
os_path_join(&full_cache_dir, test_exe_name, test_exe_path);
|
||||
codegen_build_and_link(g);
|
||||
Buf *test_exe_path = &g->output_file_path;
|
||||
|
||||
for (size_t i = 0; i < test_exec_args.length; i += 1) {
|
||||
if (test_exec_args.items[i] == nullptr) {
|
||||
@ -1017,8 +1007,6 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
}
|
||||
|
||||
codegen_build(g);
|
||||
codegen_link(g, buf_ptr(test_exe_path));
|
||||
|
||||
if (!target_can_exec(&native, target)) {
|
||||
fprintf(stderr, "Created %s but skipping execution because it is non-native.\n",
|
||||
|
||||
54
src/os.cpp
54
src/os.cpp
@ -972,6 +972,22 @@ static int os_exec_process_windows(const char *exe, ZigList<const char *> &args,
|
||||
}
|
||||
#endif
|
||||
|
||||
Error os_execv(const char *exe, const char **argv) {
|
||||
#if defined(ZIG_OS_WINDOWS)
|
||||
return ErrorUnsupportedOperatingSystem;
|
||||
#else
|
||||
execv(exe, (char *const *)argv);
|
||||
switch (errno) {
|
||||
case ENOMEM:
|
||||
return ErrorSystemResources;
|
||||
case EIO:
|
||||
return ErrorFileSystem;
|
||||
default:
|
||||
return ErrorUnexpected;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int os_exec_process(const char *exe, ZigList<const char *> &args,
|
||||
Termination *term, Buf *out_stderr, Buf *out_stdout)
|
||||
{
|
||||
@ -1238,44 +1254,6 @@ int os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(ZIG_OS_POSIX)
|
||||
int os_get_global_cache_directory(Buf *out_tmp_path) {
|
||||
const char *tmp_dir = getenv("TMPDIR");
|
||||
if (!tmp_dir) {
|
||||
tmp_dir = P_tmpdir;
|
||||
}
|
||||
|
||||
Buf *tmp_dir_buf = buf_create_from_str(tmp_dir);
|
||||
Buf *cache_dirname_buf = buf_create_from_str("zig-cache");
|
||||
|
||||
buf_resize(out_tmp_path, 0);
|
||||
os_path_join(tmp_dir_buf, cache_dirname_buf, out_tmp_path);
|
||||
|
||||
buf_deinit(tmp_dir_buf);
|
||||
buf_deinit(cache_dirname_buf);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ZIG_OS_WINDOWS)
|
||||
int os_get_global_cache_directory(Buf *out_tmp_path) {
|
||||
char tmp_dir[MAX_PATH + 1];
|
||||
if (GetTempPath(MAX_PATH, tmp_dir) == 0) {
|
||||
zig_panic("GetTempPath failed");
|
||||
}
|
||||
|
||||
Buf *tmp_dir_buf = buf_create_from_str(tmp_dir);
|
||||
Buf *cache_dirname_buf = buf_create_from_str("zig-cache");
|
||||
|
||||
buf_resize(out_tmp_path, 0);
|
||||
os_path_join(tmp_dir_buf, cache_dirname_buf, out_tmp_path);
|
||||
|
||||
buf_deinit(tmp_dir_buf);
|
||||
buf_deinit(cache_dirname_buf);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int os_delete_file(Buf *path) {
|
||||
if (remove(buf_ptr(path))) {
|
||||
return ErrorFileSystem;
|
||||
|
||||
@ -87,6 +87,7 @@ int os_init(void);
|
||||
void os_spawn_process(const char *exe, ZigList<const char *> &args, Termination *term);
|
||||
int os_exec_process(const char *exe, ZigList<const char *> &args,
|
||||
Termination *term, Buf *out_stderr, Buf *out_stdout);
|
||||
Error os_execv(const char *exe, const char **argv);
|
||||
|
||||
void os_path_dirname(Buf *full_path, Buf *out_dirname);
|
||||
void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename);
|
||||
@ -96,8 +97,6 @@ int os_path_real(Buf *rel_path, Buf *out_abs_path);
|
||||
Buf os_path_resolve(Buf **paths_ptr, size_t paths_len);
|
||||
bool os_path_is_absolute(Buf *path);
|
||||
|
||||
int os_get_global_cache_directory(Buf *out_tmp_path);
|
||||
|
||||
Error ATTRIBUTE_MUST_USE os_make_path(Buf *path);
|
||||
Error ATTRIBUTE_MUST_USE os_make_dir(Buf *path);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user