| author | |
| committer | |
| log | 91955dee587214722daa09e6f3dbff059ac3752e |
| tree | 7f56bf31f93081c63a4bcf03b9e38b7c5b1ca29c |
| parent | 1e634a384ccc0ae57e0343369f7adb0b1b4b9875 |
| signature | Commit is signed but in an unrecognized format. |
* in Zig build scripts, getOutputPath() is no longer a valid function
to call, unless setOutputDir() was used, or within a custom make()
function. Instead there is more convenient API to use which takes
advantage of the caching system. Search this commit diff for
`exe.run()` for an example.
* Zig build by default enables caching. All build artifacts will go
into zig-cache. If you want to access build artifacts in a convenient
location, it is recommended to add an `install` step. Otherwise
you can use the `run()` API mentioned above to execute programs
directly from their location in the cache. Closes #330.
`addSystemCommand` is available for programs not built with Zig
build.
* Please note that Zig does no cache evicting yet. You may have to
manually delete zig-cache directories periodically to keep disk
usage down. It's planned for this to be a simple Least Recently
Used eviction system eventually.
* `--output`, `--output-lib`, and `--output-h` are removed. Instead,
use `--output-dir` which defaults to the current working directory.
Or take advantage of `--cache on`, which will print the main output
path to stdout, and the other artifacts will be in the same directory
with predictable file names. `--disable-gen-h` is available when
one wants to prevent .h file generation.
* `@cImport` is always independently cached now. Closes #2015.
It always writes the generated Zig code to disk which makes debug
info and compile errors better. No more "TODO: remember C source
location to display here"
* Fix .d file parsing. (Fixes the MacOS CI failure)
* Zig no longer creates "temporary files" other than inside a
zig-cache directory.
This breaks the CLI API that Godbolt uses. The suggested new invocation
can be found in this commit diff, in the changes to `test/cli.zig`.26 files changed, 691 insertions(+), 661 deletions(-)
build.zig+2-2| ... | ... | @@ -20,8 +20,8 @@ pub fn build(b: *Builder) !void { |
| 20 | 20 | b.allocator, |
| 21 | 21 | [][]const u8{ b.cache_root, "langref.html" }, |
| 22 | 22 | ) catch unreachable; |
| 23 | var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8{ | |
| 24 | docgen_exe.getOutputPath(), | |
| 23 | var docgen_cmd = docgen_exe.run(); | |
| 24 | docgen_cmd.addArgs([][]const u8{ | |
| 25 | 25 | rel_zig_exe, |
| 26 | 26 | "doc" ++ os.path.sep_str ++ "langref.html.in", |
| 27 | 27 | langref_out_path, |
doc/langref.html.in+1-2| ... | ... | @@ -7914,8 +7914,7 @@ pub fn build(b: *Builder) void { |
| 7914 | 7914 | |
| 7915 | 7915 | b.default_step.dependOn(&exe.step); |
| 7916 | 7916 | |
| 7917 | const run_cmd = b.addCommand(".", b.env_map, [][]const u8{exe.getOutputPath()}); | |
| 7918 | run_cmd.step.dependOn(&exe.step); | |
| 7917 | const run_cmd = exe.run(); | |
| 7919 | 7918 | |
| 7920 | 7919 | const test_step = b.step("test", "Test the program"); |
| 7921 | 7920 | test_step.dependOn(&run_cmd.step); |
example/mix_o_files/build.zig+2-3| ... | ... | @@ -4,14 +4,13 @@ pub fn build(b: *Builder) void { |
| 4 | 4 | const obj = b.addObject("base64", "base64.zig"); |
| 5 | 5 | |
| 6 | 6 | const exe = b.addExecutable("test", null); |
| 7 | exe.addCSourceFile("test.c",[][]const u8{"-std=c99"}); | |
| 7 | exe.addCSourceFile("test.c", [][]const u8{"-std=c99"}); | |
| 8 | 8 | exe.addObject(obj); |
| 9 | 9 | exe.linkSystemLibrary("c"); |
| 10 | 10 | |
| 11 | 11 | b.default_step.dependOn(&exe.step); |
| 12 | 12 | |
| 13 | const run_cmd = b.addCommand(".", b.env_map, [][]const u8{exe.getOutputPath()}); | |
| 14 | run_cmd.step.dependOn(&exe.step); | |
| 13 | const run_cmd = exe.run(); | |
| 15 | 14 | |
| 16 | 15 | const test_step = b.step("test", "Test the program"); |
| 17 | 16 | test_step.dependOn(&run_cmd.step); |
example/shared_library/build.zig+1-2| ... | ... | @@ -10,8 +10,7 @@ pub fn build(b: *Builder) void { |
| 10 | 10 | |
| 11 | 11 | b.default_step.dependOn(&exe.step); |
| 12 | 12 | |
| 13 | const run_cmd = b.addCommand(".", b.env_map, [][]const u8{exe.getOutputPath()}); | |
| 14 | run_cmd.step.dependOn(&exe.step); | |
| 13 | const run_cmd = exe.run(); | |
| 15 | 14 | |
| 16 | 15 | const test_step = b.step("test", "Test the program"); |
| 17 | 16 | test_step.dependOn(&run_cmd.step); |
src/all_types.hpp+5-6| ... | ... | @@ -1087,7 +1087,6 @@ struct RootStruct { |
| 1087 | 1087 | Buf *path; // relative to root_package->root_src_dir |
| 1088 | 1088 | ZigList<size_t> *line_offsets; |
| 1089 | 1089 | Buf *source_code; |
| 1090 | AstNode *c_import_node; | |
| 1091 | 1090 | ZigLLVMDIFile *di_file; |
| 1092 | 1091 | }; |
| 1093 | 1092 | |
| ... | ... | @@ -1746,13 +1745,12 @@ struct CodeGen { |
| 1746 | 1745 | |
| 1747 | 1746 | Buf triple_str; |
| 1748 | 1747 | Buf global_asm; |
| 1749 | Buf *out_h_path; | |
| 1750 | Buf *out_lib_path; | |
| 1751 | Buf artifact_dir; | |
| 1752 | 1748 | Buf output_file_path; |
| 1753 | 1749 | Buf o_file_output_path; |
| 1754 | Buf *wanted_output_file_path; | |
| 1755 | 1750 | Buf *cache_dir; |
| 1751 | // As an input parameter, mutually exclusive with enable_cache. But it gets | |
| 1752 | // populated in codegen_build_and_link. | |
| 1753 | Buf *output_dir; | |
| 1756 | 1754 | Buf **libc_include_dir_list; |
| 1757 | 1755 | size_t libc_include_dir_len; |
| 1758 | 1756 | |
| ... | ... | @@ -1804,7 +1802,7 @@ struct CodeGen { |
| 1804 | 1802 | bool verbose_cc; |
| 1805 | 1803 | bool error_during_imports; |
| 1806 | 1804 | bool generate_error_name_table; |
| 1807 | bool enable_cache; | |
| 1805 | bool enable_cache; // mutually exclusive with output_dir | |
| 1808 | 1806 | bool enable_time_report; |
| 1809 | 1807 | bool system_linker_hack; |
| 1810 | 1808 | bool reported_bad_link_libc_error; |
| ... | ... | @@ -1844,6 +1842,7 @@ struct CodeGen { |
| 1844 | 1842 | bool each_lib_rpath; |
| 1845 | 1843 | bool disable_pic; |
| 1846 | 1844 | bool is_dummy_so; |
| 1845 | bool disable_gen_h; | |
| 1847 | 1846 | |
| 1848 | 1847 | Buf *mmacosx_version_min; |
| 1849 | 1848 | Buf *mios_version_min; |
src/analyze.cpp+3-28| ... | ... | @@ -35,20 +35,6 @@ static bool is_top_level_struct(ZigType *import) { |
| 35 | 35 | static ErrorMsg *add_error_note_token(CodeGen *g, ErrorMsg *parent_msg, ZigType *owner, Token *token, Buf *msg) { |
| 36 | 36 | assert(is_top_level_struct(owner)); |
| 37 | 37 | RootStruct *root_struct = owner->data.structure.root_struct; |
| 38 | if (root_struct->c_import_node != nullptr) { | |
| 39 | // if this happens, then translate_c generated code that | |
| 40 | // failed semantic analysis, which isn't supposed to happen | |
| 41 | ||
| 42 | Buf *note_path = buf_create_from_str("?.c"); | |
| 43 | Buf *note_source = buf_create_from_str("TODO: remember C source location to display here "); | |
| 44 | ZigList<size_t> note_line_offsets = {0}; | |
| 45 | note_line_offsets.append(0); | |
| 46 | ErrorMsg *note = err_msg_create_with_line(note_path, 0, 0, | |
| 47 | note_source, &note_line_offsets, msg); | |
| 48 | ||
| 49 | err_msg_add_note(parent_msg, note); | |
| 50 | return note; | |
| 51 | } | |
| 52 | 38 | |
| 53 | 39 | ErrorMsg *err = err_msg_create_with_line(root_struct->path, token->start_line, token->start_column, |
| 54 | 40 | root_struct->source_code, root_struct->line_offsets, msg); |
| ... | ... | @@ -60,17 +46,6 @@ static ErrorMsg *add_error_note_token(CodeGen *g, ErrorMsg *parent_msg, ZigType |
| 60 | 46 | ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, Token *token, Buf *msg) { |
| 61 | 47 | assert(is_top_level_struct(owner)); |
| 62 | 48 | RootStruct *root_struct = owner->data.structure.root_struct; |
| 63 | if (root_struct->c_import_node != nullptr) { | |
| 64 | // if this happens, then translate_c generated code that | |
| 65 | // failed semantic analysis, which isn't supposed to happen | |
| 66 | ErrorMsg *err = add_node_error(g, root_struct->c_import_node, | |
| 67 | buf_sprintf("compiler bug: @cImport generated invalid zig code")); | |
| 68 | ||
| 69 | add_error_note_token(g, err, owner, token, msg); | |
| 70 | ||
| 71 | g->errors.append(err); | |
| 72 | return err; | |
| 73 | } | |
| 74 | 49 | ErrorMsg *err = err_msg_create_with_line(root_struct->path, token->start_line, token->start_column, |
| 75 | 50 | root_struct->source_code, root_struct->line_offsets, msg); |
| 76 | 51 | |
| ... | ... | @@ -1300,7 +1275,7 @@ static ZigTypeId container_to_type(ContainerKind kind) { |
| 1300 | 1275 | } |
| 1301 | 1276 | |
| 1302 | 1277 | // This is like get_partial_container_type except it's for the implicit root struct of files. |
| 1303 | ZigType *get_root_container_type(CodeGen *g, const char *full_name, Buf *bare_name, | |
| 1278 | static ZigType *get_root_container_type(CodeGen *g, const char *full_name, Buf *bare_name, | |
| 1304 | 1279 | RootStruct *root_struct) |
| 1305 | 1280 | { |
| 1306 | 1281 | ZigType *entry = new_type_table_entry(ZigTypeIdStruct); |
| ... | ... | @@ -4503,11 +4478,11 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu |
| 4503 | 4478 | Buf *pkg_root_src_dir = &package->root_src_dir; |
| 4504 | 4479 | Buf resolved_root_src_dir = os_path_resolve(&pkg_root_src_dir, 1); |
| 4505 | 4480 | |
| 4506 | assert(buf_starts_with_buf(resolved_path, &resolved_root_src_dir)); | |
| 4507 | ||
| 4508 | 4481 | Buf namespace_name = BUF_INIT; |
| 4509 | 4482 | buf_init_from_buf(&namespace_name, &package->pkg_path); |
| 4510 | 4483 | if (source_kind == SourceKindNonRoot) { |
| 4484 | assert(buf_starts_with_buf(resolved_path, &resolved_root_src_dir)); | |
| 4485 | ||
| 4511 | 4486 | if (buf_len(&namespace_name) != 0) buf_append_char(&namespace_name, NAMESPACE_SEP_CHAR); |
| 4512 | 4487 | buf_append_mem(&namespace_name, buf_ptr(&noextname) + buf_len(&resolved_root_src_dir) + 1, |
| 4513 | 4488 | buf_len(&noextname) - (buf_len(&resolved_root_src_dir) + 1)); |
src/analyze.hpp+3-2| ... | ... | @@ -31,8 +31,6 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size); |
| 31 | 31 | ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type); |
| 32 | 32 | ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind, |
| 33 | 33 | AstNode *decl_node, const char *full_name, Buf *bare_name, ContainerLayout layout); |
| 34 | ZigType *get_root_container_type(CodeGen *g, const char *full_name, Buf *bare_name, | |
| 35 | RootStruct *root_struct); | |
| 36 | 34 | ZigType *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x); |
| 37 | 35 | ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payload_type); |
| 38 | 36 | ZigType *get_bound_fn_type(CodeGen *g, ZigFn *fn_entry); |
| ... | ... | @@ -53,6 +51,7 @@ enum SourceKind { |
| 53 | 51 | SourceKindRoot, |
| 54 | 52 | SourceKindPkgMain, |
| 55 | 53 | SourceKindNonRoot, |
| 54 | SourceKindCImport, | |
| 56 | 55 | }; |
| 57 | 56 | ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *abs_full_path, Buf *source_code, |
| 58 | 57 | SourceKind source_kind); |
| ... | ... | @@ -242,4 +241,6 @@ Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_no |
| 242 | 241 | void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn); |
| 243 | 242 | Buf *type_bare_name(ZigType *t); |
| 244 | 243 | Buf *type_h_name(ZigType *t); |
| 244 | Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose); | |
| 245 | ||
| 245 | 246 | #endif |
src/ast_render.cpp+3| ... | ... | @@ -470,6 +470,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 470 | 470 | fprintf(ar->f, ", "); |
| 471 | 471 | } |
| 472 | 472 | } |
| 473 | if (node->data.fn_proto.is_var_args) { | |
| 474 | fprintf(ar->f, ", ..."); | |
| 475 | } | |
| 473 | 476 | fprintf(ar->f, ")"); |
| 474 | 477 | if (node->data.fn_proto.align_expr) { |
| 475 | 478 | fprintf(ar->f, " align("); |
src/cache_hash.cpp+29-20| ... | ... | @@ -19,6 +19,8 @@ void cache_init(CacheHash *ch, Buf *manifest_dir) { |
| 19 | 19 | ch->manifest_dir = manifest_dir; |
| 20 | 20 | ch->manifest_file_path = nullptr; |
| 21 | 21 | ch->manifest_dirty = false; |
| 22 | ch->force_check_manifest = false; | |
| 23 | ch->b64_digest = BUF_INIT; | |
| 22 | 24 | } |
| 23 | 25 | |
| 24 | 26 | void cache_str(CacheHash *ch, const char *ptr) { |
| ... | ... | @@ -243,22 +245,21 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) { |
| 243 | 245 | int rc = blake2b_final(&ch->blake, bin_digest, 48); |
| 244 | 246 | assert(rc == 0); |
| 245 | 247 | |
| 246 | if (ch->files.length == 0) { | |
| 248 | buf_resize(&ch->b64_digest, 64); | |
| 249 | base64_encode(buf_to_slice(&ch->b64_digest), {bin_digest, 48}); | |
| 250 | ||
| 251 | if (ch->files.length == 0 && !ch->force_check_manifest) { | |
| 247 | 252 | buf_resize(out_digest, 64); |
| 248 | 253 | base64_encode(buf_to_slice(out_digest), {bin_digest, 48}); |
| 249 | 254 | return ErrorNone; |
| 250 | 255 | } |
| 251 | 256 | |
| 252 | Buf b64_digest = BUF_INIT; | |
| 253 | buf_resize(&b64_digest, 64); | |
| 254 | base64_encode(buf_to_slice(&b64_digest), {bin_digest, 48}); | |
| 255 | ||
| 256 | 257 | rc = blake2b_init(&ch->blake, 48); |
| 257 | 258 | assert(rc == 0); |
| 258 | 259 | blake2b_update(&ch->blake, bin_digest, 48); |
| 259 | 260 | |
| 260 | 261 | ch->manifest_file_path = buf_alloc(); |
| 261 | os_path_join(ch->manifest_dir, &b64_digest, ch->manifest_file_path); | |
| 262 | os_path_join(ch->manifest_dir, &ch->b64_digest, ch->manifest_file_path); | |
| 262 | 263 | |
| 263 | 264 | buf_append_str(ch->manifest_file_path, ".txt"); |
| 264 | 265 | |
| ... | ... | @@ -380,7 +381,7 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) { |
| 380 | 381 | blake2b_update(&ch->blake, chf->bin_digest, 48); |
| 381 | 382 | } |
| 382 | 383 | } |
| 383 | if (file_i < input_file_count) { | |
| 384 | if (file_i < input_file_count || file_i == 0) { | |
| 384 | 385 | // manifest file is empty or missing entries, so this is a cache miss |
| 385 | 386 | ch->manifest_dirty = true; |
| 386 | 387 | for (; file_i < input_file_count; file_i += 1) { |
| ... | ... | @@ -442,6 +443,7 @@ Error cache_add_dep_file(CacheHash *ch, Buf *dep_file_path, bool verbose) { |
| 442 | 443 | } |
| 443 | 444 | if (opt_line.value.len == 0) |
| 444 | 445 | continue; |
| 446 | ||
| 445 | 447 | if (opt_line.value.ptr[0] == '"') { |
| 446 | 448 | if (opt_line.value.len < 2) { |
| 447 | 449 | if (verbose) { |
| ... | ... | @@ -460,21 +462,28 @@ Error cache_add_dep_file(CacheHash *ch, Buf *dep_file_path, bool verbose) { |
| 460 | 462 | } |
| 461 | 463 | return ErrorInvalidDepFile; |
| 462 | 464 | } |
| 463 | } else { | |
| 464 | if (opt_line.value.ptr[opt_line.value.len - 1] == '\\') { | |
| 465 | opt_line.value.len -= 2; // cut off ` \` | |
| 465 | Buf *filename_buf = buf_create_from_slice(opt_line.value); | |
| 466 | if ((err = cache_add_file(ch, filename_buf))) { | |
| 467 | if (verbose) { | |
| 468 | fprintf(stderr, "unable to add %s to cache: %s\n", buf_ptr(filename_buf), err_str(err)); | |
| 469 | fprintf(stderr, "when processing .d file: %s\n", buf_ptr(dep_file_path)); | |
| 470 | } | |
| 471 | return err; | |
| 466 | 472 | } |
| 467 | if (opt_line.value.len == 0) | |
| 468 | continue; | |
| 469 | } | |
| 470 | ||
| 471 | Buf *filename_buf = buf_create_from_slice(opt_line.value); | |
| 472 | if ((err = cache_add_file(ch, filename_buf))) { | |
| 473 | if (verbose) { | |
| 474 | fprintf(stderr, "unable to add %s to cache: %s\n", buf_ptr(filename_buf), err_str(err)); | |
| 475 | fprintf(stderr, "when processing .d file: %s\n", buf_ptr(dep_file_path)); | |
| 473 | } else { | |
| 474 | // sometimes there are multiple files on the same line; we actually need space tokenization. | |
| 475 | SplitIterator line_it = memSplit(opt_line.value, str(" \t\\")); | |
| 476 | Slice<uint8_t> filename; | |
| 477 | while (SplitIterator_next(&line_it).unwrap(&filename)) { | |
| 478 | Buf *filename_buf = buf_create_from_slice(filename); | |
| 479 | if ((err = cache_add_file(ch, filename_buf))) { | |
| 480 | if (verbose) { | |
| 481 | fprintf(stderr, "unable to add %s to cache: %s\n", buf_ptr(filename_buf), err_str(err)); | |
| 482 | fprintf(stderr, "when processing .d file: %s\n", buf_ptr(dep_file_path)); | |
| 483 | } | |
| 484 | return err; | |
| 485 | } | |
| 476 | 486 | } |
| 477 | return err; | |
| 478 | 487 | } |
| 479 | 488 | } |
| 480 | 489 | return ErrorNone; |
src/cache_hash.hpp+6| ... | ... | @@ -25,8 +25,10 @@ struct CacheHash { |
| 25 | 25 | ZigList<CacheHashFile> files; |
| 26 | 26 | Buf *manifest_dir; |
| 27 | 27 | Buf *manifest_file_path; |
| 28 | Buf b64_digest; | |
| 28 | 29 | OsFile manifest_file; |
| 29 | 30 | bool manifest_dirty; |
| 31 | bool force_check_manifest; | |
| 30 | 32 | }; |
| 31 | 33 | |
| 32 | 34 | // Always call this first to set up. |
| ... | ... | @@ -51,6 +53,10 @@ void cache_file_opt(CacheHash *ch, Buf *path); |
| 51 | 53 | // If you got a cache hit, the next step is cache_release. |
| 52 | 54 | // From this point on, there is a lock on the input params. Release |
| 53 | 55 | // the lock with cache_release. |
| 56 | // Set force_check_manifest if you plan to add files later, but have not | |
| 57 | // added any files before calling cache_hit. CacheHash::b64_digest becomes | |
| 58 | // available for use after this call, even in the case of a miss, and it | |
| 59 | // is a hash of the input parameters only. | |
| 54 | 60 | Error ATTRIBUTE_MUST_USE cache_hit(CacheHash *ch, Buf *out_b64_digest); |
| 55 | 61 | |
| 56 | 62 | // If you did not get a cache hit, call this function for every file |
src/codegen.cpp+119-130| ... | ... | @@ -23,6 +23,9 @@ |
| 23 | 23 | #include <stdio.h> |
| 24 | 24 | #include <errno.h> |
| 25 | 25 | |
| 26 | #define CACHE_OUT_SUBDIR "o" | |
| 27 | #define CACHE_HASH_SUBDIR "h" | |
| 28 | ||
| 26 | 29 | static void init_darwin_native(CodeGen *g) { |
| 27 | 30 | char *osx_target = getenv("MACOSX_DEPLOYMENT_TARGET"); |
| 28 | 31 | char *ios_target = getenv("IPHONEOS_DEPLOYMENT_TARGET"); |
| ... | ... | @@ -196,18 +199,6 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget |
| 196 | 199 | return g; |
| 197 | 200 | } |
| 198 | 201 | |
| 199 | void codegen_set_output_h_path(CodeGen *g, Buf *h_path) { | |
| 200 | g->out_h_path = h_path; | |
| 201 | } | |
| 202 | ||
| 203 | void codegen_set_output_lib_path(CodeGen *g, Buf *lib_path) { | |
| 204 | g->out_lib_path = lib_path; | |
| 205 | } | |
| 206 | ||
| 207 | void codegen_set_output_path(CodeGen *g, Buf *path) { | |
| 208 | g->wanted_output_file_path = path; | |
| 209 | } | |
| 210 | ||
| 211 | 202 | void codegen_set_clang_argv(CodeGen *g, const char **args, size_t len) { |
| 212 | 203 | g->clang_argv = args; |
| 213 | 204 | g->clang_argv_len = len; |
| ... | ... | @@ -256,10 +247,6 @@ void codegen_set_out_name(CodeGen *g, Buf *out_name) { |
| 256 | 247 | g->root_out_name = out_name; |
| 257 | 248 | } |
| 258 | 249 | |
| 259 | void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker_path) { | |
| 260 | g->dynamic_linker_path = dynamic_linker_path; | |
| 261 | } | |
| 262 | ||
| 263 | 250 | void codegen_add_lib_dir(CodeGen *g, const char *dir) { |
| 264 | 251 | g->lib_dirs.append(dir); |
| 265 | 252 | } |
| ... | ... | @@ -7766,7 +7753,10 @@ static Error define_builtin_compile_vars(CodeGen *g) { |
| 7766 | 7753 | } |
| 7767 | 7754 | } else { |
| 7768 | 7755 | contents = codegen_generate_builtin_source(g); |
| 7769 | os_write_file(builtin_zig_path, contents); | |
| 7756 | if ((err = os_write_file(builtin_zig_path, contents))) { | |
| 7757 | fprintf(stderr, "Unable to write file '%s': %s\n", buf_ptr(builtin_zig_path), err_str(err)); | |
| 7758 | exit(1); | |
| 7759 | } | |
| 7770 | 7760 | } |
| 7771 | 7761 | |
| 7772 | 7762 | assert(g->root_package); |
| ... | ... | @@ -8030,7 +8020,7 @@ static void detect_libc(CodeGen *g) { |
| 8030 | 8020 | } |
| 8031 | 8021 | } |
| 8032 | 8022 | |
| 8033 | void codegen_translate_c(CodeGen *g, Buf *full_path) { | |
| 8023 | AstNode *codegen_translate_c(CodeGen *g, Buf *full_path) { | |
| 8034 | 8024 | Buf *src_basename = buf_alloc(); |
| 8035 | 8025 | Buf *src_dirname = buf_alloc(); |
| 8036 | 8026 | os_path_split(full_path, src_dirname, src_basename); |
| ... | ... | @@ -8042,16 +8032,9 @@ void codegen_translate_c(CodeGen *g, Buf *full_path) { |
| 8042 | 8032 | |
| 8043 | 8033 | init(g); |
| 8044 | 8034 | |
| 8045 | RootStruct *root_struct = allocate<RootStruct>(1); | |
| 8046 | root_struct->source_code = nullptr; | |
| 8047 | root_struct->path = full_path; | |
| 8048 | root_struct->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname)); | |
| 8049 | ||
| 8050 | ZigType *import = get_root_container_type(g, buf_ptr(&noextname), &noextname, root_struct); | |
| 8051 | g->root_import = import; | |
| 8052 | ||
| 8053 | 8035 | ZigList<ErrorMsg *> errors = {0}; |
| 8054 | Error err = parse_h_file(import, &errors, buf_ptr(full_path), g, nullptr); | |
| 8036 | AstNode *root_node; | |
| 8037 | Error err = parse_h_file(&root_node, &errors, buf_ptr(full_path), g, nullptr); | |
| 8055 | 8038 | |
| 8056 | 8039 | if (err == ErrorCCompileErrors && errors.length > 0) { |
| 8057 | 8040 | for (size_t i = 0; i < errors.length; i += 1) { |
| ... | ... | @@ -8065,6 +8048,8 @@ void codegen_translate_c(CodeGen *g, Buf *full_path) { |
| 8065 | 8048 | fprintf(stderr, "unable to parse C file: %s\n", err_str(err)); |
| 8066 | 8049 | exit(1); |
| 8067 | 8050 | } |
| 8051 | ||
| 8052 | return root_node; | |
| 8068 | 8053 | } |
| 8069 | 8054 | |
| 8070 | 8055 | static ZigType *add_special_code(CodeGen *g, ZigPackage *package, const char *basename) { |
| ... | ... | @@ -8282,32 +8267,18 @@ static Error get_tmp_filename(CodeGen *g, Buf *out, Buf *suffix) { |
| 8282 | 8267 | return ErrorNone; |
| 8283 | 8268 | } |
| 8284 | 8269 | |
| 8285 | // returns true if it was a cache miss | |
| 8286 | static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) { | |
| 8270 | Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose) { | |
| 8287 | 8271 | Error err; |
| 8288 | ||
| 8289 | Buf *artifact_dir; | |
| 8290 | Buf *o_final_path; | |
| 8291 | ||
| 8292 | Buf *o_dir = buf_alloc(); | |
| 8293 | os_path_join(g->cache_dir, buf_create_from_str("o"), o_dir); | |
| 8294 | ||
| 8295 | Buf *c_source_file = buf_create_from_str(c_file->source_path); | |
| 8296 | Buf *c_source_basename = buf_alloc(); | |
| 8297 | os_path_split(c_source_file, nullptr, c_source_basename); | |
| 8298 | Buf *final_o_basename = buf_alloc(); | |
| 8299 | os_path_extname(c_source_basename, final_o_basename, nullptr); | |
| 8300 | buf_append_str(final_o_basename, target_o_file_ext(g->zig_target)); | |
| 8301 | ||
| 8302 | 8272 | CacheHash *cache_hash = allocate<CacheHash>(1); |
| 8303 | Buf *manifest_dir = buf_alloc(); | |
| 8304 | os_path_join(g->cache_dir, buf_create_from_str("c"), manifest_dir); | |
| 8273 | Buf *manifest_dir = buf_sprintf("%s" OS_SEP CACHE_HASH_SUBDIR, buf_ptr(g->cache_dir)); | |
| 8305 | 8274 | cache_init(cache_hash, manifest_dir); |
| 8306 | 8275 | |
| 8307 | 8276 | Buf *compiler_id; |
| 8308 | 8277 | if ((err = get_compiler_id(&compiler_id))) { |
| 8309 | fprintf(stderr, "unable to get compiler id: %s\n", err_str(err)); | |
| 8310 | exit(1); | |
| 8278 | if (verbose) { | |
| 8279 | fprintf(stderr, "unable to get compiler id: %s\n", err_str(err)); | |
| 8280 | } | |
| 8281 | return err; | |
| 8311 | 8282 | } |
| 8312 | 8283 | cache_buf(cache_hash, compiler_id); |
| 8313 | 8284 | cache_int(cache_hash, g->err_color); |
| ... | ... | @@ -8321,11 +8292,38 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) { |
| 8321 | 8292 | cache_int(cache_hash, g->zig_target->abi); |
| 8322 | 8293 | cache_bool(cache_hash, g->strip_debug_symbols); |
| 8323 | 8294 | cache_int(cache_hash, g->build_mode); |
| 8324 | cache_file(cache_hash, c_source_file); | |
| 8325 | 8295 | cache_bool(cache_hash, g->disable_pic); |
| 8326 | 8296 | for (size_t arg_i = 0; arg_i < g->clang_argv_len; arg_i += 1) { |
| 8327 | 8297 | cache_str(cache_hash, g->clang_argv[arg_i]); |
| 8328 | 8298 | } |
| 8299 | ||
| 8300 | *out_cache_hash = cache_hash; | |
| 8301 | return ErrorNone; | |
| 8302 | } | |
| 8303 | ||
| 8304 | // returns true if it was a cache miss | |
| 8305 | static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) { | |
| 8306 | Error err; | |
| 8307 | ||
| 8308 | Buf *artifact_dir; | |
| 8309 | Buf *o_final_path; | |
| 8310 | ||
| 8311 | Buf *o_dir = buf_sprintf("%s" OS_SEP CACHE_OUT_SUBDIR, buf_ptr(g->cache_dir)); | |
| 8312 | ||
| 8313 | Buf *c_source_file = buf_create_from_str(c_file->source_path); | |
| 8314 | Buf *c_source_basename = buf_alloc(); | |
| 8315 | os_path_split(c_source_file, nullptr, c_source_basename); | |
| 8316 | Buf *final_o_basename = buf_alloc(); | |
| 8317 | os_path_extname(c_source_basename, final_o_basename, nullptr); | |
| 8318 | buf_append_str(final_o_basename, target_o_file_ext(g->zig_target)); | |
| 8319 | ||
| 8320 | CacheHash *cache_hash; | |
| 8321 | if ((err = create_c_object_cache(g, &cache_hash, true))) { | |
| 8322 | // Already printed error; verbose = true | |
| 8323 | exit(1); | |
| 8324 | } | |
| 8325 | cache_file(cache_hash, c_source_file); | |
| 8326 | ||
| 8329 | 8327 | // Note: not directory args, just args that always have a file next |
| 8330 | 8328 | static const char *file_args[] = { |
| 8331 | 8329 | "-include", |
| ... | ... | @@ -8787,11 +8785,13 @@ static void gen_h_file(CodeGen *g) { |
| 8787 | 8785 | GenH *gen_h = &gen_h_data; |
| 8788 | 8786 | |
| 8789 | 8787 | assert(!g->is_test_build); |
| 8790 | assert(g->out_h_path != nullptr); | |
| 8788 | assert(!g->disable_gen_h); | |
| 8789 | ||
| 8790 | Buf *out_h_path = buf_sprintf("%s" OS_SEP "%s.h", buf_ptr(g->output_dir), buf_ptr(g->root_out_name)); | |
| 8791 | 8791 | |
| 8792 | FILE *out_h = fopen(buf_ptr(g->out_h_path), "wb"); | |
| 8792 | FILE *out_h = fopen(buf_ptr(out_h_path), "wb"); | |
| 8793 | 8793 | if (!out_h) |
| 8794 | zig_panic("unable to open %s: %s\n", buf_ptr(g->out_h_path), strerror(errno)); | |
| 8794 | zig_panic("unable to open %s: %s\n", buf_ptr(out_h_path), strerror(errno)); | |
| 8795 | 8795 | |
| 8796 | 8796 | Buf *export_macro = preprocessor_mangle(buf_sprintf("%s_EXPORT", buf_ptr(g->root_out_name))); |
| 8797 | 8797 | buf_upcase(export_macro); |
| ... | ... | @@ -9065,6 +9065,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { |
| 9065 | 9065 | cache_bool(ch, g->linker_rdynamic); |
| 9066 | 9066 | cache_bool(ch, g->each_lib_rpath); |
| 9067 | 9067 | cache_bool(ch, g->disable_pic); |
| 9068 | cache_bool(ch, g->disable_gen_h); | |
| 9068 | 9069 | cache_bool(ch, g->valgrind_support); |
| 9069 | 9070 | cache_bool(ch, g->is_dummy_so); |
| 9070 | 9071 | cache_buf_opt(ch, g->mmacosx_version_min); |
| ... | ... | @@ -9103,99 +9104,83 @@ static bool need_llvm_module(CodeGen *g) { |
| 9103 | 9104 | return g->assembly_files.length != 0 || buf_len(&g->root_package->root_src_path) != 0; |
| 9104 | 9105 | } |
| 9105 | 9106 | |
| 9106 | static bool compilation_is_already_done(CodeGen *g) { | |
| 9107 | return !need_llvm_module(g) && g->link_objects.length == 1 && g->out_type == OutTypeObj; | |
| 9108 | } | |
| 9109 | ||
| 9110 | 9107 | static void resolve_out_paths(CodeGen *g) { |
| 9111 | Buf *o_basename = buf_create_from_buf(g->root_out_name); | |
| 9108 | assert(g->output_dir != nullptr); | |
| 9109 | assert(g->root_out_name != nullptr); | |
| 9112 | 9110 | |
| 9111 | Buf *out_basename = buf_create_from_buf(g->root_out_name); | |
| 9112 | Buf *o_basename = buf_create_from_buf(g->root_out_name); | |
| 9113 | 9113 | switch (g->emit_file_type) { |
| 9114 | case EmitFileTypeBinary: | |
| 9115 | { | |
| 9116 | const char *o_ext = target_o_file_ext(g->zig_target); | |
| 9117 | buf_append_str(o_basename, o_ext); | |
| 9114 | case EmitFileTypeBinary: { | |
| 9115 | switch (g->out_type) { | |
| 9116 | case OutTypeUnknown: | |
| 9117 | zig_unreachable(); | |
| 9118 | case OutTypeObj: | |
| 9119 | if (g->enable_cache && g->link_objects.length == 1 && !need_llvm_module(g)) { | |
| 9120 | buf_init_from_buf(&g->output_file_path, g->link_objects.at(0)); | |
| 9121 | return; | |
| 9122 | } | |
| 9123 | if (!need_llvm_module(g) || (g->enable_cache && g->link_objects.length == 0)) { | |
| 9124 | // Either we're not creating an object file from our LLVM Module, | |
| 9125 | // or we have caching enabled and do not need to link objects together. | |
| 9126 | // In both cases, the output file path and object file path basename can match. | |
| 9127 | buf_append_str(o_basename, target_o_file_ext(g->zig_target)); | |
| 9128 | buf_append_str(out_basename, target_o_file_ext(g->zig_target)); | |
| 9129 | } else { | |
| 9130 | // make it not collide with main output object | |
| 9131 | buf_append_str(o_basename, ".root"); | |
| 9132 | buf_append_str(o_basename, target_o_file_ext(g->zig_target)); | |
| 9133 | buf_append_str(out_basename, target_o_file_ext(g->zig_target)); | |
| 9134 | } | |
| 9135 | break; | |
| 9136 | case OutTypeExe: | |
| 9137 | buf_append_str(o_basename, target_o_file_ext(g->zig_target)); | |
| 9138 | buf_append_str(out_basename, target_exe_file_ext(g->zig_target)); | |
| 9139 | break; | |
| 9140 | case OutTypeLib: | |
| 9141 | buf_append_str(o_basename, target_o_file_ext(g->zig_target)); | |
| 9142 | buf_resize(out_basename, 0); | |
| 9143 | buf_append_str(out_basename, target_lib_file_prefix(g->zig_target)); | |
| 9144 | buf_append_buf(out_basename, g->root_out_name); | |
| 9145 | buf_append_str(out_basename, target_lib_file_ext(g->zig_target, g->is_static, | |
| 9146 | g->version_major, g->version_minor, g->version_patch)); | |
| 9147 | break; | |
| 9148 | } | |
| 9118 | 9149 | break; |
| 9119 | 9150 | } |
| 9120 | case EmitFileTypeAssembly: | |
| 9121 | { | |
| 9151 | case EmitFileTypeAssembly: { | |
| 9122 | 9152 | const char *asm_ext = target_asm_file_ext(g->zig_target); |
| 9123 | 9153 | buf_append_str(o_basename, asm_ext); |
| 9154 | buf_append_str(out_basename, asm_ext); | |
| 9124 | 9155 | break; |
| 9125 | 9156 | } |
| 9126 | case EmitFileTypeLLVMIr: | |
| 9127 | { | |
| 9157 | case EmitFileTypeLLVMIr: { | |
| 9128 | 9158 | const char *llvm_ir_ext = target_llvm_ir_file_ext(g->zig_target); |
| 9129 | 9159 | buf_append_str(o_basename, llvm_ir_ext); |
| 9160 | buf_append_str(out_basename, llvm_ir_ext); | |
| 9130 | 9161 | break; |
| 9131 | 9162 | } |
| 9132 | default: | |
| 9133 | zig_unreachable(); | |
| 9134 | } | |
| 9135 | ||
| 9136 | if (compilation_is_already_done(g)) { | |
| 9137 | buf_init_from_str(&g->o_file_output_path, buf_ptr(g->link_objects.at(0))); | |
| 9138 | } else if (g->enable_cache || g->out_type != OutTypeObj) { | |
| 9139 | os_path_join(&g->artifact_dir, o_basename, &g->o_file_output_path); | |
| 9140 | } else if (g->wanted_output_file_path != nullptr && g->out_type == OutTypeObj) { | |
| 9141 | buf_init_from_buf(&g->o_file_output_path, g->wanted_output_file_path); | |
| 9142 | } else { | |
| 9143 | buf_init_from_buf(&g->o_file_output_path, o_basename); | |
| 9144 | } | |
| 9145 | ||
| 9146 | if (!g->enable_cache && g->wanted_output_file_path != nullptr) { | |
| 9147 | buf_init_from_buf(&g->output_file_path, g->wanted_output_file_path); | |
| 9148 | return; | |
| 9149 | } | |
| 9150 | ||
| 9151 | if (compilation_is_already_done(g)) { | |
| 9152 | buf_init_from_buf(&g->output_file_path, &g->o_file_output_path); | |
| 9153 | return; | |
| 9154 | } | |
| 9155 | ||
| 9156 | const char *prefix = ""; | |
| 9157 | const char *extname; | |
| 9158 | switch (g->out_type) { | |
| 9159 | case OutTypeUnknown: | |
| 9160 | zig_unreachable(); | |
| 9161 | case OutTypeObj: | |
| 9162 | extname = target_o_file_ext(g->zig_target); | |
| 9163 | break; | |
| 9164 | case OutTypeExe: | |
| 9165 | extname = target_exe_file_ext(g->zig_target); | |
| 9166 | break; | |
| 9167 | case OutTypeLib: | |
| 9168 | prefix = target_lib_file_prefix(g->zig_target); | |
| 9169 | extname = target_lib_file_ext(g->zig_target, g->is_static, | |
| 9170 | g->version_major, g->version_minor, g->version_patch); | |
| 9171 | break; | |
| 9172 | 9163 | } |
| 9173 | 9164 | |
| 9174 | assert(g->root_out_name); | |
| 9175 | ||
| 9176 | Buf basename = BUF_INIT; | |
| 9177 | buf_init_from_str(&basename, prefix); | |
| 9178 | buf_append_buf(&basename, g->root_out_name); | |
| 9179 | buf_append_str(&basename, extname); | |
| 9180 | if (g->enable_cache || g->is_test_build) { | |
| 9181 | os_path_join(&g->artifact_dir, &basename, &g->output_file_path); | |
| 9182 | } else { | |
| 9183 | buf_init_from_buf(&g->output_file_path, &basename); | |
| 9184 | } | |
| 9165 | os_path_join(g->output_dir, o_basename, &g->o_file_output_path); | |
| 9166 | os_path_join(g->output_dir, out_basename, &g->output_file_path); | |
| 9185 | 9167 | } |
| 9186 | 9168 | |
| 9187 | 9169 | void codegen_build_and_link(CodeGen *g) { |
| 9188 | 9170 | Error err; |
| 9189 | 9171 | assert(g->out_type != OutTypeUnknown); |
| 9190 | 9172 | |
| 9173 | if (!g->enable_cache && g->output_dir == nullptr) { | |
| 9174 | g->output_dir = buf_create_from_str("."); | |
| 9175 | } | |
| 9176 | ||
| 9191 | 9177 | detect_libc(g); |
| 9192 | 9178 | detect_dynamic_linker(g); |
| 9193 | 9179 | |
| 9194 | Buf *artifact_dir = buf_alloc(); | |
| 9195 | 9180 | Buf digest = BUF_INIT; |
| 9196 | 9181 | if (g->enable_cache) { |
| 9197 | 9182 | Buf *manifest_dir = buf_alloc(); |
| 9198 | os_path_join(g->cache_dir, buf_create_from_str("h"), manifest_dir); | |
| 9183 | os_path_join(g->cache_dir, buf_create_from_str(CACHE_HASH_SUBDIR), manifest_dir); | |
| 9199 | 9184 | |
| 9200 | 9185 | if ((err = check_cache(g, manifest_dir, &digest))) { |
| 9201 | 9186 | if (err == ErrorCacheUnavailable) { |
| ... | ... | @@ -9208,15 +9193,14 @@ void codegen_build_and_link(CodeGen *g) { |
| 9208 | 9193 | } |
| 9209 | 9194 | exit(1); |
| 9210 | 9195 | } |
| 9211 | ||
| 9212 | os_path_join(g->cache_dir, buf_create_from_str("artifact"), artifact_dir); | |
| 9213 | 9196 | } else { |
| 9214 | 9197 | // There is a call to this in check_cache |
| 9215 | 9198 | gen_c_objects(g); |
| 9216 | 9199 | } |
| 9217 | 9200 | |
| 9218 | 9201 | if (g->enable_cache && buf_len(&digest) != 0) { |
| 9219 | os_path_join(artifact_dir, &digest, &g->artifact_dir); | |
| 9202 | g->output_dir = buf_sprintf("%s" OS_SEP CACHE_OUT_SUBDIR OS_SEP "%s", | |
| 9203 | buf_ptr(g->cache_dir), buf_ptr(&digest)); | |
| 9220 | 9204 | resolve_out_paths(g); |
| 9221 | 9205 | } else { |
| 9222 | 9206 | if (need_llvm_module(g)) { |
| ... | ... | @@ -9235,13 +9219,13 @@ void codegen_build_and_link(CodeGen *g) { |
| 9235 | 9219 | exit(1); |
| 9236 | 9220 | } |
| 9237 | 9221 | } |
| 9238 | os_path_join(artifact_dir, &digest, &g->artifact_dir); | |
| 9239 | } else { | |
| 9240 | buf_init_from_buf(&g->artifact_dir, g->cache_dir); | |
| 9241 | } | |
| 9242 | if ((err = os_make_path(&g->artifact_dir))) { | |
| 9243 | fprintf(stderr, "Unable to create artifact directory: %s\n", err_str(err)); | |
| 9244 | exit(1); | |
| 9222 | g->output_dir = buf_sprintf("%s" OS_SEP CACHE_OUT_SUBDIR OS_SEP "%s", | |
| 9223 | buf_ptr(g->cache_dir), buf_ptr(&digest)); | |
| 9224 | ||
| 9225 | if ((err = os_make_path(g->output_dir))) { | |
| 9226 | fprintf(stderr, "Unable to create output directory: %s\n", err_str(err)); | |
| 9227 | exit(1); | |
| 9228 | } | |
| 9245 | 9229 | } |
| 9246 | 9230 | resolve_out_paths(g); |
| 9247 | 9231 | |
| ... | ... | @@ -9252,14 +9236,19 @@ void codegen_build_and_link(CodeGen *g) { |
| 9252 | 9236 | codegen_add_time_event(g, "LLVM Emit Output"); |
| 9253 | 9237 | zig_llvm_emit_output(g); |
| 9254 | 9238 | |
| 9255 | if (g->out_h_path != nullptr) { | |
| 9239 | if (!g->disable_gen_h && (g->out_type == OutTypeObj || g->out_type == OutTypeLib)) { | |
| 9256 | 9240 | codegen_add_time_event(g, "Generate .h"); |
| 9257 | 9241 | gen_h_file(g); |
| 9258 | 9242 | } |
| 9259 | 9243 | } |
| 9260 | 9244 | |
| 9261 | if (g->emit_file_type == EmitFileTypeBinary && | |
| 9262 | (g->link_objects.length > 1 || g->out_type != OutTypeObj)) | |
| 9245 | // If we're outputting assembly or llvm IR we skip linking. | |
| 9246 | // If we're making a library or executable we must link. | |
| 9247 | // If there is more than one object, we have to link them (with -r). | |
| 9248 | // Finally, if we didn't make an object from zig source, and we don't have caching enabled, | |
| 9249 | // then we have an object from C source that we must copy to the output dir which we do with a -r link. | |
| 9250 | if (g->emit_file_type == EmitFileTypeBinary && (g->out_type != OutTypeObj || g->link_objects.length > 1 || | |
| 9251 | (!need_llvm_module(g) && !g->enable_cache))) | |
| 9263 | 9252 | { |
| 9264 | 9253 | codegen_link(g); |
| 9265 | 9254 | } |
src/codegen.hpp+1-5| ... | ... | @@ -28,7 +28,6 @@ void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type); |
| 28 | 28 | void codegen_set_strip(CodeGen *codegen, bool strip); |
| 29 | 29 | void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color); |
| 30 | 30 | void codegen_set_out_name(CodeGen *codegen, Buf *out_name); |
| 31 | void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker); | |
| 32 | 31 | void codegen_add_lib_dir(CodeGen *codegen, const char *dir); |
| 33 | 32 | void codegen_add_forbidden_lib(CodeGen *codegen, Buf *lib); |
| 34 | 33 | LinkLib *codegen_add_link_lib(CodeGen *codegen, Buf *lib); |
| ... | ... | @@ -41,9 +40,6 @@ void codegen_set_linker_script(CodeGen *g, const char *linker_script); |
| 41 | 40 | void codegen_set_test_filter(CodeGen *g, Buf *filter); |
| 42 | 41 | void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix); |
| 43 | 42 | void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch); |
| 44 | void codegen_set_output_h_path(CodeGen *g, Buf *h_path); | |
| 45 | void codegen_set_output_lib_path(CodeGen *g, Buf *lib_path); | |
| 46 | void codegen_set_output_path(CodeGen *g, Buf *path); | |
| 47 | 43 | void codegen_add_time_event(CodeGen *g, const char *name); |
| 48 | 44 | void codegen_print_timing_report(CodeGen *g, FILE *f); |
| 49 | 45 | void codegen_link(CodeGen *g); |
| ... | ... | @@ -54,7 +50,7 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c |
| 54 | 50 | void codegen_add_assembly(CodeGen *g, Buf *path); |
| 55 | 51 | void codegen_add_object(CodeGen *g, Buf *object_path); |
| 56 | 52 | |
| 57 | void codegen_translate_c(CodeGen *g, Buf *path); | |
| 53 | AstNode *codegen_translate_c(CodeGen *g, Buf *path); | |
| 58 | 54 | |
| 59 | 55 | Buf *codegen_generate_builtin_source(CodeGen *g); |
| 60 | 56 |
src/ir.cpp+121-33| ... | ... | @@ -16,6 +16,8 @@ |
| 16 | 16 | #include "translate_c.hpp" |
| 17 | 17 | #include "util.hpp" |
| 18 | 18 | |
| 19 | #include <errno.h> | |
| 20 | ||
| 19 | 21 | struct IrExecContext { |
| 20 | 22 | ZigList<ConstExprValue *> mem_slot_list; |
| 21 | 23 | }; |
| ... | ... | @@ -18687,7 +18689,15 @@ static IrInstruction *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstruc |
| 18687 | 18689 | return result; |
| 18688 | 18690 | } |
| 18689 | 18691 | |
| 18692 | static void ir_cimport_cache_paths(Buf *cache_dir, Buf *tmp_c_file_digest, Buf *out_zig_dir, Buf *out_zig_path) { | |
| 18693 | buf_resize(out_zig_dir, 0); | |
| 18694 | buf_resize(out_zig_path, 0); | |
| 18695 | buf_appendf(out_zig_dir, "%s" OS_SEP "o" OS_SEP "%s", | |
| 18696 | buf_ptr(cache_dir), buf_ptr(tmp_c_file_digest)); | |
| 18697 | buf_appendf(out_zig_path, "%s" OS_SEP "cimport.zig", buf_ptr(out_zig_dir)); | |
| 18698 | } | |
| 18690 | 18699 | static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstructionCImport *instruction) { |
| 18700 | Error err; | |
| 18691 | 18701 | AstNode *node = instruction->base.source_node; |
| 18692 | 18702 | assert(node->type == NodeTypeFnCallExpr); |
| 18693 | 18703 | AstNode *block_node = node->data.fn_call_expr.params.at(0); |
| ... | ... | @@ -18706,50 +18716,128 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct |
| 18706 | 18716 | Buf *namespace_name = buf_sprintf("%s.cimport:%" ZIG_PRI_usize ":%" ZIG_PRI_usize, |
| 18707 | 18717 | buf_ptr(&cur_scope_pkg->pkg_path), node->line + 1, node->column + 1); |
| 18708 | 18718 | |
| 18709 | RootStruct *root_struct = allocate<RootStruct>(1); | |
| 18710 | root_struct->package = new_anonymous_package(); | |
| 18711 | root_struct->package->package_table.put(buf_create_from_str("builtin"), ira->codegen->compile_var_package); | |
| 18712 | root_struct->package->package_table.put(buf_create_from_str("std"), ira->codegen->std_package); | |
| 18713 | root_struct->c_import_node = node; | |
| 18714 | // TODO create namespace_name file in zig-cache instead of /tmp and use it | |
| 18715 | // for this DIFile | |
| 18716 | root_struct->di_file = ZigLLVMCreateFile(ira->codegen->dbuilder, | |
| 18717 | buf_ptr(buf_create_from_str("cimport.h")), buf_ptr(buf_create_from_str("."))); | |
| 18718 | ZigType *child_import = get_root_container_type(ira->codegen, buf_ptr(namespace_name), | |
| 18719 | namespace_name, root_struct); | |
| 18719 | ZigPackage *cimport_pkg = new_anonymous_package(); | |
| 18720 | cimport_pkg->package_table.put(buf_create_from_str("builtin"), ira->codegen->compile_var_package); | |
| 18721 | cimport_pkg->package_table.put(buf_create_from_str("std"), ira->codegen->std_package); | |
| 18722 | buf_init_from_buf(&cimport_pkg->pkg_path, namespace_name); | |
| 18720 | 18723 | |
| 18721 | ZigList<ErrorMsg *> errors = {0}; | |
| 18724 | CacheHash *cache_hash; | |
| 18725 | if ((err = create_c_object_cache(ira->codegen, &cache_hash, false))) { | |
| 18726 | ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to create cache: %s", err_str(err))); | |
| 18727 | return ira->codegen->invalid_instruction; | |
| 18728 | } | |
| 18729 | cache_buf(cache_hash, &cimport_scope->buf); | |
| 18722 | 18730 | |
| 18723 | Error err; | |
| 18724 | if ((err = parse_h_buf(child_import, &errors, &cimport_scope->buf, ira->codegen, node))) { | |
| 18725 | if (err != ErrorCCompileErrors) { | |
| 18726 | ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err))); | |
| 18731 | // Set this because we're not adding any files before checking for a hit. | |
| 18732 | cache_hash->force_check_manifest = true; | |
| 18733 | ||
| 18734 | Buf tmp_c_file_digest = BUF_INIT; | |
| 18735 | buf_resize(&tmp_c_file_digest, 0); | |
| 18736 | if ((err = cache_hit(cache_hash, &tmp_c_file_digest))) { | |
| 18737 | ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to check cache: %s", err_str(err))); | |
| 18738 | return ira->codegen->invalid_instruction; | |
| 18739 | } | |
| 18740 | ira->codegen->caches_to_release.append(cache_hash); | |
| 18741 | ||
| 18742 | Buf *out_zig_dir = buf_alloc(); | |
| 18743 | Buf *out_zig_path = buf_alloc(); | |
| 18744 | if (buf_len(&tmp_c_file_digest) == 0 || cache_hash->files.length == 0) { | |
| 18745 | // Cache Miss | |
| 18746 | Buf *tmp_c_file_dir = buf_sprintf("%s" OS_SEP "o" OS_SEP "%s", | |
| 18747 | buf_ptr(ira->codegen->cache_dir), buf_ptr(&cache_hash->b64_digest)); | |
| 18748 | Buf *resolve_paths[] = { | |
| 18749 | tmp_c_file_dir, | |
| 18750 | buf_create_from_str("cimport.h"), | |
| 18751 | }; | |
| 18752 | Buf tmp_c_file_path = os_path_resolve(resolve_paths, 2); | |
| 18753 | ||
| 18754 | if ((err = os_make_path(tmp_c_file_dir))) { | |
| 18755 | ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to make dir: %s", err_str(err))); | |
| 18727 | 18756 | return ira->codegen->invalid_instruction; |
| 18728 | 18757 | } |
| 18729 | } | |
| 18758 | ||
| 18759 | if ((err = os_write_file(&tmp_c_file_path, &cimport_scope->buf))) { | |
| 18760 | ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to write .h file: %s", err_str(err))); | |
| 18761 | return ira->codegen->invalid_instruction; | |
| 18762 | } | |
| 18763 | if (ira->codegen->verbose_cimport) { | |
| 18764 | fprintf(stderr, "@cImport source: %s\n", buf_ptr(&tmp_c_file_path)); | |
| 18765 | } | |
| 18766 | ||
| 18767 | ZigList<ErrorMsg *> errors = {0}; | |
| 18768 | ||
| 18769 | Buf *tmp_dep_file = buf_sprintf("%s.d", buf_ptr(&tmp_c_file_path)); | |
| 18770 | AstNode *root_node; | |
| 18771 | if ((err = parse_h_file(&root_node, &errors, buf_ptr(&tmp_c_file_path), ira->codegen, tmp_dep_file))) { | |
| 18772 | if (err != ErrorCCompileErrors) { | |
| 18773 | ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err))); | |
| 18774 | return ira->codegen->invalid_instruction; | |
| 18775 | } | |
| 18776 | assert(errors.length > 0); | |
| 18777 | ||
| 18778 | ErrorMsg *parent_err_msg = ir_add_error_node(ira, node, buf_sprintf("C import failed")); | |
| 18779 | if (ira->codegen->libc_link_lib == nullptr) { | |
| 18780 | add_error_note(ira->codegen, parent_err_msg, node, | |
| 18781 | buf_sprintf("libc headers not available; compilation does not link against libc")); | |
| 18782 | } | |
| 18783 | for (size_t i = 0; i < errors.length; i += 1) { | |
| 18784 | ErrorMsg *err_msg = errors.at(i); | |
| 18785 | err_msg_add_note(parent_err_msg, err_msg); | |
| 18786 | } | |
| 18730 | 18787 | |
| 18731 | if (errors.length > 0) { | |
| 18732 | ErrorMsg *parent_err_msg = ir_add_error_node(ira, node, buf_sprintf("C import failed")); | |
| 18733 | if (ira->codegen->libc_link_lib == nullptr) { | |
| 18734 | add_error_note(ira->codegen, parent_err_msg, node, | |
| 18735 | buf_sprintf("libc headers not available; compilation does not link against libc")); | |
| 18788 | return ira->codegen->invalid_instruction; | |
| 18736 | 18789 | } |
| 18737 | for (size_t i = 0; i < errors.length; i += 1) { | |
| 18738 | ErrorMsg *err_msg = errors.at(i); | |
| 18739 | err_msg_add_note(parent_err_msg, err_msg); | |
| 18790 | if (ira->codegen->verbose_cimport) { | |
| 18791 | fprintf(stderr, "@cImport .d file: %s\n", buf_ptr(tmp_dep_file)); | |
| 18740 | 18792 | } |
| 18741 | 18793 | |
| 18742 | return ira->codegen->invalid_instruction; | |
| 18743 | } | |
| 18794 | if ((err = cache_add_dep_file(cache_hash, tmp_dep_file, false))) { | |
| 18795 | ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to parse .d file: %s", err_str(err))); | |
| 18796 | return ira->codegen->invalid_instruction; | |
| 18797 | } | |
| 18798 | if ((err = cache_final(cache_hash, &tmp_c_file_digest))) { | |
| 18799 | ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to finalize cache: %s", err_str(err))); | |
| 18800 | return ira->codegen->invalid_instruction; | |
| 18801 | } | |
| 18744 | 18802 | |
| 18745 | if (ira->codegen->verbose_cimport) { | |
| 18746 | fprintf(stderr, "\nC imports:\n"); | |
| 18747 | fprintf(stderr, "-----------\n"); | |
| 18748 | ast_render(ira->codegen, stderr, child_import->data.structure.decl_node, 4); | |
| 18749 | } | |
| 18803 | ir_cimport_cache_paths(ira->codegen->cache_dir, &tmp_c_file_digest, out_zig_dir, out_zig_path); | |
| 18804 | if ((err = os_make_path(out_zig_dir))) { | |
| 18805 | ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to make output dir: %s", err_str(err))); | |
| 18806 | return ira->codegen->invalid_instruction; | |
| 18807 | } | |
| 18808 | FILE *out_file = fopen(buf_ptr(out_zig_path), "wb"); | |
| 18809 | if (out_file == nullptr) { | |
| 18810 | ir_add_error_node(ira, node, | |
| 18811 | buf_sprintf("C import failed: unable to open output file: %s", strerror(errno))); | |
| 18812 | return ira->codegen->invalid_instruction; | |
| 18813 | } | |
| 18814 | ast_render(ira->codegen, out_file, root_node, 4); | |
| 18815 | if (fclose(out_file) != 0) { | |
| 18816 | ir_add_error_node(ira, node, | |
| 18817 | buf_sprintf("C import failed: unable to write to output file: %s", strerror(errno))); | |
| 18818 | return ira->codegen->invalid_instruction; | |
| 18819 | } | |
| 18750 | 18820 | |
| 18751 | scan_decls(ira->codegen, get_container_scope(child_import), child_import->data.structure.decl_node); | |
| 18821 | if (ira->codegen->verbose_cimport) { | |
| 18822 | fprintf(stderr, "@cImport output: %s\n", buf_ptr(out_zig_path)); | |
| 18823 | } | |
| 18752 | 18824 | |
| 18825 | } else { | |
| 18826 | // Cache Hit | |
| 18827 | ir_cimport_cache_paths(ira->codegen->cache_dir, &tmp_c_file_digest, out_zig_dir, out_zig_path); | |
| 18828 | if (ira->codegen->verbose_cimport) { | |
| 18829 | fprintf(stderr, "@cImport cache hit: %s\n", buf_ptr(out_zig_path)); | |
| 18830 | } | |
| 18831 | } | |
| 18832 | ||
| 18833 | Buf *import_code = buf_alloc(); | |
| 18834 | if ((err = file_fetch(ira->codegen, out_zig_path, import_code))) { | |
| 18835 | ir_add_error_node(ira, node, | |
| 18836 | buf_sprintf("unable to open '%s': %s", buf_ptr(out_zig_path), err_str(err))); | |
| 18837 | return ira->codegen->invalid_instruction; | |
| 18838 | } | |
| 18839 | ZigType *child_import = add_source_file(ira->codegen, cimport_pkg, out_zig_path, | |
| 18840 | import_code, SourceKindCImport); | |
| 18753 | 18841 | return ir_const_type(ira, &instruction->base, child_import); |
| 18754 | 18842 | } |
| 18755 | 18843 |
src/link.cpp+10-18| ... | ... | @@ -24,7 +24,7 @@ static CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, Ou |
| 24 | 24 | { |
| 25 | 25 | CodeGen *child_gen = codegen_create(nullptr, root_src_path, parent_gen->zig_target, out_type, |
| 26 | 26 | parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir, libc, get_stage1_cache_path()); |
| 27 | child_gen->out_h_path = nullptr; | |
| 27 | child_gen->disable_gen_h = true; | |
| 28 | 28 | child_gen->verbose_tokenize = parent_gen->verbose_tokenize; |
| 29 | 29 | child_gen->verbose_ast = parent_gen->verbose_ast; |
| 30 | 30 | child_gen->verbose_link = parent_gen->verbose_link; |
| ... | ... | @@ -700,11 +700,8 @@ static void construct_linker_job_elf(LinkJob *lj) { |
| 700 | 700 | } else if (is_dyn_lib) { |
| 701 | 701 | lj->args.append("-shared"); |
| 702 | 702 | |
| 703 | if (buf_len(&g->output_file_path) == 0) { | |
| 704 | buf_appendf(&g->output_file_path, "lib%s.so.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize "", | |
| 705 | buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch); | |
| 706 | } | |
| 707 | soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize "", buf_ptr(g->root_out_name), g->version_major); | |
| 703 | assert(buf_len(&g->output_file_path) != 0); | |
| 704 | soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize, buf_ptr(g->root_out_name), g->version_major); | |
| 708 | 705 | } |
| 709 | 706 | |
| 710 | 707 | lj->args.append("-o"); |
| ... | ... | @@ -884,11 +881,6 @@ static void construct_linker_job_wasm(LinkJob *lj) { |
| 884 | 881 | } |
| 885 | 882 | } |
| 886 | 883 | |
| 887 | //static bool is_target_cyg_mingw(const ZigTarget *target) { | |
| 888 | // return (target->os == ZigLLVM_Win32 && target->abi == ZigLLVM_Cygnus) || | |
| 889 | // (target->os == ZigLLVM_Win32 && target->abi == ZigLLVM_GNU); | |
| 890 | //} | |
| 891 | ||
| 892 | 884 | static void coff_append_machine_arg(CodeGen *g, ZigList<const char *> *list) { |
| 893 | 885 | if (g->zig_target->arch == ZigLLVM_x86) { |
| 894 | 886 | list->append("-MACHINE:X86"); |
| ... | ... | @@ -960,6 +952,7 @@ static void add_nt_link_args(LinkJob *lj, bool is_library) { |
| 960 | 952 | } |
| 961 | 953 | |
| 962 | 954 | static void construct_linker_job_coff(LinkJob *lj) { |
| 955 | Error err; | |
| 963 | 956 | CodeGen *g = lj->codegen; |
| 964 | 957 | |
| 965 | 958 | lj->args.append("/ERRORLIMIT:0"); |
| ... | ... | @@ -1079,11 +1072,13 @@ static void construct_linker_job_coff(LinkJob *lj) { |
| 1079 | 1072 | buf_appendf(def_contents, "\n"); |
| 1080 | 1073 | |
| 1081 | 1074 | Buf *def_path = buf_alloc(); |
| 1082 | os_path_join(&g->artifact_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path); | |
| 1083 | os_write_file(def_path, def_contents); | |
| 1075 | os_path_join(g->output_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path); | |
| 1076 | if ((err = os_write_file(def_path, def_contents))) { | |
| 1077 | zig_panic("error writing def file: %s", err_str(err)); | |
| 1078 | } | |
| 1084 | 1079 | |
| 1085 | 1080 | Buf *generated_lib_path = buf_alloc(); |
| 1086 | os_path_join(&g->artifact_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path); | |
| 1081 | os_path_join(g->output_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path); | |
| 1087 | 1082 | |
| 1088 | 1083 | gen_lib_args.resize(0); |
| 1089 | 1084 | gen_lib_args.append("link"); |
| ... | ... | @@ -1245,10 +1240,7 @@ static void construct_linker_job_macho(LinkJob *lj) { |
| 1245 | 1240 | //lj->args.append("-install_name"); |
| 1246 | 1241 | //lj->args.append(buf_ptr(dylib_install_name)); |
| 1247 | 1242 | |
| 1248 | if (buf_len(&g->output_file_path) == 0) { | |
| 1249 | buf_appendf(&g->output_file_path, "lib%s.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib", | |
| 1250 | buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch); | |
| 1251 | } | |
| 1243 | assert(buf_len(&g->output_file_path) != 0); | |
| 1252 | 1244 | } |
| 1253 | 1245 | |
| 1254 | 1246 | lj->args.append("-arch"); |
src/main.cpp+45-41| ... | ... | @@ -48,9 +48,10 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { |
| 48 | 48 | "Compile Options:\n" |
| 49 | 49 | " --assembly [source] add assembly file to build\n" |
| 50 | 50 | " --c-source [options] [file] compile C source code\n" |
| 51 | " --cache-dir [path] override the cache directory\n" | |
| 52 | " --cache [auto|off|on] build in global cache, print out paths to stdout\n" | |
| 51 | " --cache-dir [path] override the local cache directory\n" | |
| 52 | " --cache [auto|off|on] build in cache, print output path to stdout\n" | |
| 53 | 53 | " --color [auto|off|on] enable or disable colored error messages\n" |
| 54 | " --disable-gen-h do not generate a C header file (.h)\n" | |
| 54 | 55 | " --disable-pic disable Position Independent Code for libraries\n" |
| 55 | 56 | " --disable-valgrind omit valgrind client requests in debug builds\n" |
| 56 | 57 | " --enable-valgrind include valgrind client requests release builds\n" |
| ... | ... | @@ -58,9 +59,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { |
| 58 | 59 | " -ftime-report print timing diagnostics\n" |
| 59 | 60 | " --libc [file] Provide a file which specifies libc paths\n" |
| 60 | 61 | " --name [name] override output name\n" |
| 61 | " --output [file] override destination path\n" | |
| 62 | " --output-h [file] generate header file\n" | |
| 63 | " --output-lib [file] override import library path\n" | |
| 62 | " --output-dir [dir] override output directory (defaults to cwd)\n" | |
| 64 | 63 | " --pkg-begin [name] [path] make pkg available to import and push current pkg\n" |
| 65 | 64 | " --pkg-end pop current pkg\n" |
| 66 | 65 | " --main-pkg-path set the directory of the root package\n" |
| ... | ... | @@ -371,8 +370,14 @@ int main(int argc, char **argv) { |
| 371 | 370 | fprintf(stderr, "Unable to make directory: %s: %s\n", buf_ptr(out_src_dir_path), err_str(err)); |
| 372 | 371 | return EXIT_FAILURE; |
| 373 | 372 | } |
| 374 | os_write_file(out_build_zig_path, modified_build_zig_contents); | |
| 375 | os_write_file(out_main_zig_path, main_zig_contents); | |
| 373 | if ((err = os_write_file(out_build_zig_path, modified_build_zig_contents))) { | |
| 374 | fprintf(stderr, "Unable to write file: %s: %s\n", buf_ptr(out_build_zig_path), err_str(err)); | |
| 375 | return EXIT_FAILURE; | |
| 376 | } | |
| 377 | if ((err = os_write_file(out_main_zig_path, main_zig_contents))) { | |
| 378 | fprintf(stderr, "Unable to write file: %s: %s\n", buf_ptr(out_main_zig_path), err_str(err)); | |
| 379 | return EXIT_FAILURE; | |
| 380 | } | |
| 376 | 381 | fprintf(stderr, "Created %s\n", buf_ptr(out_build_zig_path)); |
| 377 | 382 | fprintf(stderr, "Created %s\n", buf_ptr(out_main_zig_path)); |
| 378 | 383 | if (init_kind == InitKindExe) { |
| ... | ... | @@ -390,9 +395,7 @@ int main(int argc, char **argv) { |
| 390 | 395 | Cmd cmd = CmdNone; |
| 391 | 396 | EmitFileType emit_file_type = EmitFileTypeBinary; |
| 392 | 397 | const char *in_file = nullptr; |
| 393 | const char *out_file = nullptr; | |
| 394 | const char *out_file_h = nullptr; | |
| 395 | const char *out_file_lib = nullptr; | |
| 398 | Buf *output_dir = nullptr; | |
| 396 | 399 | bool strip = false; |
| 397 | 400 | bool is_static = false; |
| 398 | 401 | OutType out_type = OutTypeUnknown; |
| ... | ... | @@ -406,7 +409,7 @@ int main(int argc, char **argv) { |
| 406 | 409 | bool verbose_cc = false; |
| 407 | 410 | ErrColor color = ErrColorAuto; |
| 408 | 411 | CacheOpt enable_cache = CacheOptAuto; |
| 409 | const char *dynamic_linker = nullptr; | |
| 412 | Buf *dynamic_linker = nullptr; | |
| 410 | 413 | const char *libc_txt = nullptr; |
| 411 | 414 | ZigList<const char *> clang_argv = {0}; |
| 412 | 415 | ZigList<const char *> lib_dirs = {0}; |
| ... | ... | @@ -438,6 +441,7 @@ int main(int argc, char **argv) { |
| 438 | 441 | bool system_linker_hack = false; |
| 439 | 442 | TargetSubsystem subsystem = TargetSubsystemAuto; |
| 440 | 443 | bool is_single_threaded = false; |
| 444 | bool disable_gen_h = false; | |
| 441 | 445 | Buf *override_std_dir = nullptr; |
| 442 | 446 | Buf *main_pkg_path = nullptr; |
| 443 | 447 | ValgrindSupport valgrind_support = ValgrindSupportAuto; |
| ... | ... | @@ -648,6 +652,8 @@ int main(int argc, char **argv) { |
| 648 | 652 | system_linker_hack = true; |
| 649 | 653 | } else if (strcmp(arg, "--single-threaded") == 0) { |
| 650 | 654 | is_single_threaded = true; |
| 655 | } else if (strcmp(arg, "--disable-gen-h") == 0) { | |
| 656 | disable_gen_h = true; | |
| 651 | 657 | } else if (strcmp(arg, "--test-cmd-bin") == 0) { |
| 652 | 658 | test_exec_args.append(nullptr); |
| 653 | 659 | } else if (arg[1] == 'L' && arg[2] != 0) { |
| ... | ... | @@ -677,12 +683,8 @@ int main(int argc, char **argv) { |
| 677 | 683 | return print_error_usage(arg0); |
| 678 | 684 | } else { |
| 679 | 685 | i += 1; |
| 680 | if (strcmp(arg, "--output") == 0) { | |
| 681 | out_file = argv[i]; | |
| 682 | } else if (strcmp(arg, "--output-h") == 0) { | |
| 683 | out_file_h = argv[i]; | |
| 684 | } else if (strcmp(arg, "--output-lib") == 0) { | |
| 685 | out_file_lib = argv[i]; | |
| 686 | if (strcmp(arg, "--output-dir") == 0) { | |
| 687 | output_dir = buf_create_from_str(argv[i]); | |
| 686 | 688 | } else if (strcmp(arg, "--color") == 0) { |
| 687 | 689 | if (strcmp(argv[i], "auto") == 0) { |
| 688 | 690 | color = ErrColorAuto; |
| ... | ... | @@ -719,7 +721,7 @@ int main(int argc, char **argv) { |
| 719 | 721 | } else if (strcmp(arg, "--name") == 0) { |
| 720 | 722 | out_name = argv[i]; |
| 721 | 723 | } else if (strcmp(arg, "--dynamic-linker") == 0) { |
| 722 | dynamic_linker = argv[i]; | |
| 724 | dynamic_linker = buf_create_from_str(argv[i]); | |
| 723 | 725 | } else if (strcmp(arg, "--libc") == 0) { |
| 724 | 726 | libc_txt = argv[i]; |
| 725 | 727 | } else if (strcmp(arg, "-isystem") == 0) { |
| ... | ... | @@ -901,6 +903,21 @@ int main(int argc, char **argv) { |
| 901 | 903 | } |
| 902 | 904 | } |
| 903 | 905 | |
| 906 | if (output_dir != nullptr && enable_cache == CacheOptOn) { | |
| 907 | fprintf(stderr, "The --output-dir argument is incompatible with --cache on.\n"); | |
| 908 | return print_error_usage(arg0); | |
| 909 | } | |
| 910 | ||
| 911 | if (emit_file_type != EmitFileTypeBinary && in_file == nullptr) { | |
| 912 | fprintf(stderr, "A root source file is required when using --emit asm or --emit llvm-ir"); | |
| 913 | return print_error_usage(arg0); | |
| 914 | } | |
| 915 | ||
| 916 | if (llvm_argv.length > 1) { | |
| 917 | llvm_argv.append(nullptr); | |
| 918 | ZigLLVMParseCommandLineOptions(llvm_argv.length - 1, llvm_argv.items); | |
| 919 | } | |
| 920 | ||
| 904 | 921 | switch (cmd) { |
| 905 | 922 | case CmdLibC: { |
| 906 | 923 | if (in_file) { |
| ... | ... | @@ -1008,6 +1025,7 @@ int main(int argc, char **argv) { |
| 1008 | 1025 | } |
| 1009 | 1026 | CodeGen *g = codegen_create(main_pkg_path, zig_root_source_file, &target, out_type, build_mode, |
| 1010 | 1027 | get_zig_lib_dir(), override_std_dir, libc, cache_dir_buf); |
| 1028 | if (llvm_argv.length >= 2) codegen_set_llvm_argv(g, llvm_argv.items + 1, llvm_argv.length - 2); | |
| 1011 | 1029 | g->valgrind_support = valgrind_support; |
| 1012 | 1030 | g->subsystem = subsystem; |
| 1013 | 1031 | |
| ... | ... | @@ -1030,16 +1048,9 @@ int main(int argc, char **argv) { |
| 1030 | 1048 | |
| 1031 | 1049 | codegen_set_clang_argv(g, clang_argv.items, clang_argv.length); |
| 1032 | 1050 | |
| 1033 | if (llvm_argv.length > 1) { | |
| 1034 | llvm_argv.append(nullptr); | |
| 1035 | ZigLLVMParseCommandLineOptions(llvm_argv.length - 1, llvm_argv.items); | |
| 1036 | } | |
| 1037 | ||
| 1038 | codegen_set_llvm_argv(g, llvm_argv.items + 1, llvm_argv.length - 2); | |
| 1039 | 1051 | codegen_set_strip(g, strip); |
| 1040 | 1052 | g->is_static = is_static; |
| 1041 | if (dynamic_linker != nullptr) | |
| 1042 | codegen_set_dynamic_linker(g, buf_create_from_str(dynamic_linker)); | |
| 1053 | g->dynamic_linker_path = dynamic_linker; | |
| 1043 | 1054 | g->verbose_tokenize = verbose_tokenize; |
| 1044 | 1055 | g->verbose_ast = verbose_ast; |
| 1045 | 1056 | g->verbose_link = verbose_link; |
| ... | ... | @@ -1047,6 +1058,8 @@ int main(int argc, char **argv) { |
| 1047 | 1058 | g->verbose_llvm_ir = verbose_llvm_ir; |
| 1048 | 1059 | g->verbose_cimport = verbose_cimport; |
| 1049 | 1060 | g->verbose_cc = verbose_cc; |
| 1061 | g->output_dir = output_dir; | |
| 1062 | g->disable_gen_h = disable_gen_h; | |
| 1050 | 1063 | codegen_set_errmsg_color(g, color); |
| 1051 | 1064 | g->system_linker_hack = system_linker_hack; |
| 1052 | 1065 | |
| ... | ... | @@ -1090,13 +1103,6 @@ int main(int argc, char **argv) { |
| 1090 | 1103 | codegen_set_test_name_prefix(g, buf_create_from_str(test_name_prefix)); |
| 1091 | 1104 | } |
| 1092 | 1105 | |
| 1093 | if (out_file) | |
| 1094 | codegen_set_output_path(g, buf_create_from_str(out_file)); | |
| 1095 | if (out_file_h != nullptr && (out_type == OutTypeObj || out_type == OutTypeLib)) | |
| 1096 | codegen_set_output_h_path(g, buf_create_from_str(out_file_h)); | |
| 1097 | if (out_file_lib != nullptr && out_type == OutTypeLib && !is_static) | |
| 1098 | codegen_set_output_lib_path(g, buf_create_from_str(out_file_lib)); | |
| 1099 | ||
| 1100 | 1106 | add_package(g, cur_pkg, g->root_package); |
| 1101 | 1107 | |
| 1102 | 1108 | if (cmd == CmdBuild || cmd == CmdRun || cmd == CmdTest) { |
| ... | ... | @@ -1135,20 +1141,18 @@ int main(int argc, char **argv) { |
| 1135 | 1141 | return term.code; |
| 1136 | 1142 | } else if (cmd == CmdBuild) { |
| 1137 | 1143 | if (g->enable_cache) { |
| 1138 | printf("%s\n", buf_ptr(&g->output_file_path)); | |
| 1139 | if (g->out_h_path != nullptr) { | |
| 1140 | printf("%s\n", buf_ptr(g->out_h_path)); | |
| 1141 | } | |
| 1144 | if (printf("%s\n", buf_ptr(&g->output_file_path)) < 0) | |
| 1145 | return EXIT_FAILURE; | |
| 1142 | 1146 | } |
| 1143 | 1147 | return EXIT_SUCCESS; |
| 1144 | 1148 | } else { |
| 1145 | 1149 | zig_unreachable(); |
| 1146 | 1150 | } |
| 1147 | 1151 | } else if (cmd == CmdTranslateC) { |
| 1148 | codegen_translate_c(g, in_file_buf); | |
| 1149 | ast_render(g, stdout, g->root_import->data.structure.decl_node, 4); | |
| 1152 | AstNode *root_node = codegen_translate_c(g, in_file_buf); | |
| 1153 | ast_render(g, stdout, root_node, 4); | |
| 1150 | 1154 | if (timing_info) |
| 1151 | codegen_print_timing_report(g, stdout); | |
| 1155 | codegen_print_timing_report(g, stderr); | |
| 1152 | 1156 | return EXIT_SUCCESS; |
| 1153 | 1157 | } else if (cmd == CmdTest) { |
| 1154 | 1158 | codegen_set_emit_file_type(g, emit_file_type); |
| ... | ... | @@ -1156,7 +1160,7 @@ int main(int argc, char **argv) { |
| 1156 | 1160 | ZigTarget native; |
| 1157 | 1161 | get_native_target(&native); |
| 1158 | 1162 | |
| 1159 | g->enable_cache = get_cache_opt(enable_cache, false); | |
| 1163 | g->enable_cache = get_cache_opt(enable_cache, true); | |
| 1160 | 1164 | codegen_build_and_link(g); |
| 1161 | 1165 | |
| 1162 | 1166 | if (timing_info) { |
src/os.cpp+2-86| ... | ... | @@ -1031,7 +1031,7 @@ Error os_exec_process(const char *exe, ZigList<const char *> &args, |
| 1031 | 1031 | #endif |
| 1032 | 1032 | } |
| 1033 | 1033 | |
| 1034 | void os_write_file(Buf *full_path, Buf *contents) { | |
| 1034 | Error os_write_file(Buf *full_path, Buf *contents) { | |
| 1035 | 1035 | FILE *f = fopen(buf_ptr(full_path), "wb"); |
| 1036 | 1036 | if (!f) { |
| 1037 | 1037 | zig_panic("os_write_file failed for %s", buf_ptr(full_path)); |
| ... | ... | @@ -1041,6 +1041,7 @@ void os_write_file(Buf *full_path, Buf *contents) { |
| 1041 | 1041 | zig_panic("write failed: %s", strerror(errno)); |
| 1042 | 1042 | if (fclose(f)) |
| 1043 | 1043 | zig_panic("close failed"); |
| 1044 | return ErrorNone; | |
| 1044 | 1045 | } |
| 1045 | 1046 | |
| 1046 | 1047 | Error os_copy_file(Buf *src_path, Buf *dest_path) { |
| ... | ... | @@ -1208,91 +1209,6 @@ bool os_stderr_tty(void) { |
| 1208 | 1209 | #endif |
| 1209 | 1210 | } |
| 1210 | 1211 | |
| 1211 | #if defined(ZIG_OS_POSIX) | |
| 1212 | static Error os_buf_to_tmp_file_posix(Buf *contents, Buf *suffix, Buf *out_tmp_path) { | |
| 1213 | const char *tmp_dir = getenv("TMPDIR"); | |
| 1214 | if (!tmp_dir) { | |
| 1215 | tmp_dir = P_tmpdir; | |
| 1216 | } | |
| 1217 | buf_resize(out_tmp_path, 0); | |
| 1218 | buf_appendf(out_tmp_path, "%s/XXXXXX%s", tmp_dir, buf_ptr(suffix)); | |
| 1219 | ||
| 1220 | int fd = mkstemps(buf_ptr(out_tmp_path), (int)buf_len(suffix)); | |
| 1221 | if (fd < 0) { | |
| 1222 | return ErrorFileSystem; | |
| 1223 | } | |
| 1224 | ||
| 1225 | FILE *f = fdopen(fd, "wb"); | |
| 1226 | if (!f) { | |
| 1227 | zig_panic("fdopen failed"); | |
| 1228 | } | |
| 1229 | ||
| 1230 | size_t amt_written = fwrite(buf_ptr(contents), 1, buf_len(contents), f); | |
| 1231 | if (amt_written != (size_t)buf_len(contents)) | |
| 1232 | zig_panic("write failed: %s", strerror(errno)); | |
| 1233 | if (fclose(f)) | |
| 1234 | zig_panic("close failed"); | |
| 1235 | ||
| 1236 | return ErrorNone; | |
| 1237 | } | |
| 1238 | #endif | |
| 1239 | ||
| 1240 | Buf *os_tmp_filename(Buf *prefix, Buf *suffix) { | |
| 1241 | Buf *result = buf_create_from_buf(prefix); | |
| 1242 | ||
| 1243 | const char base64[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"; | |
| 1244 | assert(array_length(base64) == 64 + 1); | |
| 1245 | for (size_t i = 0; i < 12; i += 1) { | |
| 1246 | buf_append_char(result, base64[rand() % 64]); | |
| 1247 | } | |
| 1248 | buf_append_buf(result, suffix); | |
| 1249 | return result; | |
| 1250 | } | |
| 1251 | ||
| 1252 | #if defined(ZIG_OS_WINDOWS) | |
| 1253 | static Error os_buf_to_tmp_file_windows(Buf *contents, Buf *suffix, Buf *out_tmp_path) { | |
| 1254 | char tmp_dir[MAX_PATH + 1]; | |
| 1255 | if (GetTempPath(MAX_PATH, tmp_dir) == 0) { | |
| 1256 | zig_panic("GetTempPath failed"); | |
| 1257 | } | |
| 1258 | buf_init_from_str(out_tmp_path, tmp_dir); | |
| 1259 | ||
| 1260 | const char base64[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"; | |
| 1261 | assert(array_length(base64) == 64 + 1); | |
| 1262 | for (size_t i = 0; i < 8; i += 1) { | |
| 1263 | buf_append_char(out_tmp_path, base64[rand() % 64]); | |
| 1264 | } | |
| 1265 | ||
| 1266 | buf_append_buf(out_tmp_path, suffix); | |
| 1267 | ||
| 1268 | FILE *f = fopen(buf_ptr(out_tmp_path), "wb"); | |
| 1269 | ||
| 1270 | if (!f) { | |
| 1271 | zig_panic("unable to open %s: %s", buf_ptr(out_tmp_path), strerror(errno)); | |
| 1272 | } | |
| 1273 | ||
| 1274 | size_t amt_written = fwrite(buf_ptr(contents), 1, buf_len(contents), f); | |
| 1275 | if (amt_written != (size_t)buf_len(contents)) { | |
| 1276 | zig_panic("write failed: %s", strerror(errno)); | |
| 1277 | } | |
| 1278 | ||
| 1279 | if (fclose(f)) { | |
| 1280 | zig_panic("fclose failed"); | |
| 1281 | } | |
| 1282 | return ErrorNone; | |
| 1283 | } | |
| 1284 | #endif | |
| 1285 | ||
| 1286 | Error os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path) { | |
| 1287 | #if defined(ZIG_OS_WINDOWS) | |
| 1288 | return os_buf_to_tmp_file_windows(contents, suffix, out_tmp_path); | |
| 1289 | #elif defined(ZIG_OS_POSIX) | |
| 1290 | return os_buf_to_tmp_file_posix(contents, suffix, out_tmp_path); | |
| 1291 | #else | |
| 1292 | #error "missing os_buf_to_tmp_file implementation" | |
| 1293 | #endif | |
| 1294 | } | |
| 1295 | ||
| 1296 | 1212 | Error os_delete_file(Buf *path) { |
| 1297 | 1213 | if (remove(buf_ptr(path))) { |
| 1298 | 1214 | return ErrorFileSystem; |
src/os.hpp+2-4| ... | ... | @@ -110,8 +110,8 @@ Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents); |
| 110 | 110 | Error ATTRIBUTE_MUST_USE os_file_overwrite(OsFile file, Buf *contents); |
| 111 | 111 | void os_file_close(OsFile file); |
| 112 | 112 | |
| 113 | void os_write_file(Buf *full_path, Buf *contents); | |
| 114 | Error os_copy_file(Buf *src_path, Buf *dest_path); | |
| 113 | Error ATTRIBUTE_MUST_USE os_write_file(Buf *full_path, Buf *contents); | |
| 114 | Error ATTRIBUTE_MUST_USE os_copy_file(Buf *src_path, Buf *dest_path); | |
| 115 | 115 | |
| 116 | 116 | Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents, bool skip_shebang); |
| 117 | 117 | Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang); |
| ... | ... | @@ -121,8 +121,6 @@ Error ATTRIBUTE_MUST_USE os_get_cwd(Buf *out_cwd); |
| 121 | 121 | bool os_stderr_tty(void); |
| 122 | 122 | void os_stderr_set_color(TermColor color); |
| 123 | 123 | |
| 124 | Buf *os_tmp_filename(Buf *prefix, Buf *suffix); | |
| 125 | Error os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path); | |
| 126 | 124 | Error os_delete_file(Buf *path); |
| 127 | 125 | |
| 128 | 126 | Error ATTRIBUTE_MUST_USE os_file_exists(Buf *full_path, bool *result); |
src/target.cpp+5-1| ... | ... | @@ -942,8 +942,12 @@ const char *target_lib_file_ext(const ZigTarget *target, bool is_static, |
| 942 | 942 | } else { |
| 943 | 943 | if (is_static) { |
| 944 | 944 | return ".a"; |
| 945 | } else if (target_is_darwin(target)) { | |
| 946 | return buf_ptr(buf_sprintf(".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib", | |
| 947 | version_major, version_minor, version_patch)); | |
| 945 | 948 | } else { |
| 946 | return buf_ptr(buf_sprintf(".so.%" ZIG_PRI_usize, version_major)); | |
| 949 | return buf_ptr(buf_sprintf(".so.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize, | |
| 950 | version_major, version_minor, version_patch)); | |
| 947 | 951 | } |
| 948 | 952 | } |
| 949 | 953 | } |
src/translate_c.cpp+6-42| ... | ... | @@ -76,7 +76,6 @@ struct TransScopeWhile { |
| 76 | 76 | }; |
| 77 | 77 | |
| 78 | 78 | struct Context { |
| 79 | ZigType *import; | |
| 80 | 79 | ZigList<ErrorMsg *> *errors; |
| 81 | 80 | VisibMod visib_mod; |
| 82 | 81 | bool want_export; |
| ... | ... | @@ -86,7 +85,6 @@ struct Context { |
| 86 | 85 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table; |
| 87 | 86 | ZigClangSourceManager *source_manager; |
| 88 | 87 | ZigList<Alias> aliases; |
| 89 | AstNode *source_node; | |
| 90 | 88 | bool warnings_on; |
| 91 | 89 | |
| 92 | 90 | CodeGen *codegen; |
| ... | ... | @@ -190,7 +188,6 @@ static Buf *trans_lookup_zig_symbol(Context *c, TransScope *scope, Buf *c_symbol |
| 190 | 188 | static AstNode * trans_create_node(Context *c, NodeType id) { |
| 191 | 189 | AstNode *node = allocate<AstNode>(1); |
| 192 | 190 | node->type = id; |
| 193 | node->owner = c->import; | |
| 194 | 191 | // TODO line/column. mapping to C file?? |
| 195 | 192 | return node; |
| 196 | 193 | } |
| ... | ... | @@ -4732,29 +4729,12 @@ static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) { |
| 4732 | 4729 | } |
| 4733 | 4730 | } |
| 4734 | 4731 | |
| 4735 | Error parse_h_buf(ZigType *import, ZigList<ErrorMsg *> *errors, Buf *source, | |
| 4736 | CodeGen *codegen, AstNode *source_node) | |
| 4737 | { | |
| 4738 | Error err; | |
| 4739 | Buf tmp_file_path = BUF_INIT; | |
| 4740 | if ((err = os_buf_to_tmp_file(source, buf_create_from_str(".h"), &tmp_file_path))) { | |
| 4741 | return err; | |
| 4742 | } | |
| 4743 | ||
| 4744 | err = parse_h_file(import, errors, buf_ptr(&tmp_file_path), codegen, source_node); | |
| 4745 | ||
| 4746 | os_delete_file(&tmp_file_path); | |
| 4747 | ||
| 4748 | return err; | |
| 4749 | } | |
| 4750 | ||
| 4751 | Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *target_file, | |
| 4752 | CodeGen *codegen, AstNode *source_node) | |
| 4732 | Error parse_h_file(AstNode **out_root_node, ZigList<ErrorMsg *> *errors, const char *target_file, | |
| 4733 | CodeGen *codegen, Buf *tmp_dep_file) | |
| 4753 | 4734 | { |
| 4754 | 4735 | Context context = {0}; |
| 4755 | 4736 | Context *c = &context; |
| 4756 | 4737 | c->warnings_on = codegen->verbose_cimport; |
| 4757 | c->import = import; | |
| 4758 | 4738 | c->errors = errors; |
| 4759 | 4739 | if (buf_ends_with_str(buf_create_from_str(target_file), ".h")) { |
| 4760 | 4740 | c->visib_mod = VisibModPub; |
| ... | ... | @@ -4768,7 +4748,6 @@ Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *tar |
| 4768 | 4748 | c->global_table.init(8); |
| 4769 | 4749 | c->ptr_params.init(8); |
| 4770 | 4750 | c->codegen = codegen; |
| 4771 | c->source_node = source_node; | |
| 4772 | 4751 | c->global_scope = trans_scope_root_create(c); |
| 4773 | 4752 | |
| 4774 | 4753 | ZigList<const char *> clang_argv = {0}; |
| ... | ... | @@ -4776,14 +4755,11 @@ Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *tar |
| 4776 | 4755 | clang_argv.append("-x"); |
| 4777 | 4756 | clang_argv.append("c"); |
| 4778 | 4757 | |
| 4779 | Buf *out_dep_path = nullptr; | |
| 4780 | if (codegen->enable_cache) { | |
| 4781 | Buf *prefix = buf_sprintf("%s" OS_SEP, buf_ptr(codegen->cache_dir)); | |
| 4782 | out_dep_path = os_tmp_filename(prefix, buf_create_from_str(".d")); | |
| 4758 | if (tmp_dep_file != nullptr) { | |
| 4783 | 4759 | clang_argv.append("-MD"); |
| 4784 | 4760 | clang_argv.append("-MV"); |
| 4785 | 4761 | clang_argv.append("-MF"); |
| 4786 | clang_argv.append(buf_ptr(out_dep_path)); | |
| 4762 | clang_argv.append(buf_ptr(tmp_dep_file)); | |
| 4787 | 4763 | } |
| 4788 | 4764 | |
| 4789 | 4765 | if (c->codegen->zig_target->is_native) { |
| ... | ... | @@ -4847,7 +4823,7 @@ Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *tar |
| 4847 | 4823 | |
| 4848 | 4824 | clang_argv.append(target_file); |
| 4849 | 4825 | |
| 4850 | if (codegen->verbose_cimport) { | |
| 4826 | if (codegen->verbose_cc) { | |
| 4851 | 4827 | fprintf(stderr, "clang"); |
| 4852 | 4828 | for (size_t i = 0; i < clang_argv.length; i += 1) { |
| 4853 | 4829 | fprintf(stderr, " %s", clang_argv.at(i)); |
| ... | ... | @@ -4932,17 +4908,6 @@ Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *tar |
| 4932 | 4908 | return ErrorCCompileErrors; |
| 4933 | 4909 | } |
| 4934 | 4910 | |
| 4935 | if (codegen->enable_cache) { | |
| 4936 | Error err; | |
| 4937 | assert(out_dep_path != nullptr); | |
| 4938 | if ((err = cache_add_dep_file(&codegen->cache_hash, out_dep_path, codegen->verbose_cimport))) { | |
| 4939 | if (codegen->verbose_cimport) { | |
| 4940 | fprintf(stderr, "translate-c: aborting due to failed cache operation: %s\n", err_str(err)); | |
| 4941 | } | |
| 4942 | return err; | |
| 4943 | } | |
| 4944 | } | |
| 4945 | ||
| 4946 | 4911 | c->ctx = ZigClangASTUnit_getASTContext(ast_unit); |
| 4947 | 4912 | c->source_manager = ZigClangASTUnit_getSourceManager(ast_unit); |
| 4948 | 4913 | c->root = trans_create_node(c, NodeTypeContainerDecl); |
| ... | ... | @@ -4955,8 +4920,7 @@ Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *tar |
| 4955 | 4920 | render_macros(c); |
| 4956 | 4921 | render_aliases(c); |
| 4957 | 4922 | |
| 4958 | import->data.structure.decl_node = c->root; | |
| 4959 | import->data.structure.decls_scope->base.source_node = c->root; | |
| 4923 | *out_root_node = c->root; | |
| 4960 | 4924 | |
| 4961 | 4925 | return ErrorNone; |
| 4962 | 4926 | } |
src/translate_c.hpp+2-5| ... | ... | @@ -11,10 +11,7 @@ |
| 11 | 11 | |
| 12 | 12 | #include "all_types.hpp" |
| 13 | 13 | |
| 14 | Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *target_file, | |
| 15 | CodeGen *codegen, AstNode *source_node); | |
| 16 | ||
| 17 | Error parse_h_buf(ZigType *import, ZigList<ErrorMsg *> *errors, Buf *source, | |
| 18 | CodeGen *codegen, AstNode *source_node); | |
| 14 | Error parse_h_file(AstNode **out_root_node, ZigList<ErrorMsg *> *errors, const char *target_file, | |
| 15 | CodeGen *codegen, Buf *tmp_dep_file); | |
| 19 | 16 | |
| 20 | 17 | #endif |
std/build.zig+266-185| ... | ... | @@ -183,9 +183,20 @@ pub const Builder = struct { |
| 183 | 183 | return obj_step; |
| 184 | 184 | } |
| 185 | 185 | |
| 186 | /// ::argv is copied. | |
| 187 | pub fn addCommand(self: *Builder, cwd: ?[]const u8, env_map: *const BufMap, argv: []const []const u8) *CommandStep { | |
| 188 | return CommandStep.create(self, cwd, env_map, argv); | |
| 186 | /// Initializes a RunStep with argv, which must at least have the path to the | |
| 187 | /// executable. More command line arguments can be added with `addArg`, | |
| 188 | /// `addArgs`, and `addArtifactArg`. | |
| 189 | /// Be careful using this function, as it introduces a system dependency. | |
| 190 | /// To run an executable built with zig build, see `LibExeObjStep.run`. | |
| 191 | pub fn addSystemCommand(self: *Builder, argv: []const []const u8) *RunStep { | |
| 192 | assert(argv.len >= 1); | |
| 193 | const run_step = RunStep.create(self, self.fmt("run {}", argv[0])); | |
| 194 | run_step.addArgs(argv); | |
| 195 | return run_step; | |
| 196 | } | |
| 197 | ||
| 198 | fn dupe(self: *Builder, bytes: []const u8) []u8 { | |
| 199 | return mem.dupe(self.allocator, u8, bytes) catch unreachable; | |
| 189 | 200 | } |
| 190 | 201 | |
| 191 | 202 | pub fn addWriteFile(self: *Builder, file_path: []const u8, data: []const u8) *WriteFileStep { |
| ... | ... | @@ -702,25 +713,42 @@ pub const Builder = struct { |
| 702 | 713 | } |
| 703 | 714 | |
| 704 | 715 | pub fn exec(self: *Builder, argv: []const []const u8) ![]u8 { |
| 716 | assert(argv.len != 0); | |
| 717 | ||
| 705 | 718 | const max_output_size = 100 * 1024; |
| 706 | const result = try os.ChildProcess.exec(self.allocator, argv, null, null, max_output_size); | |
| 707 | switch (result.term) { | |
| 719 | const child = try os.ChildProcess.init(argv, self.allocator); | |
| 720 | defer child.deinit(); | |
| 721 | ||
| 722 | child.stdin_behavior = os.ChildProcess.StdIo.Ignore; | |
| 723 | child.stdout_behavior = os.ChildProcess.StdIo.Pipe; | |
| 724 | child.stderr_behavior = os.ChildProcess.StdIo.Inherit; | |
| 725 | ||
| 726 | try child.spawn(); | |
| 727 | ||
| 728 | var stdout = std.Buffer.initNull(self.allocator); | |
| 729 | defer std.Buffer.deinit(&stdout); | |
| 730 | ||
| 731 | var stdout_file_in_stream = child.stdout.?.inStream(); | |
| 732 | try stdout_file_in_stream.stream.readAllBuffer(&stdout, max_output_size); | |
| 733 | ||
| 734 | const term = child.wait() catch |err| std.debug.panic("unable to spawn {}: {}", argv[0], err); | |
| 735 | switch (term) { | |
| 708 | 736 | os.ChildProcess.Term.Exited => |code| { |
| 709 | 737 | if (code != 0) { |
| 710 | 738 | warn("The following command exited with error code {}:\n", code); |
| 711 | 739 | printCmd(null, argv); |
| 712 | warn("stderr:{}\n", result.stderr); | |
| 713 | std.debug.panic("command failed"); | |
| 740 | std.debug.panic("exec failed"); | |
| 714 | 741 | } |
| 715 | return result.stdout; | |
| 742 | return stdout.toOwnedSlice(); | |
| 716 | 743 | }, |
| 717 | 744 | else => { |
| 718 | 745 | warn("The following command terminated unexpectedly:\n"); |
| 719 | 746 | printCmd(null, argv); |
| 720 | warn("stderr:{}\n", result.stderr); | |
| 721 | std.debug.panic("command failed"); | |
| 747 | std.debug.panic("exec failed"); | |
| 722 | 748 | }, |
| 723 | 749 | } |
| 750 | ||
| 751 | return stdout.toOwnedSlice(); | |
| 724 | 752 | } |
| 725 | 753 | |
| 726 | 754 | pub fn addSearchPrefix(self: *Builder, search_prefix: []const u8) void { |
| ... | ... | @@ -837,26 +865,20 @@ pub const LibExeObjStep = struct { |
| 837 | 865 | builder: *Builder, |
| 838 | 866 | name: []const u8, |
| 839 | 867 | target: Target, |
| 840 | link_libs: BufSet, | |
| 841 | 868 | linker_script: ?[]const u8, |
| 842 | 869 | out_filename: []const u8, |
| 843 | output_path: ?[]const u8, | |
| 844 | output_lib_path: ?[]const u8, | |
| 845 | 870 | static: bool, |
| 846 | 871 | version: Version, |
| 847 | object_files: ArrayList([]const u8), | |
| 848 | 872 | build_mode: builtin.Mode, |
| 849 | 873 | kind: Kind, |
| 850 | 874 | major_only_filename: []const u8, |
| 851 | 875 | name_only_filename: []const u8, |
| 852 | 876 | strip: bool, |
| 853 | full_path_libs: ArrayList([]const u8), | |
| 854 | need_flat_namespace_hack: bool, | |
| 855 | include_dirs: ArrayList([]const u8), | |
| 856 | 877 | lib_paths: ArrayList([]const u8), |
| 857 | 878 | frameworks: BufSet, |
| 858 | 879 | verbose_link: bool, |
| 859 | 880 | verbose_cc: bool, |
| 881 | disable_gen_h: bool, | |
| 860 | 882 | c_std: Builder.CStd, |
| 861 | 883 | override_std_dir: ?[]const u8, |
| 862 | 884 | main_pkg_path: ?[]const u8, |
| ... | ... | @@ -865,17 +887,31 @@ pub const LibExeObjStep = struct { |
| 865 | 887 | filter: ?[]const u8, |
| 866 | 888 | |
| 867 | 889 | root_src: ?[]const u8, |
| 868 | output_h_path: ?[]const u8, | |
| 869 | 890 | out_h_filename: []const u8, |
| 870 | 891 | out_lib_filename: []const u8, |
| 871 | assembly_files: ArrayList([]const u8), | |
| 872 | 892 | packages: ArrayList(Pkg), |
| 873 | 893 | build_options_contents: std.Buffer, |
| 874 | 894 | system_linker_hack: bool, |
| 875 | 895 | |
| 876 | c_source_files: ArrayList(*CSourceFile), | |
| 877 | 896 | object_src: []const u8, |
| 878 | 897 | |
| 898 | link_objects: ArrayList(LinkObject), | |
| 899 | include_dirs: ArrayList(IncludeDir), | |
| 900 | output_dir: ?[]const u8, | |
| 901 | ||
| 902 | const LinkObject = union(enum) { | |
| 903 | StaticPath: []const u8, | |
| 904 | OtherStep: *LibExeObjStep, | |
| 905 | SystemLib: []const u8, | |
| 906 | AssemblyFile: []const u8, | |
| 907 | CSourceFile: *CSourceFile, | |
| 908 | }; | |
| 909 | ||
| 910 | const IncludeDir = union(enum) { | |
| 911 | RawPath: []const u8, | |
| 912 | OtherStep: *LibExeObjStep, | |
| 913 | }; | |
| 914 | ||
| 879 | 915 | const Kind = enum { |
| 880 | 916 | Exe, |
| 881 | 917 | Lib, |
| ... | ... | @@ -926,25 +962,17 @@ pub const LibExeObjStep = struct { |
| 926 | 962 | .name = name, |
| 927 | 963 | .target = Target.Native, |
| 928 | 964 | .linker_script = null, |
| 929 | .link_libs = BufSet.init(builder.allocator), | |
| 930 | 965 | .frameworks = BufSet.init(builder.allocator), |
| 931 | 966 | .step = Step.init(name, builder.allocator, make), |
| 932 | .output_path = null, | |
| 933 | .output_lib_path = null, | |
| 934 | .output_h_path = null, | |
| 935 | 967 | .version = ver, |
| 936 | 968 | .out_filename = undefined, |
| 937 | 969 | .out_h_filename = builder.fmt("{}.h", name), |
| 938 | 970 | .out_lib_filename = undefined, |
| 939 | 971 | .major_only_filename = undefined, |
| 940 | 972 | .name_only_filename = undefined, |
| 941 | .object_files = ArrayList([]const u8).init(builder.allocator), | |
| 942 | .assembly_files = ArrayList([]const u8).init(builder.allocator), | |
| 943 | 973 | .packages = ArrayList(Pkg).init(builder.allocator), |
| 944 | .full_path_libs = ArrayList([]const u8).init(builder.allocator), | |
| 945 | .need_flat_namespace_hack = false, | |
| 946 | .c_source_files = ArrayList(*CSourceFile).init(builder.allocator), | |
| 947 | .include_dirs = ArrayList([]const u8).init(builder.allocator), | |
| 974 | .include_dirs = ArrayList(IncludeDir).init(builder.allocator), | |
| 975 | .link_objects = ArrayList(LinkObject).init(builder.allocator), | |
| 948 | 976 | .lib_paths = ArrayList([]const u8).init(builder.allocator), |
| 949 | 977 | .object_src = undefined, |
| 950 | 978 | .build_options_contents = std.Buffer.initSize(builder.allocator, 0) catch unreachable, |
| ... | ... | @@ -955,6 +983,8 @@ pub const LibExeObjStep = struct { |
| 955 | 983 | .exec_cmd_args = null, |
| 956 | 984 | .name_prefix = "", |
| 957 | 985 | .filter = null, |
| 986 | .disable_gen_h = false, | |
| 987 | .output_dir = null, | |
| 958 | 988 | }; |
| 959 | 989 | self.computeOutFileNames(); |
| 960 | 990 | return self; |
| ... | ... | @@ -1022,7 +1052,19 @@ pub const LibExeObjStep = struct { |
| 1022 | 1052 | self.computeOutFileNames(); |
| 1023 | 1053 | } |
| 1024 | 1054 | |
| 1025 | // TODO respect this in the C args | |
| 1055 | pub fn setOutputDir(self: *LibExeObjStep, dir: []const u8) void { | |
| 1056 | self.output_dir = self.builder.dupe(dir); | |
| 1057 | } | |
| 1058 | ||
| 1059 | /// Creates a `RunStep` with an executable built with `addExecutable`. | |
| 1060 | /// Add command line arguments with `addArg`. | |
| 1061 | pub fn run(exe: *LibExeObjStep) *RunStep { | |
| 1062 | assert(exe.kind == Kind.Exe); | |
| 1063 | const run_step = RunStep.create(exe.builder, exe.builder.fmt("run {}", exe.step.name)); | |
| 1064 | run_step.addArtifactArg(exe); | |
| 1065 | return run_step; | |
| 1066 | } | |
| 1067 | ||
| 1026 | 1068 | pub fn setLinkerScriptPath(self: *LibExeObjStep, path: []const u8) void { |
| 1027 | 1069 | self.linker_script = path; |
| 1028 | 1070 | } |
| ... | ... | @@ -1032,37 +1074,28 @@ pub const LibExeObjStep = struct { |
| 1032 | 1074 | self.frameworks.put(framework_name) catch unreachable; |
| 1033 | 1075 | } |
| 1034 | 1076 | |
| 1035 | pub fn linkLibrary(self: *LibExeObjStep, lib: *LibExeObjStep) void { | |
| 1036 | assert(self.kind != Kind.Obj); | |
| 1037 | assert(lib.kind == Kind.Lib); | |
| 1038 | ||
| 1039 | self.step.dependOn(&lib.step); | |
| 1040 | ||
| 1041 | if (lib.static or self.target.isWindows()) { | |
| 1042 | self.object_files.append(lib.getOutputLibPath()) catch unreachable; | |
| 1043 | } else { | |
| 1044 | self.full_path_libs.append(lib.getOutputPath()) catch unreachable; | |
| 1045 | } | |
| 1046 | ||
| 1047 | if (lib.link_libs.exists("c")) { | |
| 1048 | self.link_libs.put("c") catch unreachable; | |
| 1077 | /// Returns whether the library, executable, or object depends on a particular system library. | |
| 1078 | pub fn dependsOnSystemLibrary(self: LibExeObjStep, name: []const u8) bool { | |
| 1079 | for (self.link_objects.toSliceConst()) |link_object| { | |
| 1080 | switch (link_object) { | |
| 1081 | LinkObject.SystemLib => |n| if (mem.eql(u8, n, name)) return true, | |
| 1082 | else => continue, | |
| 1083 | } | |
| 1049 | 1084 | } |
| 1085 | return false; | |
| 1086 | } | |
| 1050 | 1087 | |
| 1051 | // TODO should be some kind of isolated directory that only has this header in it | |
| 1052 | self.include_dirs.append(self.builder.cache_root) catch unreachable; | |
| 1053 | self.need_flat_namespace_hack = true; | |
| 1088 | pub fn linkLibrary(self: *LibExeObjStep, lib: *LibExeObjStep) void { | |
| 1089 | assert(lib.kind == Kind.Lib); | |
| 1090 | self.linkLibraryOrObject(lib); | |
| 1091 | } | |
| 1054 | 1092 | |
| 1055 | // inherit the object's frameworks | |
| 1056 | if (self.target.isDarwin() and lib.static) { | |
| 1057 | var it = lib.frameworks.iterator(); | |
| 1058 | while (it.next()) |entry| { | |
| 1059 | self.frameworks.put(entry.key) catch unreachable; | |
| 1060 | } | |
| 1061 | } | |
| 1093 | pub fn isDynamicLibrary(self: *LibExeObjStep) bool { | |
| 1094 | return self.kind == Kind.Lib and !self.static; | |
| 1062 | 1095 | } |
| 1063 | 1096 | |
| 1064 | 1097 | pub fn linkSystemLibrary(self: *LibExeObjStep, name: []const u8) void { |
| 1065 | self.link_libs.put(name) catch unreachable; | |
| 1098 | self.link_objects.append(LinkObject{ .SystemLib = self.builder.dupe(name) }) catch unreachable; | |
| 1066 | 1099 | } |
| 1067 | 1100 | |
| 1068 | 1101 | pub fn setNamePrefix(self: *LibExeObjStep, text: []const u8) void { |
| ... | ... | @@ -1077,11 +1110,15 @@ pub const LibExeObjStep = struct { |
| 1077 | 1110 | |
| 1078 | 1111 | pub fn addCSourceFile(self: *LibExeObjStep, file: []const u8, args: []const []const u8) void { |
| 1079 | 1112 | const c_source_file = self.builder.allocator.create(CSourceFile) catch unreachable; |
| 1113 | const args_copy = self.builder.allocator.alloc([]u8, args.len) catch unreachable; | |
| 1114 | for (args) |arg, i| { | |
| 1115 | args_copy[i] = self.builder.dupe(arg); | |
| 1116 | } | |
| 1080 | 1117 | c_source_file.* = CSourceFile{ |
| 1081 | .source_path = file, | |
| 1082 | .args = args, | |
| 1118 | .source_path = self.builder.dupe(file), | |
| 1119 | .args = args_copy, | |
| 1083 | 1120 | }; |
| 1084 | self.c_source_files.append(c_source_file) catch unreachable; | |
| 1121 | self.link_objects.append(LinkObject{ .CSourceFile = c_source_file }) catch unreachable; | |
| 1085 | 1122 | } |
| 1086 | 1123 | |
| 1087 | 1124 | pub fn setVerboseLink(self: *LibExeObjStep, value: bool) void { |
| ... | ... | @@ -1104,78 +1141,48 @@ pub const LibExeObjStep = struct { |
| 1104 | 1141 | self.main_pkg_path = dir_path; |
| 1105 | 1142 | } |
| 1106 | 1143 | |
| 1107 | pub fn setOutputPath(self: *LibExeObjStep, file_path: []const u8) void { | |
| 1108 | self.output_path = file_path; | |
| 1109 | ||
| 1110 | // catch a common mistake | |
| 1111 | if (mem.eql(u8, self.builder.pathFromRoot(file_path), self.builder.pathFromRoot("."))) { | |
| 1112 | debug.panic("setOutputPath wants a file path, not a directory\n"); | |
| 1113 | } | |
| 1114 | } | |
| 1115 | ||
| 1144 | /// Unless setOutputDir was called, this function must be called only in | |
| 1145 | /// the make step, from a step that has declared a dependency on this one. | |
| 1146 | /// To run an executable built with zig build, use `run`, or create an install step and invoke it. | |
| 1116 | 1147 | pub fn getOutputPath(self: *LibExeObjStep) []const u8 { |
| 1117 | return if (self.output_path) |output_path| output_path else os.path.join( | |
| 1148 | return os.path.join( | |
| 1118 | 1149 | self.builder.allocator, |
| 1119 | [][]const u8{ self.builder.cache_root, self.out_filename }, | |
| 1150 | [][]const u8{ self.output_dir.?, self.out_filename }, | |
| 1120 | 1151 | ) catch unreachable; |
| 1121 | 1152 | } |
| 1122 | 1153 | |
| 1123 | pub fn setOutputLibPath(self: *LibExeObjStep, file_path: []const u8) void { | |
| 1124 | assert(self.kind == Kind.Lib); | |
| 1125 | if (self.static) | |
| 1126 | return self.setOutputPath(file_path); | |
| 1127 | ||
| 1128 | self.output_lib_path = file_path; | |
| 1129 | } | |
| 1130 | ||
| 1154 | /// Unless setOutputDir was called, this function must be called only in | |
| 1155 | /// the make step, from a step that has declared a dependency on this one. | |
| 1131 | 1156 | pub fn getOutputLibPath(self: *LibExeObjStep) []const u8 { |
| 1132 | 1157 | assert(self.kind == Kind.Lib); |
| 1133 | return if (self.output_lib_path) |output_lib_path| output_lib_path else os.path.join( | |
| 1158 | return os.path.join( | |
| 1134 | 1159 | self.builder.allocator, |
| 1135 | [][]const u8{ self.builder.cache_root, self.out_lib_filename }, | |
| 1160 | [][]const u8{ self.output_dir.?, self.out_lib_filename }, | |
| 1136 | 1161 | ) catch unreachable; |
| 1137 | 1162 | } |
| 1138 | 1163 | |
| 1139 | pub fn setOutputHPath(self: *LibExeObjStep, file_path: []const u8) void { | |
| 1140 | self.output_h_path = file_path; | |
| 1141 | ||
| 1142 | // catch a common mistake | |
| 1143 | if (mem.eql(u8, self.builder.pathFromRoot(file_path), self.builder.pathFromRoot("."))) { | |
| 1144 | debug.panic("setOutputHPath wants a file path, not a directory\n"); | |
| 1145 | } | |
| 1146 | } | |
| 1147 | ||
| 1164 | /// Unless setOutputDir was called, this function must be called only in | |
| 1165 | /// the make step, from a step that has declared a dependency on this one. | |
| 1148 | 1166 | pub fn getOutputHPath(self: *LibExeObjStep) []const u8 { |
| 1149 | return if (self.output_h_path) |output_h_path| output_h_path else os.path.join( | |
| 1167 | assert(self.kind != Kind.Exe); | |
| 1168 | assert(!self.disable_gen_h); | |
| 1169 | return os.path.join( | |
| 1150 | 1170 | self.builder.allocator, |
| 1151 | [][]const u8{ self.builder.cache_root, self.out_h_filename }, | |
| 1171 | [][]const u8{ self.output_dir.?, self.out_h_filename }, | |
| 1152 | 1172 | ) catch unreachable; |
| 1153 | 1173 | } |
| 1154 | 1174 | |
| 1155 | 1175 | pub fn addAssemblyFile(self: *LibExeObjStep, path: []const u8) void { |
| 1156 | self.assembly_files.append(path) catch unreachable; | |
| 1176 | self.link_objects.append(LinkObject{ .AssemblyFile = self.builder.dupe(path) }) catch unreachable; | |
| 1157 | 1177 | } |
| 1158 | 1178 | |
| 1159 | 1179 | pub fn addObjectFile(self: *LibExeObjStep, path: []const u8) void { |
| 1160 | assert(self.kind != Kind.Obj); | |
| 1161 | ||
| 1162 | self.object_files.append(path) catch unreachable; | |
| 1180 | self.link_objects.append(LinkObject{ .StaticPath = self.builder.dupe(path) }) catch unreachable; | |
| 1163 | 1181 | } |
| 1164 | 1182 | |
| 1165 | 1183 | pub fn addObject(self: *LibExeObjStep, obj: *LibExeObjStep) void { |
| 1166 | 1184 | assert(obj.kind == Kind.Obj); |
| 1167 | assert(self.kind != Kind.Obj); | |
| 1168 | ||
| 1169 | self.step.dependOn(&obj.step); | |
| 1170 | ||
| 1171 | self.object_files.append(obj.getOutputPath()) catch unreachable; | |
| 1172 | ||
| 1173 | // TODO should be some kind of isolated directory that only has this header in it | |
| 1174 | self.include_dirs.append(self.builder.cache_root) catch unreachable; | |
| 1175 | ||
| 1176 | if (obj.link_libs.exists("c")) { | |
| 1177 | self.link_libs.put("c") catch unreachable; | |
| 1178 | } | |
| 1185 | self.linkLibraryOrObject(obj); | |
| 1179 | 1186 | } |
| 1180 | 1187 | |
| 1181 | 1188 | pub fn addBuildOption(self: *LibExeObjStep, comptime T: type, name: []const u8, value: T) void { |
| ... | ... | @@ -1184,7 +1191,7 @@ pub const LibExeObjStep = struct { |
| 1184 | 1191 | } |
| 1185 | 1192 | |
| 1186 | 1193 | pub fn addIncludeDir(self: *LibExeObjStep, path: []const u8) void { |
| 1187 | self.include_dirs.append(path) catch unreachable; | |
| 1194 | self.include_dirs.append(IncludeDir{ .RawPath = self.builder.dupe(path) }) catch unreachable; | |
| 1188 | 1195 | } |
| 1189 | 1196 | |
| 1190 | 1197 | pub fn addLibPath(self: *LibExeObjStep, path: []const u8) void { |
| ... | ... | @@ -1207,13 +1214,30 @@ pub const LibExeObjStep = struct { |
| 1207 | 1214 | self.system_linker_hack = true; |
| 1208 | 1215 | } |
| 1209 | 1216 | |
| 1217 | fn linkLibraryOrObject(self: *LibExeObjStep, other: *LibExeObjStep) void { | |
| 1218 | self.step.dependOn(&other.step); | |
| 1219 | self.link_objects.append(LinkObject{ .OtherStep = other }) catch unreachable; | |
| 1220 | self.include_dirs.append(IncludeDir{ .OtherStep = other }) catch unreachable; | |
| 1221 | ||
| 1222 | // Inherit dependency on libc | |
| 1223 | if (other.dependsOnSystemLibrary("c")) { | |
| 1224 | self.linkSystemLibrary("c"); | |
| 1225 | } | |
| 1226 | ||
| 1227 | // Inherit dependencies on darwin frameworks | |
| 1228 | if (self.target.isDarwin() and !other.isDynamicLibrary()) { | |
| 1229 | var it = other.frameworks.iterator(); | |
| 1230 | while (it.next()) |entry| { | |
| 1231 | self.frameworks.put(entry.key) catch unreachable; | |
| 1232 | } | |
| 1233 | } | |
| 1234 | } | |
| 1235 | ||
| 1210 | 1236 | fn make(step: *Step) !void { |
| 1211 | 1237 | const self = @fieldParentPtr(LibExeObjStep, "step", step); |
| 1212 | 1238 | const builder = self.builder; |
| 1213 | 1239 | |
| 1214 | if (self.root_src == null and self.object_files.len == 0 and | |
| 1215 | self.assembly_files.len == 0 and self.c_source_files.len == 0) | |
| 1216 | { | |
| 1240 | if (self.root_src == null and self.link_objects.len == 0) { | |
| 1217 | 1241 | warn("{}: linker needs 1 or more objects to link\n", self.step.name); |
| 1218 | 1242 | return error.NeedAnObject; |
| 1219 | 1243 | } |
| ... | ... | @@ -1235,12 +1259,52 @@ pub const LibExeObjStep = struct { |
| 1235 | 1259 | zig_args.append(builder.pathFromRoot(root_src)) catch unreachable; |
| 1236 | 1260 | } |
| 1237 | 1261 | |
| 1238 | for (self.c_source_files.toSliceConst()) |c_source_file| { | |
| 1239 | try zig_args.append("--c-source"); | |
| 1240 | for (c_source_file.args) |arg| { | |
| 1241 | try zig_args.append(arg); | |
| 1262 | for (self.link_objects.toSlice()) |link_object| { | |
| 1263 | switch (link_object) { | |
| 1264 | LinkObject.StaticPath => |static_path| { | |
| 1265 | try zig_args.append("--object"); | |
| 1266 | try zig_args.append(builder.pathFromRoot(static_path)); | |
| 1267 | }, | |
| 1268 | ||
| 1269 | LinkObject.OtherStep => |other| switch (other.kind) { | |
| 1270 | LibExeObjStep.Kind.Exe => unreachable, | |
| 1271 | LibExeObjStep.Kind.Test => unreachable, | |
| 1272 | LibExeObjStep.Kind.Obj => { | |
| 1273 | try zig_args.append("--object"); | |
| 1274 | try zig_args.append(other.getOutputPath()); | |
| 1275 | }, | |
| 1276 | LibExeObjStep.Kind.Lib => { | |
| 1277 | if (other.static or self.target.isWindows()) { | |
| 1278 | try zig_args.append("--object"); | |
| 1279 | try zig_args.append(other.getOutputPath()); | |
| 1280 | } else { | |
| 1281 | const full_path_lib = other.getOutputPath(); | |
| 1282 | try zig_args.append("--library"); | |
| 1283 | try zig_args.append(full_path_lib); | |
| 1284 | ||
| 1285 | if (os.path.dirname(full_path_lib)) |dirname| { | |
| 1286 | try zig_args.append("-rpath"); | |
| 1287 | try zig_args.append(dirname); | |
| 1288 | } | |
| 1289 | } | |
| 1290 | }, | |
| 1291 | }, | |
| 1292 | LinkObject.SystemLib => |name| { | |
| 1293 | try zig_args.append("--library"); | |
| 1294 | try zig_args.append(name); | |
| 1295 | }, | |
| 1296 | LinkObject.AssemblyFile => |asm_file| { | |
| 1297 | try zig_args.append("--assembly"); | |
| 1298 | try zig_args.append(builder.pathFromRoot(asm_file)); | |
| 1299 | }, | |
| 1300 | LinkObject.CSourceFile => |c_source_file| { | |
| 1301 | try zig_args.append("--c-source"); | |
| 1302 | for (c_source_file.args) |arg| { | |
| 1303 | try zig_args.append(arg); | |
| 1304 | } | |
| 1305 | try zig_args.append(self.builder.pathFromRoot(c_source_file.source_path)); | |
| 1306 | }, | |
| 1242 | 1307 | } |
| 1243 | try zig_args.append(self.builder.pathFromRoot(c_source_file.source_path)); | |
| 1244 | 1308 | } |
| 1245 | 1309 | |
| 1246 | 1310 | if (self.build_options_contents.len() > 0) { |
| ... | ... | @@ -1265,16 +1329,6 @@ pub const LibExeObjStep = struct { |
| 1265 | 1329 | try zig_args.append(self.name_prefix); |
| 1266 | 1330 | } |
| 1267 | 1331 | |
| 1268 | for (self.object_files.toSliceConst()) |object_file| { | |
| 1269 | zig_args.append("--object") catch unreachable; | |
| 1270 | zig_args.append(builder.pathFromRoot(object_file)) catch unreachable; | |
| 1271 | } | |
| 1272 | ||
| 1273 | for (self.assembly_files.toSliceConst()) |asm_file| { | |
| 1274 | zig_args.append("--assembly") catch unreachable; | |
| 1275 | zig_args.append(builder.pathFromRoot(asm_file)) catch unreachable; | |
| 1276 | } | |
| 1277 | ||
| 1278 | 1332 | if (builder.verbose_tokenize) zig_args.append("--verbose-tokenize") catch unreachable; |
| 1279 | 1333 | if (builder.verbose_ast) zig_args.append("--verbose-ast") catch unreachable; |
| 1280 | 1334 | if (builder.verbose_cimport) zig_args.append("--verbose-cimport") catch unreachable; |
| ... | ... | @@ -1294,24 +1348,8 @@ pub const LibExeObjStep = struct { |
| 1294 | 1348 | builtin.Mode.ReleaseSmall => zig_args.append("--release-small") catch unreachable, |
| 1295 | 1349 | } |
| 1296 | 1350 | |
| 1297 | zig_args.append("--cache-dir") catch unreachable; | |
| 1298 | zig_args.append(builder.pathFromRoot(builder.cache_root)) catch unreachable; | |
| 1299 | ||
| 1300 | const output_path = builder.pathFromRoot(self.getOutputPath()); | |
| 1301 | zig_args.append("--output") catch unreachable; | |
| 1302 | zig_args.append(output_path) catch unreachable; | |
| 1303 | ||
| 1304 | if (self.kind == Kind.Lib and !self.static) { | |
| 1305 | const output_lib_path = builder.pathFromRoot(self.getOutputLibPath()); | |
| 1306 | zig_args.append("--output-lib") catch unreachable; | |
| 1307 | zig_args.append(output_lib_path) catch unreachable; | |
| 1308 | } | |
| 1309 | ||
| 1310 | if (self.kind != Kind.Exe and self.root_src != null) { | |
| 1311 | const output_h_path = self.getOutputHPath(); | |
| 1312 | zig_args.append("--output-h") catch unreachable; | |
| 1313 | zig_args.append(builder.pathFromRoot(output_h_path)) catch unreachable; | |
| 1314 | } | |
| 1351 | try zig_args.append("--cache-dir"); | |
| 1352 | try zig_args.append(builder.pathFromRoot(builder.cache_root)); | |
| 1315 | 1353 | |
| 1316 | 1354 | zig_args.append("--name") catch unreachable; |
| 1317 | 1355 | zig_args.append(self.name) catch unreachable; |
| ... | ... | @@ -1351,15 +1389,6 @@ pub const LibExeObjStep = struct { |
| 1351 | 1389 | zig_args.append(linker_script) catch unreachable; |
| 1352 | 1390 | } |
| 1353 | 1391 | |
| 1354 | { | |
| 1355 | var it = self.link_libs.iterator(); | |
| 1356 | while (true) { | |
| 1357 | const entry = it.next() orelse break; | |
| 1358 | zig_args.append("--library") catch unreachable; | |
| 1359 | zig_args.append(entry.key) catch unreachable; | |
| 1360 | } | |
| 1361 | } | |
| 1362 | ||
| 1363 | 1392 | if (self.exec_cmd_args) |exec_cmd_args| { |
| 1364 | 1393 | for (exec_cmd_args) |cmd_arg| { |
| 1365 | 1394 | if (cmd_arg) |arg| { |
| ... | ... | @@ -1377,9 +1406,18 @@ pub const LibExeObjStep = struct { |
| 1377 | 1406 | zig_args.append("--pkg-end") catch unreachable; |
| 1378 | 1407 | } |
| 1379 | 1408 | |
| 1380 | for (self.include_dirs.toSliceConst()) |include_path| { | |
| 1381 | zig_args.append("-isystem") catch unreachable; | |
| 1382 | zig_args.append(self.builder.pathFromRoot(include_path)) catch unreachable; | |
| 1409 | for (self.include_dirs.toSliceConst()) |include_dir| { | |
| 1410 | switch (include_dir) { | |
| 1411 | IncludeDir.RawPath => |include_path| { | |
| 1412 | try zig_args.append("-isystem"); | |
| 1413 | try zig_args.append(self.builder.pathFromRoot(include_path)); | |
| 1414 | }, | |
| 1415 | IncludeDir.OtherStep => |other| { | |
| 1416 | const h_path = other.getOutputHPath(); | |
| 1417 | try zig_args.append("-isystem"); | |
| 1418 | try zig_args.append(os.path.dirname(h_path).?); | |
| 1419 | }, | |
| 1420 | } | |
| 1383 | 1421 | } |
| 1384 | 1422 | |
| 1385 | 1423 | for (builder.include_paths.toSliceConst()) |include_path| { |
| ... | ... | @@ -1402,17 +1440,6 @@ pub const LibExeObjStep = struct { |
| 1402 | 1440 | zig_args.append(lib_path) catch unreachable; |
| 1403 | 1441 | } |
| 1404 | 1442 | |
| 1405 | for (self.full_path_libs.toSliceConst()) |full_path_lib| { | |
| 1406 | try zig_args.append("--library"); | |
| 1407 | try zig_args.append(builder.pathFromRoot(full_path_lib)); | |
| 1408 | ||
| 1409 | const full_path_lib_abs = builder.pathFromRoot(full_path_lib); | |
| 1410 | if (os.path.dirname(full_path_lib_abs)) |dirname| { | |
| 1411 | try zig_args.append("-rpath"); | |
| 1412 | try zig_args.append(dirname); | |
| 1413 | } | |
| 1414 | } | |
| 1415 | ||
| 1416 | 1443 | if (self.target.isDarwin()) { |
| 1417 | 1444 | var it = self.frameworks.iterator(); |
| 1418 | 1445 | while (it.next()) |entry| { |
| ... | ... | @@ -1435,42 +1462,96 @@ pub const LibExeObjStep = struct { |
| 1435 | 1462 | try zig_args.append(builder.pathFromRoot(dir)); |
| 1436 | 1463 | } |
| 1437 | 1464 | |
| 1438 | try builder.spawnChild(zig_args.toSliceConst()); | |
| 1465 | if (self.output_dir) |output_dir| { | |
| 1466 | try zig_args.append("--output-dir"); | |
| 1467 | try zig_args.append(output_dir); | |
| 1468 | ||
| 1469 | try builder.spawnChild(zig_args.toSliceConst()); | |
| 1470 | } else if (self.kind == Kind.Test) { | |
| 1471 | try builder.spawnChild(zig_args.toSliceConst()); | |
| 1472 | } else { | |
| 1473 | try zig_args.append("--cache"); | |
| 1474 | try zig_args.append("on"); | |
| 1475 | ||
| 1476 | const output_path_nl = try builder.exec(zig_args.toSliceConst()); | |
| 1477 | const output_path = mem.trimRight(u8, output_path_nl, "\r\n"); | |
| 1478 | self.output_dir = os.path.dirname(output_path).?; | |
| 1479 | } | |
| 1439 | 1480 | |
| 1440 | 1481 | if (self.kind == Kind.Lib and !self.static and self.target.wantSharedLibSymLinks()) { |
| 1441 | try doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename, self.name_only_filename); | |
| 1482 | try doAtomicSymLinks(builder.allocator, self.getOutputPath(), self.major_only_filename, self.name_only_filename); | |
| 1442 | 1483 | } |
| 1443 | 1484 | } |
| 1444 | 1485 | }; |
| 1445 | 1486 | |
| 1446 | pub const CommandStep = struct { | |
| 1487 | pub const RunStep = struct { | |
| 1447 | 1488 | step: Step, |
| 1448 | 1489 | builder: *Builder, |
| 1449 | argv: [][]const u8, | |
| 1490 | ||
| 1491 | /// See also addArg and addArgs to modifying this directly | |
| 1492 | argv: ArrayList(Arg), | |
| 1493 | ||
| 1494 | /// Set this to modify the current working directory | |
| 1450 | 1495 | cwd: ?[]const u8, |
| 1451 | env_map: *const BufMap, | |
| 1452 | 1496 | |
| 1453 | /// ::argv is copied. | |
| 1454 | pub fn create(builder: *Builder, cwd: ?[]const u8, env_map: *const BufMap, argv: []const []const u8) *CommandStep { | |
| 1455 | const self = builder.allocator.create(CommandStep) catch unreachable; | |
| 1456 | self.* = CommandStep{ | |
| 1497 | /// Override this field to modify the environment, or use setEnvironmentVariable | |
| 1498 | env_map: ?*const BufMap, | |
| 1499 | ||
| 1500 | pub const Arg = union(enum) { | |
| 1501 | Artifact: *LibExeObjStep, | |
| 1502 | Bytes: []u8, | |
| 1503 | }; | |
| 1504 | ||
| 1505 | pub fn create(builder: *Builder, name: []const u8) *RunStep { | |
| 1506 | const self = builder.allocator.create(RunStep) catch unreachable; | |
| 1507 | self.* = RunStep{ | |
| 1457 | 1508 | .builder = builder, |
| 1458 | .step = Step.init(argv[0], builder.allocator, make), | |
| 1459 | .argv = builder.allocator.alloc([]u8, argv.len) catch unreachable, | |
| 1460 | .cwd = cwd, | |
| 1461 | .env_map = env_map, | |
| 1509 | .step = Step.init(name, builder.allocator, make), | |
| 1510 | .argv = ArrayList(Arg).init(builder.allocator), | |
| 1511 | .cwd = null, | |
| 1512 | .env_map = null, | |
| 1462 | 1513 | }; |
| 1463 | ||
| 1464 | mem.copy([]const u8, self.argv, argv); | |
| 1465 | self.step.name = self.argv[0]; | |
| 1466 | 1514 | return self; |
| 1467 | 1515 | } |
| 1468 | 1516 | |
| 1517 | pub fn addArtifactArg(self: *RunStep, artifact: *LibExeObjStep) void { | |
| 1518 | self.argv.append(Arg{ .Artifact = artifact }) catch unreachable; | |
| 1519 | self.step.dependOn(&artifact.step); | |
| 1520 | } | |
| 1521 | ||
| 1522 | pub fn addArg(self: *RunStep, arg: []const u8) void { | |
| 1523 | self.argv.append(Arg{ .Bytes = self.builder.dupe(arg) }) catch unreachable; | |
| 1524 | } | |
| 1525 | ||
| 1526 | pub fn addArgs(self: *RunStep, args: []const []const u8) void { | |
| 1527 | for (args) |arg| { | |
| 1528 | self.addArg(arg); | |
| 1529 | } | |
| 1530 | } | |
| 1531 | ||
| 1532 | pub fn setEnvironmentVariable(self: *RunStep, key: []const u8, value: []const u8) void { | |
| 1533 | const env_map = self.env_map orelse blk: { | |
| 1534 | const env_map = os.getEnvMap(allocator) catch unreachable; | |
| 1535 | self.env_map = env_map; | |
| 1536 | break :blk env_map; | |
| 1537 | }; | |
| 1538 | env_map.set(key, value) catch unreachable; | |
| 1539 | } | |
| 1540 | ||
| 1469 | 1541 | fn make(step: *Step) !void { |
| 1470 | const self = @fieldParentPtr(CommandStep, "step", step); | |
| 1542 | const self = @fieldParentPtr(RunStep, "step", step); | |
| 1471 | 1543 | |
| 1472 | 1544 | const cwd = if (self.cwd) |cwd| self.builder.pathFromRoot(cwd) else self.builder.build_root; |
| 1473 | return self.builder.spawnChildEnvMap(cwd, self.env_map, self.argv); | |
| 1545 | ||
| 1546 | var argv = ArrayList([]const u8).init(self.builder.allocator); | |
| 1547 | for (self.argv.toSlice()) |arg| { | |
| 1548 | switch (arg) { | |
| 1549 | Arg.Bytes => |bytes| try argv.append(bytes), | |
| 1550 | Arg.Artifact => |artifact| try argv.append(artifact.getOutputPath()), | |
| 1551 | } | |
| 1552 | } | |
| 1553 | ||
| 1554 | return self.builder.spawnChildEnvMap(cwd, self.env_map orelse self.builder.env_map, argv.toSliceConst()); | |
| 1474 | 1555 | } |
| 1475 | 1556 | }; |
| 1476 | 1557 |
std/special/init-exe/build.zig+2-2| ... | ... | @@ -5,10 +5,10 @@ pub fn build(b: *Builder) void { |
| 5 | 5 | const exe = b.addExecutable("$", "src/main.zig"); |
| 6 | 6 | exe.setBuildMode(mode); |
| 7 | 7 | |
| 8 | const run_cmd = exe.run(); | |
| 9 | ||
| 8 | 10 | const run_step = b.step("run", "Run the app"); |
| 9 | const run_cmd = b.addCommand(".", b.env_map, [][]const u8{exe.getOutputPath()}); | |
| 10 | 11 | run_step.dependOn(&run_cmd.step); |
| 11 | run_cmd.step.dependOn(&exe.step); | |
| 12 | 12 | |
| 13 | 13 | b.default_step.dependOn(&exe.step); |
| 14 | 14 | b.installArtifact(exe); |
test/cli.zig+3-3| ... | ... | @@ -116,12 +116,12 @@ fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void { |
| 116 | 116 | const args = [][]const u8{ |
| 117 | 117 | zig_exe, "build-obj", |
| 118 | 118 | "--cache-dir", dir_path, |
| 119 | "--output", example_s_path, | |
| 120 | "--output-h", "/dev/null", | |
| 119 | "--name", "example", | |
| 120 | "--output-dir", dir_path, | |
| 121 | 121 | "--emit", "asm", |
| 122 | 122 | "-mllvm", "--x86-asm-syntax=intel", |
| 123 | 123 | "--strip", "--release-fast", |
| 124 | example_zig_path, | |
| 124 | example_zig_path, "--disable-gen-h", | |
| 125 | 125 | }; |
| 126 | 126 | _ = try exec(dir_path, args); |
| 127 | 127 |
test/standalone/load_dynamic_library/build.zig+2-6| ... | ... | @@ -9,12 +9,8 @@ pub fn build(b: *Builder) void { |
| 9 | 9 | const main = b.addExecutable("main", "main.zig"); |
| 10 | 10 | main.setBuildMode(opts); |
| 11 | 11 | |
| 12 | const run = b.addCommand(".", b.env_map, [][]const u8{ | |
| 13 | main.getOutputPath(), | |
| 14 | lib.getOutputPath(), | |
| 15 | }); | |
| 16 | run.step.dependOn(&lib.step); | |
| 17 | run.step.dependOn(&main.step); | |
| 12 | const run = main.run(); | |
| 13 | run.addArtifactArg(lib); | |
| 18 | 14 | |
| 19 | 15 | const test_step = b.step("test", "Test the program"); |
| 20 | 16 | test_step.dependOn(&run.step); |
test/standalone/pkg_import/build.zig+1-2| ... | ... | @@ -9,8 +9,7 @@ pub fn build(b: *Builder) void { |
| 9 | 9 | exe.setBuildMode(b.standardReleaseOptions()); |
| 10 | 10 | exe.setBuildMode(b.standardReleaseOptions()); |
| 11 | 11 | |
| 12 | const run = b.addCommand(".", b.env_map, [][]const u8{exe.getOutputPath()}); | |
| 13 | run.step.dependOn(&exe.step); | |
| 12 | const run = exe.run(); | |
| 14 | 13 | |
| 15 | 14 | const test_step = b.step("test", "Test it"); |
| 16 | 15 | test_step.dependOn(&run.step); |
test/tests.zig+49-33| ... | ... | @@ -12,6 +12,7 @@ const fmt = std.fmt; |
| 12 | 12 | const ArrayList = std.ArrayList; |
| 13 | 13 | const builtin = @import("builtin"); |
| 14 | 14 | const Mode = builtin.Mode; |
| 15 | const LibExeObjStep = build.LibExeObjStep; | |
| 15 | 16 | |
| 16 | 17 | const compare_output = @import("compare_output.zig"); |
| 17 | 18 | const build_examples = @import("build_examples.zig"); |
| ... | ... | @@ -111,12 +112,11 @@ pub fn addCliTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const M |
| 111 | 112 | const step = b.step("test-cli", "Test the command line interface"); |
| 112 | 113 | |
| 113 | 114 | const exe = b.addExecutable("test-cli", "test/cli.zig"); |
| 114 | const run_cmd = b.addCommand(null, b.env_map, [][]const u8{ | |
| 115 | b.pathFromRoot(exe.getOutputPath()), | |
| 115 | const run_cmd = exe.run(); | |
| 116 | run_cmd.addArgs([][]const u8{ | |
| 116 | 117 | os.path.realAlloc(b.allocator, b.zig_exe) catch unreachable, |
| 117 | 118 | b.pathFromRoot(b.cache_root), |
| 118 | 119 | }); |
| 119 | run_cmd.step.dependOn(&exe.step); | |
| 120 | 120 | |
| 121 | 121 | step.dependOn(&run_cmd.step); |
| 122 | 122 | return step; |
| ... | ... | @@ -246,24 +246,31 @@ pub const CompareOutputContext = struct { |
| 246 | 246 | const RunCompareOutputStep = struct { |
| 247 | 247 | step: build.Step, |
| 248 | 248 | context: *CompareOutputContext, |
| 249 | exe_path: []const u8, | |
| 249 | exe: *LibExeObjStep, | |
| 250 | 250 | name: []const u8, |
| 251 | 251 | expected_output: []const u8, |
| 252 | 252 | test_index: usize, |
| 253 | 253 | cli_args: []const []const u8, |
| 254 | 254 | |
| 255 | pub fn create(context: *CompareOutputContext, exe_path: []const u8, name: []const u8, expected_output: []const u8, cli_args: []const []const u8) *RunCompareOutputStep { | |
| 255 | pub fn create( | |
| 256 | context: *CompareOutputContext, | |
| 257 | exe: *LibExeObjStep, | |
| 258 | name: []const u8, | |
| 259 | expected_output: []const u8, | |
| 260 | cli_args: []const []const u8, | |
| 261 | ) *RunCompareOutputStep { | |
| 256 | 262 | const allocator = context.b.allocator; |
| 257 | 263 | const ptr = allocator.create(RunCompareOutputStep) catch unreachable; |
| 258 | 264 | ptr.* = RunCompareOutputStep{ |
| 259 | 265 | .context = context, |
| 260 | .exe_path = exe_path, | |
| 266 | .exe = exe, | |
| 261 | 267 | .name = name, |
| 262 | 268 | .expected_output = expected_output, |
| 263 | 269 | .test_index = context.test_index, |
| 264 | 270 | .step = build.Step.init("RunCompareOutput", allocator, make), |
| 265 | 271 | .cli_args = cli_args, |
| 266 | 272 | }; |
| 273 | ptr.step.dependOn(&exe.step); | |
| 267 | 274 | context.test_index += 1; |
| 268 | 275 | return ptr; |
| 269 | 276 | } |
| ... | ... | @@ -272,7 +279,7 @@ pub const CompareOutputContext = struct { |
| 272 | 279 | const self = @fieldParentPtr(RunCompareOutputStep, "step", step); |
| 273 | 280 | const b = self.context.b; |
| 274 | 281 | |
| 275 | const full_exe_path = b.pathFromRoot(self.exe_path); | |
| 282 | const full_exe_path = self.exe.getOutputPath(); | |
| 276 | 283 | var args = ArrayList([]const u8).init(b.allocator); |
| 277 | 284 | defer args.deinit(); |
| 278 | 285 | |
| ... | ... | @@ -336,21 +343,21 @@ pub const CompareOutputContext = struct { |
| 336 | 343 | const RuntimeSafetyRunStep = struct { |
| 337 | 344 | step: build.Step, |
| 338 | 345 | context: *CompareOutputContext, |
| 339 | exe_path: []const u8, | |
| 346 | exe: *LibExeObjStep, | |
| 340 | 347 | name: []const u8, |
| 341 | 348 | test_index: usize, |
| 342 | 349 | |
| 343 | pub fn create(context: *CompareOutputContext, exe_path: []const u8, name: []const u8) *RuntimeSafetyRunStep { | |
| 350 | pub fn create(context: *CompareOutputContext, exe: *LibExeObjStep, name: []const u8) *RuntimeSafetyRunStep { | |
| 344 | 351 | const allocator = context.b.allocator; |
| 345 | 352 | const ptr = allocator.create(RuntimeSafetyRunStep) catch unreachable; |
| 346 | 353 | ptr.* = RuntimeSafetyRunStep{ |
| 347 | 354 | .context = context, |
| 348 | .exe_path = exe_path, | |
| 355 | .exe = exe, | |
| 349 | 356 | .name = name, |
| 350 | 357 | .test_index = context.test_index, |
| 351 | 358 | .step = build.Step.init("RuntimeSafetyRun", allocator, make), |
| 352 | 359 | }; |
| 353 | ||
| 360 | ptr.step.dependOn(&exe.step); | |
| 354 | 361 | context.test_index += 1; |
| 355 | 362 | return ptr; |
| 356 | 363 | } |
| ... | ... | @@ -359,11 +366,11 @@ pub const CompareOutputContext = struct { |
| 359 | 366 | const self = @fieldParentPtr(RuntimeSafetyRunStep, "step", step); |
| 360 | 367 | const b = self.context.b; |
| 361 | 368 | |
| 362 | const full_exe_path = b.pathFromRoot(self.exe_path); | |
| 369 | const full_exe_path = self.exe.getOutputPath(); | |
| 363 | 370 | |
| 364 | 371 | warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name); |
| 365 | 372 | |
| 366 | const child = os.ChildProcess.init([][]u8{full_exe_path}, b.allocator) catch unreachable; | |
| 373 | const child = os.ChildProcess.init([][]const u8{full_exe_path}, b.allocator) catch unreachable; | |
| 367 | 374 | defer child.deinit(); |
| 368 | 375 | |
| 369 | 376 | child.env_map = b.env_map; |
| ... | ... | @@ -463,8 +470,13 @@ pub const CompareOutputContext = struct { |
| 463 | 470 | exe.step.dependOn(&write_src.step); |
| 464 | 471 | } |
| 465 | 472 | |
| 466 | const run_and_cmp_output = RunCompareOutputStep.create(self, exe.getOutputPath(), annotated_case_name, case.expected_output, case.cli_args); | |
| 467 | run_and_cmp_output.step.dependOn(&exe.step); | |
| 473 | const run_and_cmp_output = RunCompareOutputStep.create( | |
| 474 | self, | |
| 475 | exe, | |
| 476 | annotated_case_name, | |
| 477 | case.expected_output, | |
| 478 | case.cli_args, | |
| 479 | ); | |
| 468 | 480 | |
| 469 | 481 | self.step.dependOn(&run_and_cmp_output.step); |
| 470 | 482 | }, |
| ... | ... | @@ -490,8 +502,13 @@ pub const CompareOutputContext = struct { |
| 490 | 502 | exe.step.dependOn(&write_src.step); |
| 491 | 503 | } |
| 492 | 504 | |
| 493 | const run_and_cmp_output = RunCompareOutputStep.create(self, exe.getOutputPath(), annotated_case_name, case.expected_output, case.cli_args); | |
| 494 | run_and_cmp_output.step.dependOn(&exe.step); | |
| 505 | const run_and_cmp_output = RunCompareOutputStep.create( | |
| 506 | self, | |
| 507 | exe, | |
| 508 | annotated_case_name, | |
| 509 | case.expected_output, | |
| 510 | case.cli_args, | |
| 511 | ); | |
| 495 | 512 | |
| 496 | 513 | self.step.dependOn(&run_and_cmp_output.step); |
| 497 | 514 | } |
| ... | ... | @@ -516,8 +533,7 @@ pub const CompareOutputContext = struct { |
| 516 | 533 | exe.step.dependOn(&write_src.step); |
| 517 | 534 | } |
| 518 | 535 | |
| 519 | const run_and_cmp_output = RuntimeSafetyRunStep.create(self, exe.getOutputPath(), annotated_case_name); | |
| 520 | run_and_cmp_output.step.dependOn(&exe.step); | |
| 536 | const run_and_cmp_output = RuntimeSafetyRunStep.create(self, exe, annotated_case_name); | |
| 521 | 537 | |
| 522 | 538 | self.step.dependOn(&run_and_cmp_output.step); |
| 523 | 539 | }, |
| ... | ... | @@ -608,10 +624,6 @@ pub const CompileErrorContext = struct { |
| 608 | 624 | b.allocator, |
| 609 | 625 | [][]const u8{ b.cache_root, self.case.sources.items[0].filename }, |
| 610 | 626 | ) catch unreachable; |
| 611 | const obj_path = os.path.join( | |
| 612 | b.allocator, | |
| 613 | [][]const u8{ b.cache_root, "test.o" }, | |
| 614 | ) catch unreachable; | |
| 615 | 627 | |
| 616 | 628 | var zig_args = ArrayList([]const u8).init(b.allocator); |
| 617 | 629 | zig_args.append(b.zig_exe) catch unreachable; |
| ... | ... | @@ -628,8 +640,8 @@ pub const CompileErrorContext = struct { |
| 628 | 640 | zig_args.append("--name") catch unreachable; |
| 629 | 641 | zig_args.append("test") catch unreachable; |
| 630 | 642 | |
| 631 | zig_args.append("--output") catch unreachable; | |
| 632 | zig_args.append(b.pathFromRoot(obj_path)) catch unreachable; | |
| 643 | zig_args.append("--output-dir") catch unreachable; | |
| 644 | zig_args.append(b.pathFromRoot(b.cache_root)) catch unreachable; | |
| 633 | 645 | |
| 634 | 646 | switch (self.build_mode) { |
| 635 | 647 | Mode.Debug => {}, |
| ... | ... | @@ -851,7 +863,7 @@ pub const BuildExamplesContext = struct { |
| 851 | 863 | zig_args.append("--verbose") catch unreachable; |
| 852 | 864 | } |
| 853 | 865 | |
| 854 | const run_cmd = b.addCommand(null, b.env_map, zig_args.toSliceConst()); | |
| 866 | const run_cmd = b.addSystemCommand(zig_args.toSliceConst()); | |
| 855 | 867 | |
| 856 | 868 | const log_step = b.addLog("PASS {}\n", annotated_case_name); |
| 857 | 869 | log_step.step.dependOn(&run_cmd.step); |
| ... | ... | @@ -1118,23 +1130,28 @@ pub const GenHContext = struct { |
| 1118 | 1130 | const GenHCmpOutputStep = struct { |
| 1119 | 1131 | step: build.Step, |
| 1120 | 1132 | context: *GenHContext, |
| 1121 | h_path: []const u8, | |
| 1133 | obj: *LibExeObjStep, | |
| 1122 | 1134 | name: []const u8, |
| 1123 | 1135 | test_index: usize, |
| 1124 | 1136 | case: *const TestCase, |
| 1125 | 1137 | |
| 1126 | pub fn create(context: *GenHContext, h_path: []const u8, name: []const u8, case: *const TestCase) *GenHCmpOutputStep { | |
| 1138 | pub fn create( | |
| 1139 | context: *GenHContext, | |
| 1140 | obj: *LibExeObjStep, | |
| 1141 | name: []const u8, | |
| 1142 | case: *const TestCase, | |
| 1143 | ) *GenHCmpOutputStep { | |
| 1127 | 1144 | const allocator = context.b.allocator; |
| 1128 | 1145 | const ptr = allocator.create(GenHCmpOutputStep) catch unreachable; |
| 1129 | 1146 | ptr.* = GenHCmpOutputStep{ |
| 1130 | 1147 | .step = build.Step.init("ParseCCmpOutput", allocator, make), |
| 1131 | 1148 | .context = context, |
| 1132 | .h_path = h_path, | |
| 1149 | .obj = obj, | |
| 1133 | 1150 | .name = name, |
| 1134 | 1151 | .test_index = context.test_index, |
| 1135 | 1152 | .case = case, |
| 1136 | 1153 | }; |
| 1137 | ||
| 1154 | ptr.step.dependOn(&obj.step); | |
| 1138 | 1155 | context.test_index += 1; |
| 1139 | 1156 | return ptr; |
| 1140 | 1157 | } |
| ... | ... | @@ -1145,7 +1162,7 @@ pub const GenHContext = struct { |
| 1145 | 1162 | |
| 1146 | 1163 | warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name); |
| 1147 | 1164 | |
| 1148 | const full_h_path = b.pathFromRoot(self.h_path); | |
| 1165 | const full_h_path = self.obj.getOutputHPath(); | |
| 1149 | 1166 | const actual_h = try io.readFileAlloc(b.allocator, full_h_path); |
| 1150 | 1167 | |
| 1151 | 1168 | for (self.case.expected_lines.toSliceConst()) |expected_line| { |
| ... | ... | @@ -1218,8 +1235,7 @@ pub const GenHContext = struct { |
| 1218 | 1235 | obj.step.dependOn(&write_src.step); |
| 1219 | 1236 | } |
| 1220 | 1237 | |
| 1221 | const cmp_h = GenHCmpOutputStep.create(self, obj.getOutputHPath(), annotated_case_name, case); | |
| 1222 | cmp_h.step.dependOn(&obj.step); | |
| 1238 | const cmp_h = GenHCmpOutputStep.create(self, obj, annotated_case_name, case); | |
| 1223 | 1239 | |
| 1224 | 1240 | self.step.dependOn(&cmp_h.step); |
| 1225 | 1241 | } |