authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-03-09 01:17:36-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-03-09 01:17:36-05:00
log8624379c71d79f67032d7ff2fd71642c84c79621
treefb34094e6738e469808cfd4318c751af759f5555
parentdd34c217791a0949ef2b0531ce8e8d4691239c45
parenta45807db22cf92167734d2055b836fa0aba8cf30
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #2038 from ziglang/caching

breaking changes to zig build API and improved caching

29 files changed, 751 insertions(+), 679 deletions(-)

build.zig+2-2
......@@ -20,8 +20,8 @@ pub fn build(b: *Builder) !void {
2020 b.allocator,
2121 [][]const u8{ b.cache_root, "langref.html" },
2222 ) 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{
2525 rel_zig_exe,
2626 "doc" ++ os.path.sep_str ++ "langref.html.in",
2727 langref_out_path,
doc/docgen.zig+14-12
......@@ -1011,8 +1011,10 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
10111011 zig_exe,
10121012 "build-exe",
10131013 tmp_source_file_name,
1014 "--output",
1015 tmp_bin_file_name,
1014 "--output-dir",
1015 tmp_dir_name,
1016 "--name",
1017 code.name,
10161018 });
10171019 try out.print("<pre><code class=\"shell\">$ zig build-exe {}.zig", code.name);
10181020 switch (code.mode) {
......@@ -1085,8 +1087,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
10851087 zig_exe,
10861088 "test",
10871089 tmp_source_file_name,
1088 "--output",
1089 test_out_path,
1090 "--output-dir",
1091 tmp_dir_name,
10901092 });
10911093 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", code.name);
10921094 switch (code.mode) {
......@@ -1122,8 +1124,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
11221124 "--color",
11231125 "on",
11241126 tmp_source_file_name,
1125 "--output",
1126 test_out_path,
1127 "--output-dir",
1128 tmp_dir_name,
11271129 });
11281130 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", code.name);
11291131 switch (code.mode) {
......@@ -1179,8 +1181,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
11791181 zig_exe,
11801182 "test",
11811183 tmp_source_file_name,
1182 "--output",
1183 test_out_path,
1184 "--output-dir",
1185 tmp_dir_name,
11841186 });
11851187 switch (code.mode) {
11861188 builtin.Mode.Debug => {},
......@@ -1239,10 +1241,10 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
12391241 tmp_source_file_name,
12401242 "--color",
12411243 "on",
1242 "--output",
1243 tmp_obj_file_name,
1244 "--output-h",
1245 output_h_file_name,
1244 "--name",
1245 code.name,
1246 "--output-dir",
1247 tmp_dir_name,
12461248 });
12471249
12481250 if (!code.is_inline) {
doc/langref.html.in+1-2
......@@ -7914,8 +7914,7 @@ pub fn build(b: *Builder) void {
79147914
79157915 b.default_step.dependOn(&exe.step);
79167916
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();
79197918
79207919 const test_step = b.step("test", "Test the program");
79217920 test_step.dependOn(&run_cmd.step);
example/mix_o_files/build.zig+2-3
......@@ -4,14 +4,13 @@ pub fn build(b: *Builder) void {
44 const obj = b.addObject("base64", "base64.zig");
55
66 const exe = b.addExecutable("test", null);
7 exe.addCSourceFile("test.c",[][]const u8{"-std=c99"});
7 exe.addCSourceFile("test.c", [][]const u8{"-std=c99"});
88 exe.addObject(obj);
99 exe.linkSystemLibrary("c");
1010
1111 b.default_step.dependOn(&exe.step);
1212
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();
1514
1615 const test_step = b.step("test", "Test the program");
1716 test_step.dependOn(&run_cmd.step);
example/shared_library/build.zig+1-2
......@@ -10,8 +10,7 @@ pub fn build(b: *Builder) void {
1010
1111 b.default_step.dependOn(&exe.step);
1212
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();
1514
1615 const test_step = b.step("test", "Test the program");
1716 test_step.dependOn(&run_cmd.step);
src/all_types.hpp+5-6
......@@ -1087,7 +1087,6 @@ struct RootStruct {
10871087 Buf *path; // relative to root_package->root_src_dir
10881088 ZigList<size_t> *line_offsets;
10891089 Buf *source_code;
1090 AstNode *c_import_node;
10911090 ZigLLVMDIFile *di_file;
10921091};
10931092
......@@ -1746,13 +1745,12 @@ struct CodeGen {
17461745
17471746 Buf triple_str;
17481747 Buf global_asm;
1749 Buf *out_h_path;
1750 Buf *out_lib_path;
1751 Buf artifact_dir;
17521748 Buf output_file_path;
17531749 Buf o_file_output_path;
1754 Buf *wanted_output_file_path;
17551750 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;
17561754 Buf **libc_include_dir_list;
17571755 size_t libc_include_dir_len;
17581756
......@@ -1804,7 +1802,7 @@ struct CodeGen {
18041802 bool verbose_cc;
18051803 bool error_during_imports;
18061804 bool generate_error_name_table;
1807 bool enable_cache;
1805 bool enable_cache; // mutually exclusive with output_dir
18081806 bool enable_time_report;
18091807 bool system_linker_hack;
18101808 bool reported_bad_link_libc_error;
......@@ -1844,6 +1842,7 @@ struct CodeGen {
18441842 bool each_lib_rpath;
18451843 bool disable_pic;
18461844 bool is_dummy_so;
1845 bool disable_gen_h;
18471846
18481847 Buf *mmacosx_version_min;
18491848 Buf *mios_version_min;
src/analyze.cpp+3-28
......@@ -35,20 +35,6 @@ static bool is_top_level_struct(ZigType *import) {
3535static ErrorMsg *add_error_note_token(CodeGen *g, ErrorMsg *parent_msg, ZigType *owner, Token *token, Buf *msg) {
3636 assert(is_top_level_struct(owner));
3737 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 }
5238
5339 ErrorMsg *err = err_msg_create_with_line(root_struct->path, token->start_line, token->start_column,
5440 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
6046ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, Token *token, Buf *msg) {
6147 assert(is_top_level_struct(owner));
6248 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 }
7449 ErrorMsg *err = err_msg_create_with_line(root_struct->path, token->start_line, token->start_column,
7550 root_struct->source_code, root_struct->line_offsets, msg);
7651
......@@ -1300,7 +1275,7 @@ static ZigTypeId container_to_type(ContainerKind kind) {
13001275}
13011276
13021277// This is like get_partial_container_type except it's for the implicit root struct of files.
1303ZigType *get_root_container_type(CodeGen *g, const char *full_name, Buf *bare_name,
1278static ZigType *get_root_container_type(CodeGen *g, const char *full_name, Buf *bare_name,
13041279 RootStruct *root_struct)
13051280{
13061281 ZigType *entry = new_type_table_entry(ZigTypeIdStruct);
......@@ -4503,11 +4478,11 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu
45034478 Buf *pkg_root_src_dir = &package->root_src_dir;
45044479 Buf resolved_root_src_dir = os_path_resolve(&pkg_root_src_dir, 1);
45054480
4506 assert(buf_starts_with_buf(resolved_path, &resolved_root_src_dir));
4507
45084481 Buf namespace_name = BUF_INIT;
45094482 buf_init_from_buf(&namespace_name, &package->pkg_path);
45104483 if (source_kind == SourceKindNonRoot) {
4484 assert(buf_starts_with_buf(resolved_path, &resolved_root_src_dir));
4485
45114486 if (buf_len(&namespace_name) != 0) buf_append_char(&namespace_name, NAMESPACE_SEP_CHAR);
45124487 buf_append_mem(&namespace_name, buf_ptr(&noextname) + buf_len(&resolved_root_src_dir) + 1,
45134488 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);
3131ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type);
3232ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,
3333 AstNode *decl_node, const char *full_name, Buf *bare_name, ContainerLayout layout);
34ZigType *get_root_container_type(CodeGen *g, const char *full_name, Buf *bare_name,
35 RootStruct *root_struct);
3634ZigType *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x);
3735ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payload_type);
3836ZigType *get_bound_fn_type(CodeGen *g, ZigFn *fn_entry);
......@@ -53,6 +51,7 @@ enum SourceKind {
5351 SourceKindRoot,
5452 SourceKindPkgMain,
5553 SourceKindNonRoot,
54 SourceKindCImport,
5655};
5756ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *abs_full_path, Buf *source_code,
5857 SourceKind source_kind);
......@@ -242,4 +241,6 @@ Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_no
242241void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn);
243242Buf *type_bare_name(ZigType *t);
244243Buf *type_h_name(ZigType *t);
244Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose);
245
245246#endif
src/ast_render.cpp+7-4
......@@ -317,7 +317,7 @@ static bool is_digit(uint8_t c) {
317317
318318static bool is_printable(uint8_t c) {
319319 static const uint8_t printables[] =
320 " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.~`!@#$%^&*()_-+=\\{}[];'\"?/<>,";
320 " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.~`!@#$%^&*()_-+=\\{}[];'\"?/<>,:";
321321 for (size_t i = 0; i < array_length(printables); i += 1) {
322322 if (c == printables[i]) return true;
323323 }
......@@ -328,9 +328,7 @@ static void string_literal_escape(Buf *source, Buf *dest) {
328328 buf_resize(dest, 0);
329329 for (size_t i = 0; i < buf_len(source); i += 1) {
330330 uint8_t c = *((uint8_t*)buf_ptr(source) + i);
331 if (is_printable(c)) {
332 buf_append_char(dest, c);
333 } else if (c == '\'') {
331 if (c == '\'') {
334332 buf_append_str(dest, "\\'");
335333 } else if (c == '"') {
336334 buf_append_str(dest, "\\\"");
......@@ -350,6 +348,8 @@ static void string_literal_escape(Buf *source, Buf *dest) {
350348 buf_append_str(dest, "\\t");
351349 } else if (c == '\v') {
352350 buf_append_str(dest, "\\v");
351 } else if (is_printable(c)) {
352 buf_append_char(dest, c);
353353 } else {
354354 buf_appendf(dest, "\\x%x", (int)c);
355355 }
......@@ -470,6 +470,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
470470 fprintf(ar->f, ", ");
471471 }
472472 }
473 if (node->data.fn_proto.is_var_args) {
474 fprintf(ar->f, ", ...");
475 }
473476 fprintf(ar->f, ")");
474477 if (node->data.fn_proto.align_expr) {
475478 fprintf(ar->f, " align(");
src/cache_hash.cpp+30-20
......@@ -19,6 +19,8 @@ void cache_init(CacheHash *ch, Buf *manifest_dir) {
1919 ch->manifest_dir = manifest_dir;
2020 ch->manifest_file_path = nullptr;
2121 ch->manifest_dirty = false;
22 ch->force_check_manifest = false;
23 ch->b64_digest = BUF_INIT;
2224}
2325
2426void cache_str(CacheHash *ch, const char *ptr) {
......@@ -243,22 +245,21 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
243245 int rc = blake2b_final(&ch->blake, bin_digest, 48);
244246 assert(rc == 0);
245247
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) {
247252 buf_resize(out_digest, 64);
248253 base64_encode(buf_to_slice(out_digest), {bin_digest, 48});
249254 return ErrorNone;
250255 }
251256
252 Buf b64_digest = BUF_INIT;
253 buf_resize(&b64_digest, 64);
254 base64_encode(buf_to_slice(&b64_digest), {bin_digest, 48});
255
256257 rc = blake2b_init(&ch->blake, 48);
257258 assert(rc == 0);
258259 blake2b_update(&ch->blake, bin_digest, 48);
259260
260261 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);
262263
263264 buf_append_str(ch->manifest_file_path, ".txt");
264265
......@@ -380,7 +381,7 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
380381 blake2b_update(&ch->blake, chf->bin_digest, 48);
381382 }
382383 }
383 if (file_i < input_file_count) {
384 if (file_i < input_file_count || file_i == 0) {
384385 // manifest file is empty or missing entries, so this is a cache miss
385386 ch->manifest_dirty = true;
386387 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) {
442443 }
443444 if (opt_line.value.len == 0)
444445 continue;
446
445447 if (opt_line.value.ptr[0] == '"') {
446448 if (opt_line.value.len < 2) {
447449 if (verbose) {
......@@ -460,21 +462,29 @@ Error cache_add_dep_file(CacheHash *ch, Buf *dep_file_path, bool verbose) {
460462 }
461463 return ErrorInvalidDepFile;
462464 }
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;
466472 }
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 (buf_eql_str(filename_buf, "\\")) continue;
480 if ((err = cache_add_file(ch, filename_buf))) {
481 if (verbose) {
482 fprintf(stderr, "unable to add %s to cache: %s\n", buf_ptr(filename_buf), err_str(err));
483 fprintf(stderr, "when processing .d file: %s\n", buf_ptr(dep_file_path));
484 }
485 return err;
486 }
476487 }
477 return err;
478488 }
479489 }
480490 return ErrorNone;
src/cache_hash.hpp+6
......@@ -25,8 +25,10 @@ struct CacheHash {
2525 ZigList<CacheHashFile> files;
2626 Buf *manifest_dir;
2727 Buf *manifest_file_path;
28 Buf b64_digest;
2829 OsFile manifest_file;
2930 bool manifest_dirty;
31 bool force_check_manifest;
3032};
3133
3234// Always call this first to set up.
......@@ -51,6 +53,10 @@ void cache_file_opt(CacheHash *ch, Buf *path);
5153// If you got a cache hit, the next step is cache_release.
5254// From this point on, there is a lock on the input params. Release
5355// 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.
5460Error ATTRIBUTE_MUST_USE cache_hit(CacheHash *ch, Buf *out_b64_digest);
5561
5662// If you did not get a cache hit, call this function for every file
src/codegen.cpp+115-130
......@@ -23,6 +23,9 @@
2323#include <stdio.h>
2424#include <errno.h>
2525
26#define CACHE_OUT_SUBDIR "o"
27#define CACHE_HASH_SUBDIR "h"
28
2629static void init_darwin_native(CodeGen *g) {
2730 char *osx_target = getenv("MACOSX_DEPLOYMENT_TARGET");
2831 char *ios_target = getenv("IPHONEOS_DEPLOYMENT_TARGET");
......@@ -196,18 +199,6 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
196199 return g;
197200}
198201
199void codegen_set_output_h_path(CodeGen *g, Buf *h_path) {
200 g->out_h_path = h_path;
201}
202
203void codegen_set_output_lib_path(CodeGen *g, Buf *lib_path) {
204 g->out_lib_path = lib_path;
205}
206
207void codegen_set_output_path(CodeGen *g, Buf *path) {
208 g->wanted_output_file_path = path;
209}
210
211202void codegen_set_clang_argv(CodeGen *g, const char **args, size_t len) {
212203 g->clang_argv = args;
213204 g->clang_argv_len = len;
......@@ -256,10 +247,6 @@ void codegen_set_out_name(CodeGen *g, Buf *out_name) {
256247 g->root_out_name = out_name;
257248}
258249
259void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker_path) {
260 g->dynamic_linker_path = dynamic_linker_path;
261}
262
263250void codegen_add_lib_dir(CodeGen *g, const char *dir) {
264251 g->lib_dirs.append(dir);
265252}
......@@ -7766,7 +7753,10 @@ static Error define_builtin_compile_vars(CodeGen *g) {
77667753 }
77677754 } else {
77687755 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 }
77707760 }
77717761
77727762 assert(g->root_package);
......@@ -8030,7 +8020,7 @@ static void detect_libc(CodeGen *g) {
80308020 }
80318021}
80328022
8033void codegen_translate_c(CodeGen *g, Buf *full_path) {
8023AstNode *codegen_translate_c(CodeGen *g, Buf *full_path) {
80348024 Buf *src_basename = buf_alloc();
80358025 Buf *src_dirname = buf_alloc();
80368026 os_path_split(full_path, src_dirname, src_basename);
......@@ -8042,16 +8032,9 @@ void codegen_translate_c(CodeGen *g, Buf *full_path) {
80428032
80438033 init(g);
80448034
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
80538035 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);
80558038
80568039 if (err == ErrorCCompileErrors && errors.length > 0) {
80578040 for (size_t i = 0; i < errors.length; i += 1) {
......@@ -8065,6 +8048,8 @@ void codegen_translate_c(CodeGen *g, Buf *full_path) {
80658048 fprintf(stderr, "unable to parse C file: %s\n", err_str(err));
80668049 exit(1);
80678050 }
8051
8052 return root_node;
80688053}
80698054
80708055static 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) {
82828267 return ErrorNone;
82838268}
82848269
8285// returns true if it was a cache miss
8286static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
8270Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose) {
82878271 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
83028272 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));
83058274 cache_init(cache_hash, manifest_dir);
83068275
83078276 Buf *compiler_id;
83088277 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;
83118282 }
83128283 cache_buf(cache_hash, compiler_id);
83138284 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) {
83218292 cache_int(cache_hash, g->zig_target->abi);
83228293 cache_bool(cache_hash, g->strip_debug_symbols);
83238294 cache_int(cache_hash, g->build_mode);
8324 cache_file(cache_hash, c_source_file);
83258295 cache_bool(cache_hash, g->disable_pic);
83268296 for (size_t arg_i = 0; arg_i < g->clang_argv_len; arg_i += 1) {
83278297 cache_str(cache_hash, g->clang_argv[arg_i]);
83288298 }
8299
8300 *out_cache_hash = cache_hash;
8301 return ErrorNone;
8302}
8303
8304// returns true if it was a cache miss
8305static 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
83298327 // Note: not directory args, just args that always have a file next
83308328 static const char *file_args[] = {
83318329 "-include",
......@@ -8787,11 +8785,13 @@ static void gen_h_file(CodeGen *g) {
87878785 GenH *gen_h = &gen_h_data;
87888786
87898787 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));
87918791
8792 FILE *out_h = fopen(buf_ptr(g->out_h_path), "wb");
8792 FILE *out_h = fopen(buf_ptr(out_h_path), "wb");
87938793 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));
87958795
87968796 Buf *export_macro = preprocessor_mangle(buf_sprintf("%s_EXPORT", buf_ptr(g->root_out_name)));
87978797 buf_upcase(export_macro);
......@@ -9065,6 +9065,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
90659065 cache_bool(ch, g->linker_rdynamic);
90669066 cache_bool(ch, g->each_lib_rpath);
90679067 cache_bool(ch, g->disable_pic);
9068 cache_bool(ch, g->disable_gen_h);
90689069 cache_bool(ch, g->valgrind_support);
90699070 cache_bool(ch, g->is_dummy_so);
90709071 cache_buf_opt(ch, g->mmacosx_version_min);
......@@ -9103,99 +9104,79 @@ static bool need_llvm_module(CodeGen *g) {
91039104 return g->assembly_files.length != 0 || buf_len(&g->root_package->root_src_path) != 0;
91049105}
91059106
9106static bool compilation_is_already_done(CodeGen *g) {
9107 return !need_llvm_module(g) && g->link_objects.length == 1 && g->out_type == OutTypeObj;
9108}
9109
91109107static 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);
91129110
9111 Buf *out_basename = buf_create_from_buf(g->root_out_name);
9112 Buf *o_basename = buf_create_from_buf(g->root_out_name);
91139113 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->link_objects.length != 0 && !g->enable_cache &&
9124 buf_eql_buf(o_basename, out_basename))
9125 {
9126 // make it not collide with main output object
9127 buf_append_str(o_basename, ".root");
9128 }
9129 buf_append_str(o_basename, target_o_file_ext(g->zig_target));
9130 buf_append_str(out_basename, target_o_file_ext(g->zig_target));
9131 break;
9132 case OutTypeExe:
9133 buf_append_str(o_basename, target_o_file_ext(g->zig_target));
9134 buf_append_str(out_basename, target_exe_file_ext(g->zig_target));
9135 break;
9136 case OutTypeLib:
9137 buf_append_str(o_basename, target_o_file_ext(g->zig_target));
9138 buf_resize(out_basename, 0);
9139 buf_append_str(out_basename, target_lib_file_prefix(g->zig_target));
9140 buf_append_buf(out_basename, g->root_out_name);
9141 buf_append_str(out_basename, target_lib_file_ext(g->zig_target, g->is_static,
9142 g->version_major, g->version_minor, g->version_patch));
9143 break;
9144 }
91189145 break;
91199146 }
9120 case EmitFileTypeAssembly:
9121 {
9147 case EmitFileTypeAssembly: {
91229148 const char *asm_ext = target_asm_file_ext(g->zig_target);
91239149 buf_append_str(o_basename, asm_ext);
9150 buf_append_str(out_basename, asm_ext);
91249151 break;
91259152 }
9126 case EmitFileTypeLLVMIr:
9127 {
9153 case EmitFileTypeLLVMIr: {
91289154 const char *llvm_ir_ext = target_llvm_ir_file_ext(g->zig_target);
91299155 buf_append_str(o_basename, llvm_ir_ext);
9156 buf_append_str(out_basename, llvm_ir_ext);
91309157 break;
91319158 }
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;
91729159 }
91739160
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 }
9161 os_path_join(g->output_dir, o_basename, &g->o_file_output_path);
9162 os_path_join(g->output_dir, out_basename, &g->output_file_path);
91859163}
91869164
91879165void codegen_build_and_link(CodeGen *g) {
91889166 Error err;
91899167 assert(g->out_type != OutTypeUnknown);
91909168
9169 if (!g->enable_cache && g->output_dir == nullptr) {
9170 g->output_dir = buf_create_from_str(".");
9171 }
9172
91919173 detect_libc(g);
91929174 detect_dynamic_linker(g);
91939175
9194 Buf *artifact_dir = buf_alloc();
91959176 Buf digest = BUF_INIT;
91969177 if (g->enable_cache) {
91979178 Buf *manifest_dir = buf_alloc();
9198 os_path_join(g->cache_dir, buf_create_from_str("h"), manifest_dir);
9179 os_path_join(g->cache_dir, buf_create_from_str(CACHE_HASH_SUBDIR), manifest_dir);
91999180
92009181 if ((err = check_cache(g, manifest_dir, &digest))) {
92019182 if (err == ErrorCacheUnavailable) {
......@@ -9208,15 +9189,14 @@ void codegen_build_and_link(CodeGen *g) {
92089189 }
92099190 exit(1);
92109191 }
9211
9212 os_path_join(g->cache_dir, buf_create_from_str("artifact"), artifact_dir);
92139192 } else {
92149193 // There is a call to this in check_cache
92159194 gen_c_objects(g);
92169195 }
92179196
92189197 if (g->enable_cache && buf_len(&digest) != 0) {
9219 os_path_join(artifact_dir, &digest, &g->artifact_dir);
9198 g->output_dir = buf_sprintf("%s" OS_SEP CACHE_OUT_SUBDIR OS_SEP "%s",
9199 buf_ptr(g->cache_dir), buf_ptr(&digest));
92209200 resolve_out_paths(g);
92219201 } else {
92229202 if (need_llvm_module(g)) {
......@@ -9235,13 +9215,13 @@ void codegen_build_and_link(CodeGen *g) {
92359215 exit(1);
92369216 }
92379217 }
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);
9218 g->output_dir = buf_sprintf("%s" OS_SEP CACHE_OUT_SUBDIR OS_SEP "%s",
9219 buf_ptr(g->cache_dir), buf_ptr(&digest));
9220
9221 if ((err = os_make_path(g->output_dir))) {
9222 fprintf(stderr, "Unable to create output directory: %s\n", err_str(err));
9223 exit(1);
9224 }
92459225 }
92469226 resolve_out_paths(g);
92479227
......@@ -9252,14 +9232,19 @@ void codegen_build_and_link(CodeGen *g) {
92529232 codegen_add_time_event(g, "LLVM Emit Output");
92539233 zig_llvm_emit_output(g);
92549234
9255 if (g->out_h_path != nullptr) {
9235 if (!g->disable_gen_h && (g->out_type == OutTypeObj || g->out_type == OutTypeLib)) {
92569236 codegen_add_time_event(g, "Generate .h");
92579237 gen_h_file(g);
92589238 }
92599239 }
92609240
9261 if (g->emit_file_type == EmitFileTypeBinary &&
9262 (g->link_objects.length > 1 || g->out_type != OutTypeObj))
9241 // If we're outputting assembly or llvm IR we skip linking.
9242 // If we're making a library or executable we must link.
9243 // If there is more than one object, we have to link them (with -r).
9244 // Finally, if we didn't make an object from zig source, and we don't have caching enabled,
9245 // then we have an object from C source that we must copy to the output dir which we do with a -r link.
9246 if (g->emit_file_type == EmitFileTypeBinary && (g->out_type != OutTypeObj || g->link_objects.length > 1 ||
9247 (!need_llvm_module(g) && !g->enable_cache)))
92639248 {
92649249 codegen_link(g);
92659250 }
src/codegen.hpp+1-5
......@@ -28,7 +28,6 @@ void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type);
2828void codegen_set_strip(CodeGen *codegen, bool strip);
2929void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);
3030void codegen_set_out_name(CodeGen *codegen, Buf *out_name);
31void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker);
3231void codegen_add_lib_dir(CodeGen *codegen, const char *dir);
3332void codegen_add_forbidden_lib(CodeGen *codegen, Buf *lib);
3433LinkLib *codegen_add_link_lib(CodeGen *codegen, Buf *lib);
......@@ -41,9 +40,6 @@ void codegen_set_linker_script(CodeGen *g, const char *linker_script);
4140void codegen_set_test_filter(CodeGen *g, Buf *filter);
4241void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);
4342void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch);
44void codegen_set_output_h_path(CodeGen *g, Buf *h_path);
45void codegen_set_output_lib_path(CodeGen *g, Buf *lib_path);
46void codegen_set_output_path(CodeGen *g, Buf *path);
4743void codegen_add_time_event(CodeGen *g, const char *name);
4844void codegen_print_timing_report(CodeGen *g, FILE *f);
4945void codegen_link(CodeGen *g);
......@@ -54,7 +50,7 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c
5450void codegen_add_assembly(CodeGen *g, Buf *path);
5551void codegen_add_object(CodeGen *g, Buf *object_path);
5652
57void codegen_translate_c(CodeGen *g, Buf *path);
53AstNode *codegen_translate_c(CodeGen *g, Buf *path);
5854
5955Buf *codegen_generate_builtin_source(CodeGen *g);
6056
src/ir.cpp+121-33
......@@ -16,6 +16,8 @@
1616#include "translate_c.hpp"
1717#include "util.hpp"
1818
19#include <errno.h>
20
1921struct IrExecContext {
2022 ZigList<ConstExprValue *> mem_slot_list;
2123};
......@@ -18687,7 +18689,15 @@ static IrInstruction *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstruc
1868718689 return result;
1868818690}
1868918691
18692static 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}
1869018699static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstructionCImport *instruction) {
18700 Error err;
1869118701 AstNode *node = instruction->base.source_node;
1869218702 assert(node->type == NodeTypeFnCallExpr);
1869318703 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
1870618716 Buf *namespace_name = buf_sprintf("%s.cimport:%" ZIG_PRI_usize ":%" ZIG_PRI_usize,
1870718717 buf_ptr(&cur_scope_pkg->pkg_path), node->line + 1, node->column + 1);
1870818718
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);
1872018723
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);
1872218730
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)));
1872718756 return ira->codegen->invalid_instruction;
1872818757 }
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 }
1873018787
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;
1873618789 }
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));
1874018792 }
1874118793
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 }
1874418802
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 }
1875018820
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 }
1875218824
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);
1875318841 return ir_const_type(ira, &instruction->base, child_import);
1875418842}
1875518843
src/link.cpp+10-18
......@@ -24,7 +24,7 @@ static CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, Ou
2424{
2525 CodeGen *child_gen = codegen_create(nullptr, root_src_path, parent_gen->zig_target, out_type,
2626 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;
2828 child_gen->verbose_tokenize = parent_gen->verbose_tokenize;
2929 child_gen->verbose_ast = parent_gen->verbose_ast;
3030 child_gen->verbose_link = parent_gen->verbose_link;
......@@ -675,11 +675,8 @@ static void construct_linker_job_elf(LinkJob *lj) {
675675 } else if (is_dyn_lib) {
676676 lj->args.append("-shared");
677677
678 if (buf_len(&g->output_file_path) == 0) {
679 buf_appendf(&g->output_file_path, "lib%s.so.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize "",
680 buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch);
681 }
682 soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize "", buf_ptr(g->root_out_name), g->version_major);
678 assert(buf_len(&g->output_file_path) != 0);
679 soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize, buf_ptr(g->root_out_name), g->version_major);
683680 }
684681
685682 lj->args.append("-o");
......@@ -859,11 +856,6 @@ static void construct_linker_job_wasm(LinkJob *lj) {
859856 }
860857}
861858
862//static bool is_target_cyg_mingw(const ZigTarget *target) {
863// return (target->os == ZigLLVM_Win32 && target->abi == ZigLLVM_Cygnus) ||
864// (target->os == ZigLLVM_Win32 && target->abi == ZigLLVM_GNU);
865//}
866
867859static void coff_append_machine_arg(CodeGen *g, ZigList<const char *> *list) {
868860 if (g->zig_target->arch == ZigLLVM_x86) {
869861 list->append("-MACHINE:X86");
......@@ -935,6 +927,7 @@ static void add_nt_link_args(LinkJob *lj, bool is_library) {
935927}
936928
937929static void construct_linker_job_coff(LinkJob *lj) {
930 Error err;
938931 CodeGen *g = lj->codegen;
939932
940933 lj->args.append("/ERRORLIMIT:0");
......@@ -1054,11 +1047,13 @@ static void construct_linker_job_coff(LinkJob *lj) {
10541047 buf_appendf(def_contents, "\n");
10551048
10561049 Buf *def_path = buf_alloc();
1057 os_path_join(&g->artifact_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path);
1058 os_write_file(def_path, def_contents);
1050 os_path_join(g->output_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path);
1051 if ((err = os_write_file(def_path, def_contents))) {
1052 zig_panic("error writing def file: %s", err_str(err));
1053 }
10591054
10601055 Buf *generated_lib_path = buf_alloc();
1061 os_path_join(&g->artifact_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path);
1056 os_path_join(g->output_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path);
10621057
10631058 gen_lib_args.resize(0);
10641059 gen_lib_args.append("link");
......@@ -1220,10 +1215,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
12201215 //lj->args.append("-install_name");
12211216 //lj->args.append(buf_ptr(dylib_install_name));
12221217
1223 if (buf_len(&g->output_file_path) == 0) {
1224 buf_appendf(&g->output_file_path, "lib%s.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib",
1225 buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch);
1226 }
1218 assert(buf_len(&g->output_file_path) != 0);
12271219 }
12281220
12291221 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) {
4848 "Compile Options:\n"
4949 " --assembly [source] add assembly file to build\n"
5050 " --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"
5353 " --color [auto|off|on] enable or disable colored error messages\n"
54 " --disable-gen-h do not generate a C header file (.h)\n"
5455 " --disable-pic disable Position Independent Code for libraries\n"
5556 " --disable-valgrind omit valgrind client requests in debug builds\n"
5657 " --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) {
5859 " -ftime-report print timing diagnostics\n"
5960 " --libc [file] Provide a file which specifies libc paths\n"
6061 " --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"
6463 " --pkg-begin [name] [path] make pkg available to import and push current pkg\n"
6564 " --pkg-end pop current pkg\n"
6665 " --main-pkg-path set the directory of the root package\n"
......@@ -371,8 +370,14 @@ int main(int argc, char **argv) {
371370 fprintf(stderr, "Unable to make directory: %s: %s\n", buf_ptr(out_src_dir_path), err_str(err));
372371 return EXIT_FAILURE;
373372 }
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 }
376381 fprintf(stderr, "Created %s\n", buf_ptr(out_build_zig_path));
377382 fprintf(stderr, "Created %s\n", buf_ptr(out_main_zig_path));
378383 if (init_kind == InitKindExe) {
......@@ -390,9 +395,7 @@ int main(int argc, char **argv) {
390395 Cmd cmd = CmdNone;
391396 EmitFileType emit_file_type = EmitFileTypeBinary;
392397 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;
396399 bool strip = false;
397400 bool is_static = false;
398401 OutType out_type = OutTypeUnknown;
......@@ -406,7 +409,7 @@ int main(int argc, char **argv) {
406409 bool verbose_cc = false;
407410 ErrColor color = ErrColorAuto;
408411 CacheOpt enable_cache = CacheOptAuto;
409 const char *dynamic_linker = nullptr;
412 Buf *dynamic_linker = nullptr;
410413 const char *libc_txt = nullptr;
411414 ZigList<const char *> clang_argv = {0};
412415 ZigList<const char *> lib_dirs = {0};
......@@ -438,6 +441,7 @@ int main(int argc, char **argv) {
438441 bool system_linker_hack = false;
439442 TargetSubsystem subsystem = TargetSubsystemAuto;
440443 bool is_single_threaded = false;
444 bool disable_gen_h = false;
441445 Buf *override_std_dir = nullptr;
442446 Buf *main_pkg_path = nullptr;
443447 ValgrindSupport valgrind_support = ValgrindSupportAuto;
......@@ -648,6 +652,8 @@ int main(int argc, char **argv) {
648652 system_linker_hack = true;
649653 } else if (strcmp(arg, "--single-threaded") == 0) {
650654 is_single_threaded = true;
655 } else if (strcmp(arg, "--disable-gen-h") == 0) {
656 disable_gen_h = true;
651657 } else if (strcmp(arg, "--test-cmd-bin") == 0) {
652658 test_exec_args.append(nullptr);
653659 } else if (arg[1] == 'L' && arg[2] != 0) {
......@@ -677,12 +683,8 @@ int main(int argc, char **argv) {
677683 return print_error_usage(arg0);
678684 } else {
679685 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]);
686688 } else if (strcmp(arg, "--color") == 0) {
687689 if (strcmp(argv[i], "auto") == 0) {
688690 color = ErrColorAuto;
......@@ -719,7 +721,7 @@ int main(int argc, char **argv) {
719721 } else if (strcmp(arg, "--name") == 0) {
720722 out_name = argv[i];
721723 } else if (strcmp(arg, "--dynamic-linker") == 0) {
722 dynamic_linker = argv[i];
724 dynamic_linker = buf_create_from_str(argv[i]);
723725 } else if (strcmp(arg, "--libc") == 0) {
724726 libc_txt = argv[i];
725727 } else if (strcmp(arg, "-isystem") == 0) {
......@@ -901,6 +903,21 @@ int main(int argc, char **argv) {
901903 }
902904 }
903905
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
904921 switch (cmd) {
905922 case CmdLibC: {
906923 if (in_file) {
......@@ -1008,6 +1025,7 @@ int main(int argc, char **argv) {
10081025 }
10091026 CodeGen *g = codegen_create(main_pkg_path, zig_root_source_file, &target, out_type, build_mode,
10101027 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);
10111029 g->valgrind_support = valgrind_support;
10121030 g->subsystem = subsystem;
10131031
......@@ -1030,16 +1048,9 @@ int main(int argc, char **argv) {
10301048
10311049 codegen_set_clang_argv(g, clang_argv.items, clang_argv.length);
10321050
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);
10391051 codegen_set_strip(g, strip);
10401052 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;
10431054 g->verbose_tokenize = verbose_tokenize;
10441055 g->verbose_ast = verbose_ast;
10451056 g->verbose_link = verbose_link;
......@@ -1047,6 +1058,8 @@ int main(int argc, char **argv) {
10471058 g->verbose_llvm_ir = verbose_llvm_ir;
10481059 g->verbose_cimport = verbose_cimport;
10491060 g->verbose_cc = verbose_cc;
1061 g->output_dir = output_dir;
1062 g->disable_gen_h = disable_gen_h;
10501063 codegen_set_errmsg_color(g, color);
10511064 g->system_linker_hack = system_linker_hack;
10521065
......@@ -1090,13 +1103,6 @@ int main(int argc, char **argv) {
10901103 codegen_set_test_name_prefix(g, buf_create_from_str(test_name_prefix));
10911104 }
10921105
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
11001106 add_package(g, cur_pkg, g->root_package);
11011107
11021108 if (cmd == CmdBuild || cmd == CmdRun || cmd == CmdTest) {
......@@ -1135,20 +1141,18 @@ int main(int argc, char **argv) {
11351141 return term.code;
11361142 } else if (cmd == CmdBuild) {
11371143 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;
11421146 }
11431147 return EXIT_SUCCESS;
11441148 } else {
11451149 zig_unreachable();
11461150 }
11471151 } 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);
11501154 if (timing_info)
1151 codegen_print_timing_report(g, stdout);
1155 codegen_print_timing_report(g, stderr);
11521156 return EXIT_SUCCESS;
11531157 } else if (cmd == CmdTest) {
11541158 codegen_set_emit_file_type(g, emit_file_type);
......@@ -1156,7 +1160,7 @@ int main(int argc, char **argv) {
11561160 ZigTarget native;
11571161 get_native_target(&native);
11581162
1159 g->enable_cache = get_cache_opt(enable_cache, false);
1163 g->enable_cache = get_cache_opt(enable_cache, true);
11601164 codegen_build_and_link(g);
11611165
11621166 if (timing_info) {
src/os.cpp+2-86
......@@ -1031,7 +1031,7 @@ Error os_exec_process(const char *exe, ZigList<const char *> &args,
10311031#endif
10321032}
10331033
1034void os_write_file(Buf *full_path, Buf *contents) {
1034Error os_write_file(Buf *full_path, Buf *contents) {
10351035 FILE *f = fopen(buf_ptr(full_path), "wb");
10361036 if (!f) {
10371037 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) {
10411041 zig_panic("write failed: %s", strerror(errno));
10421042 if (fclose(f))
10431043 zig_panic("close failed");
1044 return ErrorNone;
10441045}
10451046
10461047Error os_copy_file(Buf *src_path, Buf *dest_path) {
......@@ -1208,91 +1209,6 @@ bool os_stderr_tty(void) {
12081209#endif
12091210}
12101211
1211#if defined(ZIG_OS_POSIX)
1212static 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
1240Buf *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)
1253static 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
1286Error 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
12961212Error os_delete_file(Buf *path) {
12971213 if (remove(buf_ptr(path))) {
12981214 return ErrorFileSystem;
src/os.hpp+2-4
......@@ -110,8 +110,8 @@ Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents);
110110Error ATTRIBUTE_MUST_USE os_file_overwrite(OsFile file, Buf *contents);
111111void os_file_close(OsFile file);
112112
113void os_write_file(Buf *full_path, Buf *contents);
114Error os_copy_file(Buf *src_path, Buf *dest_path);
113Error ATTRIBUTE_MUST_USE os_write_file(Buf *full_path, Buf *contents);
114Error ATTRIBUTE_MUST_USE os_copy_file(Buf *src_path, Buf *dest_path);
115115
116116Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents, bool skip_shebang);
117117Error 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);
121121bool os_stderr_tty(void);
122122void os_stderr_set_color(TermColor color);
123123
124Buf *os_tmp_filename(Buf *prefix, Buf *suffix);
125Error os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path);
126124Error os_delete_file(Buf *path);
127125
128126Error 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,
942942 } else {
943943 if (is_static) {
944944 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));
945948 } 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));
947951 }
948952 }
949953}
src/translate_c.cpp+6-42
......@@ -76,7 +76,6 @@ struct TransScopeWhile {
7676};
7777
7878struct Context {
79 ZigType *import;
8079 ZigList<ErrorMsg *> *errors;
8180 VisibMod visib_mod;
8281 bool want_export;
......@@ -86,7 +85,6 @@ struct Context {
8685 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table;
8786 ZigClangSourceManager *source_manager;
8887 ZigList<Alias> aliases;
89 AstNode *source_node;
9088 bool warnings_on;
9189
9290 CodeGen *codegen;
......@@ -190,7 +188,6 @@ static Buf *trans_lookup_zig_symbol(Context *c, TransScope *scope, Buf *c_symbol
190188static AstNode * trans_create_node(Context *c, NodeType id) {
191189 AstNode *node = allocate<AstNode>(1);
192190 node->type = id;
193 node->owner = c->import;
194191 // TODO line/column. mapping to C file??
195192 return node;
196193}
......@@ -4732,29 +4729,12 @@ static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) {
47324729 }
47334730}
47344731
4735Error 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
4751Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *target_file,
4752 CodeGen *codegen, AstNode *source_node)
4732Error parse_h_file(AstNode **out_root_node, ZigList<ErrorMsg *> *errors, const char *target_file,
4733 CodeGen *codegen, Buf *tmp_dep_file)
47534734{
47544735 Context context = {0};
47554736 Context *c = &context;
47564737 c->warnings_on = codegen->verbose_cimport;
4757 c->import = import;
47584738 c->errors = errors;
47594739 if (buf_ends_with_str(buf_create_from_str(target_file), ".h")) {
47604740 c->visib_mod = VisibModPub;
......@@ -4768,7 +4748,6 @@ Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *tar
47684748 c->global_table.init(8);
47694749 c->ptr_params.init(8);
47704750 c->codegen = codegen;
4771 c->source_node = source_node;
47724751 c->global_scope = trans_scope_root_create(c);
47734752
47744753 ZigList<const char *> clang_argv = {0};
......@@ -4776,14 +4755,11 @@ Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *tar
47764755 clang_argv.append("-x");
47774756 clang_argv.append("c");
47784757
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) {
47834759 clang_argv.append("-MD");
47844760 clang_argv.append("-MV");
47854761 clang_argv.append("-MF");
4786 clang_argv.append(buf_ptr(out_dep_path));
4762 clang_argv.append(buf_ptr(tmp_dep_file));
47874763 }
47884764
47894765 if (c->codegen->zig_target->is_native) {
......@@ -4847,7 +4823,7 @@ Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *tar
48474823
48484824 clang_argv.append(target_file);
48494825
4850 if (codegen->verbose_cimport) {
4826 if (codegen->verbose_cc) {
48514827 fprintf(stderr, "clang");
48524828 for (size_t i = 0; i < clang_argv.length; i += 1) {
48534829 fprintf(stderr, " %s", clang_argv.at(i));
......@@ -4932,17 +4908,6 @@ Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *tar
49324908 return ErrorCCompileErrors;
49334909 }
49344910
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
49464911 c->ctx = ZigClangASTUnit_getASTContext(ast_unit);
49474912 c->source_manager = ZigClangASTUnit_getSourceManager(ast_unit);
49484913 c->root = trans_create_node(c, NodeTypeContainerDecl);
......@@ -4955,8 +4920,7 @@ Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *tar
49554920 render_macros(c);
49564921 render_aliases(c);
49574922
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;
49604924
49614925 return ErrorNone;
49624926}
src/translate_c.hpp+2-5
......@@ -11,10 +11,7 @@
1111
1212#include "all_types.hpp"
1313
14Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *target_file,
15 CodeGen *codegen, AstNode *source_node);
16
17Error parse_h_buf(ZigType *import, ZigList<ErrorMsg *> *errors, Buf *source,
18 CodeGen *codegen, AstNode *source_node);
14Error parse_h_file(AstNode **out_root_node, ZigList<ErrorMsg *> *errors, const char *target_file,
15 CodeGen *codegen, Buf *tmp_dep_file);
1916
2017#endif
std/build.zig+303-185
......@@ -183,9 +183,20 @@ pub const Builder = struct {
183183 return obj_step;
184184 }
185185
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;
189200 }
190201
191202 pub fn addWriteFile(self: *Builder, file_path: []const u8, data: []const u8) *WriteFileStep {
......@@ -702,25 +713,42 @@ pub const Builder = struct {
702713 }
703714
704715 pub fn exec(self: *Builder, argv: []const []const u8) ![]u8 {
716 assert(argv.len != 0);
717
705718 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) {
708736 os.ChildProcess.Term.Exited => |code| {
709737 if (code != 0) {
710738 warn("The following command exited with error code {}:\n", code);
711739 printCmd(null, argv);
712 warn("stderr:{}\n", result.stderr);
713 std.debug.panic("command failed");
740 std.debug.panic("exec failed");
714741 }
715 return result.stdout;
742 return stdout.toOwnedSlice();
716743 },
717744 else => {
718745 warn("The following command terminated unexpectedly:\n");
719746 printCmd(null, argv);
720 warn("stderr:{}\n", result.stderr);
721 std.debug.panic("command failed");
747 std.debug.panic("exec failed");
722748 },
723749 }
750
751 return stdout.toOwnedSlice();
724752 }
725753
726754 pub fn addSearchPrefix(self: *Builder, search_prefix: []const u8) void {
......@@ -837,26 +865,20 @@ pub const LibExeObjStep = struct {
837865 builder: *Builder,
838866 name: []const u8,
839867 target: Target,
840 link_libs: BufSet,
841868 linker_script: ?[]const u8,
842869 out_filename: []const u8,
843 output_path: ?[]const u8,
844 output_lib_path: ?[]const u8,
845870 static: bool,
846871 version: Version,
847 object_files: ArrayList([]const u8),
848872 build_mode: builtin.Mode,
849873 kind: Kind,
850874 major_only_filename: []const u8,
851875 name_only_filename: []const u8,
852876 strip: bool,
853 full_path_libs: ArrayList([]const u8),
854 need_flat_namespace_hack: bool,
855 include_dirs: ArrayList([]const u8),
856877 lib_paths: ArrayList([]const u8),
857878 frameworks: BufSet,
858879 verbose_link: bool,
859880 verbose_cc: bool,
881 disable_gen_h: bool,
860882 c_std: Builder.CStd,
861883 override_std_dir: ?[]const u8,
862884 main_pkg_path: ?[]const u8,
......@@ -865,17 +887,31 @@ pub const LibExeObjStep = struct {
865887 filter: ?[]const u8,
866888
867889 root_src: ?[]const u8,
868 output_h_path: ?[]const u8,
869890 out_h_filename: []const u8,
870891 out_lib_filename: []const u8,
871 assembly_files: ArrayList([]const u8),
872892 packages: ArrayList(Pkg),
873893 build_options_contents: std.Buffer,
874894 system_linker_hack: bool,
875895
876 c_source_files: ArrayList(*CSourceFile),
877896 object_src: []const u8,
878897
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
879915 const Kind = enum {
880916 Exe,
881917 Lib,
......@@ -926,25 +962,17 @@ pub const LibExeObjStep = struct {
926962 .name = name,
927963 .target = Target.Native,
928964 .linker_script = null,
929 .link_libs = BufSet.init(builder.allocator),
930965 .frameworks = BufSet.init(builder.allocator),
931966 .step = Step.init(name, builder.allocator, make),
932 .output_path = null,
933 .output_lib_path = null,
934 .output_h_path = null,
935967 .version = ver,
936968 .out_filename = undefined,
937969 .out_h_filename = builder.fmt("{}.h", name),
938970 .out_lib_filename = undefined,
939971 .major_only_filename = undefined,
940972 .name_only_filename = undefined,
941 .object_files = ArrayList([]const u8).init(builder.allocator),
942 .assembly_files = ArrayList([]const u8).init(builder.allocator),
943973 .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),
948976 .lib_paths = ArrayList([]const u8).init(builder.allocator),
949977 .object_src = undefined,
950978 .build_options_contents = std.Buffer.initSize(builder.allocator, 0) catch unreachable,
......@@ -955,6 +983,8 @@ pub const LibExeObjStep = struct {
955983 .exec_cmd_args = null,
956984 .name_prefix = "",
957985 .filter = null,
986 .disable_gen_h = false,
987 .output_dir = null,
958988 };
959989 self.computeOutFileNames();
960990 return self;
......@@ -1022,7 +1052,20 @@ pub const LibExeObjStep = struct {
10221052 self.computeOutFileNames();
10231053 }
10241054
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 assert(exe.target == Target.Native);
1064 const run_step = RunStep.create(exe.builder, exe.builder.fmt("run {}", exe.step.name));
1065 run_step.addArtifactArg(exe);
1066 return run_step;
1067 }
1068
10261069 pub fn setLinkerScriptPath(self: *LibExeObjStep, path: []const u8) void {
10271070 self.linker_script = path;
10281071 }
......@@ -1032,37 +1075,28 @@ pub const LibExeObjStep = struct {
10321075 self.frameworks.put(framework_name) catch unreachable;
10331076 }
10341077
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;
1078 /// Returns whether the library, executable, or object depends on a particular system library.
1079 pub fn dependsOnSystemLibrary(self: LibExeObjStep, name: []const u8) bool {
1080 for (self.link_objects.toSliceConst()) |link_object| {
1081 switch (link_object) {
1082 LinkObject.SystemLib => |n| if (mem.eql(u8, n, name)) return true,
1083 else => continue,
1084 }
10491085 }
1086 return false;
1087 }
10501088
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;
1089 pub fn linkLibrary(self: *LibExeObjStep, lib: *LibExeObjStep) void {
1090 assert(lib.kind == Kind.Lib);
1091 self.linkLibraryOrObject(lib);
1092 }
10541093
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 }
1094 pub fn isDynamicLibrary(self: *LibExeObjStep) bool {
1095 return self.kind == Kind.Lib and !self.static;
10621096 }
10631097
10641098 pub fn linkSystemLibrary(self: *LibExeObjStep, name: []const u8) void {
1065 self.link_libs.put(name) catch unreachable;
1099 self.link_objects.append(LinkObject{ .SystemLib = self.builder.dupe(name) }) catch unreachable;
10661100 }
10671101
10681102 pub fn setNamePrefix(self: *LibExeObjStep, text: []const u8) void {
......@@ -1077,11 +1111,15 @@ pub const LibExeObjStep = struct {
10771111
10781112 pub fn addCSourceFile(self: *LibExeObjStep, file: []const u8, args: []const []const u8) void {
10791113 const c_source_file = self.builder.allocator.create(CSourceFile) catch unreachable;
1114 const args_copy = self.builder.allocator.alloc([]u8, args.len) catch unreachable;
1115 for (args) |arg, i| {
1116 args_copy[i] = self.builder.dupe(arg);
1117 }
10801118 c_source_file.* = CSourceFile{
1081 .source_path = file,
1082 .args = args,
1119 .source_path = self.builder.dupe(file),
1120 .args = args_copy,
10831121 };
1084 self.c_source_files.append(c_source_file) catch unreachable;
1122 self.link_objects.append(LinkObject{ .CSourceFile = c_source_file }) catch unreachable;
10851123 }
10861124
10871125 pub fn setVerboseLink(self: *LibExeObjStep, value: bool) void {
......@@ -1104,78 +1142,48 @@ pub const LibExeObjStep = struct {
11041142 self.main_pkg_path = dir_path;
11051143 }
11061144
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
1145 /// Unless setOutputDir was called, this function must be called only in
1146 /// the make step, from a step that has declared a dependency on this one.
1147 /// To run an executable built with zig build, use `run`, or create an install step and invoke it.
11161148 pub fn getOutputPath(self: *LibExeObjStep) []const u8 {
1117 return if (self.output_path) |output_path| output_path else os.path.join(
1149 return os.path.join(
11181150 self.builder.allocator,
1119 [][]const u8{ self.builder.cache_root, self.out_filename },
1151 [][]const u8{ self.output_dir.?, self.out_filename },
11201152 ) catch unreachable;
11211153 }
11221154
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
1155 /// Unless setOutputDir was called, this function must be called only in
1156 /// the make step, from a step that has declared a dependency on this one.
11311157 pub fn getOutputLibPath(self: *LibExeObjStep) []const u8 {
11321158 assert(self.kind == Kind.Lib);
1133 return if (self.output_lib_path) |output_lib_path| output_lib_path else os.path.join(
1159 return os.path.join(
11341160 self.builder.allocator,
1135 [][]const u8{ self.builder.cache_root, self.out_lib_filename },
1161 [][]const u8{ self.output_dir.?, self.out_lib_filename },
11361162 ) catch unreachable;
11371163 }
11381164
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
1165 /// Unless setOutputDir was called, this function must be called only in
1166 /// the make step, from a step that has declared a dependency on this one.
11481167 pub fn getOutputHPath(self: *LibExeObjStep) []const u8 {
1149 return if (self.output_h_path) |output_h_path| output_h_path else os.path.join(
1168 assert(self.kind != Kind.Exe);
1169 assert(!self.disable_gen_h);
1170 return os.path.join(
11501171 self.builder.allocator,
1151 [][]const u8{ self.builder.cache_root, self.out_h_filename },
1172 [][]const u8{ self.output_dir.?, self.out_h_filename },
11521173 ) catch unreachable;
11531174 }
11541175
11551176 pub fn addAssemblyFile(self: *LibExeObjStep, path: []const u8) void {
1156 self.assembly_files.append(path) catch unreachable;
1177 self.link_objects.append(LinkObject{ .AssemblyFile = self.builder.dupe(path) }) catch unreachable;
11571178 }
11581179
11591180 pub fn addObjectFile(self: *LibExeObjStep, path: []const u8) void {
1160 assert(self.kind != Kind.Obj);
1161
1162 self.object_files.append(path) catch unreachable;
1181 self.link_objects.append(LinkObject{ .StaticPath = self.builder.dupe(path) }) catch unreachable;
11631182 }
11641183
11651184 pub fn addObject(self: *LibExeObjStep, obj: *LibExeObjStep) void {
11661185 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 }
1186 self.linkLibraryOrObject(obj);
11791187 }
11801188
11811189 pub fn addBuildOption(self: *LibExeObjStep, comptime T: type, name: []const u8, value: T) void {
......@@ -1184,7 +1192,7 @@ pub const LibExeObjStep = struct {
11841192 }
11851193
11861194 pub fn addIncludeDir(self: *LibExeObjStep, path: []const u8) void {
1187 self.include_dirs.append(path) catch unreachable;
1195 self.include_dirs.append(IncludeDir{ .RawPath = self.builder.dupe(path) }) catch unreachable;
11881196 }
11891197
11901198 pub fn addLibPath(self: *LibExeObjStep, path: []const u8) void {
......@@ -1207,13 +1215,30 @@ pub const LibExeObjStep = struct {
12071215 self.system_linker_hack = true;
12081216 }
12091217
1218 fn linkLibraryOrObject(self: *LibExeObjStep, other: *LibExeObjStep) void {
1219 self.step.dependOn(&other.step);
1220 self.link_objects.append(LinkObject{ .OtherStep = other }) catch unreachable;
1221 self.include_dirs.append(IncludeDir{ .OtherStep = other }) catch unreachable;
1222
1223 // Inherit dependency on libc
1224 if (other.dependsOnSystemLibrary("c")) {
1225 self.linkSystemLibrary("c");
1226 }
1227
1228 // Inherit dependencies on darwin frameworks
1229 if (self.target.isDarwin() and !other.isDynamicLibrary()) {
1230 var it = other.frameworks.iterator();
1231 while (it.next()) |entry| {
1232 self.frameworks.put(entry.key) catch unreachable;
1233 }
1234 }
1235 }
1236
12101237 fn make(step: *Step) !void {
12111238 const self = @fieldParentPtr(LibExeObjStep, "step", step);
12121239 const builder = self.builder;
12131240
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 {
1241 if (self.root_src == null and self.link_objects.len == 0) {
12171242 warn("{}: linker needs 1 or more objects to link\n", self.step.name);
12181243 return error.NeedAnObject;
12191244 }
......@@ -1235,12 +1260,52 @@ pub const LibExeObjStep = struct {
12351260 zig_args.append(builder.pathFromRoot(root_src)) catch unreachable;
12361261 }
12371262
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);
1263 for (self.link_objects.toSlice()) |link_object| {
1264 switch (link_object) {
1265 LinkObject.StaticPath => |static_path| {
1266 try zig_args.append("--object");
1267 try zig_args.append(builder.pathFromRoot(static_path));
1268 },
1269
1270 LinkObject.OtherStep => |other| switch (other.kind) {
1271 LibExeObjStep.Kind.Exe => unreachable,
1272 LibExeObjStep.Kind.Test => unreachable,
1273 LibExeObjStep.Kind.Obj => {
1274 try zig_args.append("--object");
1275 try zig_args.append(other.getOutputPath());
1276 },
1277 LibExeObjStep.Kind.Lib => {
1278 if (other.static or self.target.isWindows()) {
1279 try zig_args.append("--object");
1280 try zig_args.append(other.getOutputLibPath());
1281 } else {
1282 const full_path_lib = other.getOutputPath();
1283 try zig_args.append("--library");
1284 try zig_args.append(full_path_lib);
1285
1286 if (os.path.dirname(full_path_lib)) |dirname| {
1287 try zig_args.append("-rpath");
1288 try zig_args.append(dirname);
1289 }
1290 }
1291 },
1292 },
1293 LinkObject.SystemLib => |name| {
1294 try zig_args.append("--library");
1295 try zig_args.append(name);
1296 },
1297 LinkObject.AssemblyFile => |asm_file| {
1298 try zig_args.append("--assembly");
1299 try zig_args.append(builder.pathFromRoot(asm_file));
1300 },
1301 LinkObject.CSourceFile => |c_source_file| {
1302 try zig_args.append("--c-source");
1303 for (c_source_file.args) |arg| {
1304 try zig_args.append(arg);
1305 }
1306 try zig_args.append(self.builder.pathFromRoot(c_source_file.source_path));
1307 },
12421308 }
1243 try zig_args.append(self.builder.pathFromRoot(c_source_file.source_path));
12441309 }
12451310
12461311 if (self.build_options_contents.len() > 0) {
......@@ -1265,16 +1330,6 @@ pub const LibExeObjStep = struct {
12651330 try zig_args.append(self.name_prefix);
12661331 }
12671332
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
12781333 if (builder.verbose_tokenize) zig_args.append("--verbose-tokenize") catch unreachable;
12791334 if (builder.verbose_ast) zig_args.append("--verbose-ast") catch unreachable;
12801335 if (builder.verbose_cimport) zig_args.append("--verbose-cimport") catch unreachable;
......@@ -1294,24 +1349,8 @@ pub const LibExeObjStep = struct {
12941349 builtin.Mode.ReleaseSmall => zig_args.append("--release-small") catch unreachable,
12951350 }
12961351
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 }
1352 try zig_args.append("--cache-dir");
1353 try zig_args.append(builder.pathFromRoot(builder.cache_root));
13151354
13161355 zig_args.append("--name") catch unreachable;
13171356 zig_args.append(self.name) catch unreachable;
......@@ -1351,15 +1390,6 @@ pub const LibExeObjStep = struct {
13511390 zig_args.append(linker_script) catch unreachable;
13521391 }
13531392
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
13631393 if (self.exec_cmd_args) |exec_cmd_args| {
13641394 for (exec_cmd_args) |cmd_arg| {
13651395 if (cmd_arg) |arg| {
......@@ -1377,9 +1407,18 @@ pub const LibExeObjStep = struct {
13771407 zig_args.append("--pkg-end") catch unreachable;
13781408 }
13791409
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;
1410 for (self.include_dirs.toSliceConst()) |include_dir| {
1411 switch (include_dir) {
1412 IncludeDir.RawPath => |include_path| {
1413 try zig_args.append("-isystem");
1414 try zig_args.append(self.builder.pathFromRoot(include_path));
1415 },
1416 IncludeDir.OtherStep => |other| {
1417 const h_path = other.getOutputHPath();
1418 try zig_args.append("-isystem");
1419 try zig_args.append(os.path.dirname(h_path).?);
1420 },
1421 }
13831422 }
13841423
13851424 for (builder.include_paths.toSliceConst()) |include_path| {
......@@ -1402,17 +1441,6 @@ pub const LibExeObjStep = struct {
14021441 zig_args.append(lib_path) catch unreachable;
14031442 }
14041443
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
14161444 if (self.target.isDarwin()) {
14171445 var it = self.frameworks.iterator();
14181446 while (it.next()) |entry| {
......@@ -1435,42 +1463,132 @@ pub const LibExeObjStep = struct {
14351463 try zig_args.append(builder.pathFromRoot(dir));
14361464 }
14371465
1438 try builder.spawnChild(zig_args.toSliceConst());
1466 if (self.output_dir) |output_dir| {
1467 try zig_args.append("--output-dir");
1468 try zig_args.append(output_dir);
1469
1470 try builder.spawnChild(zig_args.toSliceConst());
1471 } else if (self.kind == Kind.Test) {
1472 try builder.spawnChild(zig_args.toSliceConst());
1473 } else {
1474 try zig_args.append("--cache");
1475 try zig_args.append("on");
1476
1477 const output_path_nl = try builder.exec(zig_args.toSliceConst());
1478 const output_path = mem.trimRight(u8, output_path_nl, "\r\n");
1479 self.output_dir = os.path.dirname(output_path).?;
1480 }
14391481
14401482 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);
1483 try doAtomicSymLinks(builder.allocator, self.getOutputPath(), self.major_only_filename, self.name_only_filename);
14421484 }
14431485 }
14441486};
14451487
1446pub const CommandStep = struct {
1488pub const RunStep = struct {
14471489 step: Step,
14481490 builder: *Builder,
1449 argv: [][]const u8,
1491
1492 /// See also addArg and addArgs to modifying this directly
1493 argv: ArrayList(Arg),
1494
1495 /// Set this to modify the current working directory
14501496 cwd: ?[]const u8,
1451 env_map: *const BufMap,
14521497
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{
1498 /// Override this field to modify the environment, or use setEnvironmentVariable
1499 env_map: ?*BufMap,
1500
1501 pub const Arg = union(enum) {
1502 Artifact: *LibExeObjStep,
1503 Bytes: []u8,
1504 };
1505
1506 pub fn create(builder: *Builder, name: []const u8) *RunStep {
1507 const self = builder.allocator.create(RunStep) catch unreachable;
1508 self.* = RunStep{
14571509 .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,
1510 .step = Step.init(name, builder.allocator, make),
1511 .argv = ArrayList(Arg).init(builder.allocator),
1512 .cwd = null,
1513 .env_map = null,
14621514 };
1463
1464 mem.copy([]const u8, self.argv, argv);
1465 self.step.name = self.argv[0];
14661515 return self;
14671516 }
14681517
1518 pub fn addArtifactArg(self: *RunStep, artifact: *LibExeObjStep) void {
1519 self.argv.append(Arg{ .Artifact = artifact }) catch unreachable;
1520 self.step.dependOn(&artifact.step);
1521 }
1522
1523 pub fn addArg(self: *RunStep, arg: []const u8) void {
1524 self.argv.append(Arg{ .Bytes = self.builder.dupe(arg) }) catch unreachable;
1525 }
1526
1527 pub fn addArgs(self: *RunStep, args: []const []const u8) void {
1528 for (args) |arg| {
1529 self.addArg(arg);
1530 }
1531 }
1532
1533 pub fn addPathDir(self: *RunStep, search_path: []const u8) void {
1534 const PATH = if (builtin.os == builtin.Os.windows) "Path" else "PATH";
1535 const env_map = self.getEnvMap();
1536 const prev_path = env_map.get(PATH) orelse {
1537 env_map.set(PATH, search_path) catch unreachable;
1538 return;
1539 };
1540 const new_path = self.builder.fmt("{}" ++ [1]u8{os.path.delimiter} ++ "{}", prev_path, search_path);
1541 env_map.set(PATH, new_path) catch unreachable;
1542 }
1543
1544 pub fn getEnvMap(self: *RunStep) *BufMap {
1545 return self.env_map orelse {
1546 const env_map = self.builder.allocator.create(BufMap) catch unreachable;
1547 env_map.* = os.getEnvMap(self.builder.allocator) catch unreachable;
1548 self.env_map = env_map;
1549 return env_map;
1550 };
1551 }
1552
1553 pub fn setEnvironmentVariable(self: *RunStep, key: []const u8, value: []const u8) void {
1554 const env_map = self.getEnvMap();
1555 env_map.set(key, value) catch unreachable;
1556 }
1557
14691558 fn make(step: *Step) !void {
1470 const self = @fieldParentPtr(CommandStep, "step", step);
1559 const self = @fieldParentPtr(RunStep, "step", step);
14711560
14721561 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);
1562
1563 var argv = ArrayList([]const u8).init(self.builder.allocator);
1564 for (self.argv.toSlice()) |arg| {
1565 switch (arg) {
1566 Arg.Bytes => |bytes| try argv.append(bytes),
1567 Arg.Artifact => |artifact| {
1568 if (artifact.target.isWindows()) {
1569 // On Windows we don't have rpaths so we have to add .dll search paths to PATH
1570 self.addPathForDynLibs(artifact);
1571 }
1572 try argv.append(artifact.getOutputPath());
1573 },
1574 }
1575 }
1576
1577 return self.builder.spawnChildEnvMap(cwd, self.env_map orelse self.builder.env_map, argv.toSliceConst());
1578 }
1579
1580 fn addPathForDynLibs(self: *RunStep, artifact: *LibExeObjStep) void {
1581 for (artifact.link_objects.toSliceConst()) |link_object| {
1582 switch (link_object) {
1583 LibExeObjStep.LinkObject.OtherStep => |other| {
1584 if (other.target.isWindows() and other.isDynamicLibrary()) {
1585 self.addPathDir(os.path.dirname(other.getOutputPath()).?);
1586 self.addPathForDynLibs(other);
1587 }
1588 },
1589 else => {},
1590 }
1591 }
14741592 }
14751593};
14761594
std/event/future.zig+1-1
......@@ -86,7 +86,7 @@ pub fn Future(comptime T: type) type {
8686
8787test "std.event.Future" {
8888 // https://github.com/ziglang/zig/issues/1908
89 if (builtin.single_threaded) return error.SkipZigTest;
89 if (builtin.single_threaded or builtin.os != builtin.Os.linux) return error.SkipZigTest;
9090
9191 var da = std.heap.DirectAllocator.init();
9292 defer da.deinit();
std/os/windows/util.zig+7-1
......@@ -167,7 +167,7 @@ pub fn windowsOpen(
167167pub fn createWindowsEnvBlock(allocator: *mem.Allocator, env_map: *const BufMap) ![]u16 {
168168 // count bytes needed
169169 const max_chars_needed = x: {
170 var max_chars_needed: usize = 1; // 1 for the final null byte
170 var max_chars_needed: usize = 4; // 4 for the final 4 null bytes
171171 var it = env_map.iterator();
172172 while (it.next()) |pair| {
173173 // +1 for '='
......@@ -191,6 +191,12 @@ pub fn createWindowsEnvBlock(allocator: *mem.Allocator, env_map: *const BufMap)
191191 }
192192 result[i] = 0;
193193 i += 1;
194 result[i] = 0;
195 i += 1;
196 result[i] = 0;
197 i += 1;
198 result[i] = 0;
199 i += 1;
194200 return allocator.shrink(u16, result, i);
195201}
196202
std/special/init-exe/build.zig+2-2
......@@ -5,10 +5,10 @@ pub fn build(b: *Builder) void {
55 const exe = b.addExecutable("$", "src/main.zig");
66 exe.setBuildMode(mode);
77
8 const run_cmd = exe.run();
9
810 const run_step = b.step("run", "Run the app");
9 const run_cmd = b.addCommand(".", b.env_map, [][]const u8{exe.getOutputPath()});
1011 run_step.dependOn(&run_cmd.step);
11 run_cmd.step.dependOn(&exe.step);
1212
1313 b.default_step.dependOn(&exe.step);
1414 b.installArtifact(exe);
test/cli.zig+3-3
......@@ -116,12 +116,12 @@ fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void {
116116 const args = [][]const u8{
117117 zig_exe, "build-obj",
118118 "--cache-dir", dir_path,
119 "--output", example_s_path,
120 "--output-h", "/dev/null",
119 "--name", "example",
120 "--output-dir", dir_path,
121121 "--emit", "asm",
122122 "-mllvm", "--x86-asm-syntax=intel",
123123 "--strip", "--release-fast",
124 example_zig_path,
124 example_zig_path, "--disable-gen-h",
125125 };
126126 _ = try exec(dir_path, args);
127127
test/standalone/load_dynamic_library/build.zig+2-6
......@@ -9,12 +9,8 @@ pub fn build(b: *Builder) void {
99 const main = b.addExecutable("main", "main.zig");
1010 main.setBuildMode(opts);
1111
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);
1814
1915 const test_step = b.step("test", "Test the program");
2016 test_step.dependOn(&run.step);
test/standalone/pkg_import/build.zig+1-2
......@@ -9,8 +9,7 @@ pub fn build(b: *Builder) void {
99 exe.setBuildMode(b.standardReleaseOptions());
1010 exe.setBuildMode(b.standardReleaseOptions());
1111
12 const run = b.addCommand(".", b.env_map, [][]const u8{exe.getOutputPath()});
13 run.step.dependOn(&exe.step);
12 const run = exe.run();
1413
1514 const test_step = b.step("test", "Test it");
1615 test_step.dependOn(&run.step);
test/tests.zig+49-33
......@@ -12,6 +12,7 @@ const fmt = std.fmt;
1212const ArrayList = std.ArrayList;
1313const builtin = @import("builtin");
1414const Mode = builtin.Mode;
15const LibExeObjStep = build.LibExeObjStep;
1516
1617const compare_output = @import("compare_output.zig");
1718const build_examples = @import("build_examples.zig");
......@@ -111,12 +112,11 @@ pub fn addCliTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const M
111112 const step = b.step("test-cli", "Test the command line interface");
112113
113114 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{
116117 os.path.realAlloc(b.allocator, b.zig_exe) catch unreachable,
117118 b.pathFromRoot(b.cache_root),
118119 });
119 run_cmd.step.dependOn(&exe.step);
120120
121121 step.dependOn(&run_cmd.step);
122122 return step;
......@@ -246,24 +246,31 @@ pub const CompareOutputContext = struct {
246246 const RunCompareOutputStep = struct {
247247 step: build.Step,
248248 context: *CompareOutputContext,
249 exe_path: []const u8,
249 exe: *LibExeObjStep,
250250 name: []const u8,
251251 expected_output: []const u8,
252252 test_index: usize,
253253 cli_args: []const []const u8,
254254
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 {
256262 const allocator = context.b.allocator;
257263 const ptr = allocator.create(RunCompareOutputStep) catch unreachable;
258264 ptr.* = RunCompareOutputStep{
259265 .context = context,
260 .exe_path = exe_path,
266 .exe = exe,
261267 .name = name,
262268 .expected_output = expected_output,
263269 .test_index = context.test_index,
264270 .step = build.Step.init("RunCompareOutput", allocator, make),
265271 .cli_args = cli_args,
266272 };
273 ptr.step.dependOn(&exe.step);
267274 context.test_index += 1;
268275 return ptr;
269276 }
......@@ -272,7 +279,7 @@ pub const CompareOutputContext = struct {
272279 const self = @fieldParentPtr(RunCompareOutputStep, "step", step);
273280 const b = self.context.b;
274281
275 const full_exe_path = b.pathFromRoot(self.exe_path);
282 const full_exe_path = self.exe.getOutputPath();
276283 var args = ArrayList([]const u8).init(b.allocator);
277284 defer args.deinit();
278285
......@@ -336,21 +343,21 @@ pub const CompareOutputContext = struct {
336343 const RuntimeSafetyRunStep = struct {
337344 step: build.Step,
338345 context: *CompareOutputContext,
339 exe_path: []const u8,
346 exe: *LibExeObjStep,
340347 name: []const u8,
341348 test_index: usize,
342349
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 {
344351 const allocator = context.b.allocator;
345352 const ptr = allocator.create(RuntimeSafetyRunStep) catch unreachable;
346353 ptr.* = RuntimeSafetyRunStep{
347354 .context = context,
348 .exe_path = exe_path,
355 .exe = exe,
349356 .name = name,
350357 .test_index = context.test_index,
351358 .step = build.Step.init("RuntimeSafetyRun", allocator, make),
352359 };
353
360 ptr.step.dependOn(&exe.step);
354361 context.test_index += 1;
355362 return ptr;
356363 }
......@@ -359,11 +366,11 @@ pub const CompareOutputContext = struct {
359366 const self = @fieldParentPtr(RuntimeSafetyRunStep, "step", step);
360367 const b = self.context.b;
361368
362 const full_exe_path = b.pathFromRoot(self.exe_path);
369 const full_exe_path = self.exe.getOutputPath();
363370
364371 warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
365372
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;
367374 defer child.deinit();
368375
369376 child.env_map = b.env_map;
......@@ -463,8 +470,13 @@ pub const CompareOutputContext = struct {
463470 exe.step.dependOn(&write_src.step);
464471 }
465472
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 );
468480
469481 self.step.dependOn(&run_and_cmp_output.step);
470482 },
......@@ -490,8 +502,13 @@ pub const CompareOutputContext = struct {
490502 exe.step.dependOn(&write_src.step);
491503 }
492504
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 );
495512
496513 self.step.dependOn(&run_and_cmp_output.step);
497514 }
......@@ -516,8 +533,7 @@ pub const CompareOutputContext = struct {
516533 exe.step.dependOn(&write_src.step);
517534 }
518535
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);
521537
522538 self.step.dependOn(&run_and_cmp_output.step);
523539 },
......@@ -608,10 +624,6 @@ pub const CompileErrorContext = struct {
608624 b.allocator,
609625 [][]const u8{ b.cache_root, self.case.sources.items[0].filename },
610626 ) catch unreachable;
611 const obj_path = os.path.join(
612 b.allocator,
613 [][]const u8{ b.cache_root, "test.o" },
614 ) catch unreachable;
615627
616628 var zig_args = ArrayList([]const u8).init(b.allocator);
617629 zig_args.append(b.zig_exe) catch unreachable;
......@@ -628,8 +640,8 @@ pub const CompileErrorContext = struct {
628640 zig_args.append("--name") catch unreachable;
629641 zig_args.append("test") catch unreachable;
630642
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;
633645
634646 switch (self.build_mode) {
635647 Mode.Debug => {},
......@@ -851,7 +863,7 @@ pub const BuildExamplesContext = struct {
851863 zig_args.append("--verbose") catch unreachable;
852864 }
853865
854 const run_cmd = b.addCommand(null, b.env_map, zig_args.toSliceConst());
866 const run_cmd = b.addSystemCommand(zig_args.toSliceConst());
855867
856868 const log_step = b.addLog("PASS {}\n", annotated_case_name);
857869 log_step.step.dependOn(&run_cmd.step);
......@@ -1118,23 +1130,28 @@ pub const GenHContext = struct {
11181130 const GenHCmpOutputStep = struct {
11191131 step: build.Step,
11201132 context: *GenHContext,
1121 h_path: []const u8,
1133 obj: *LibExeObjStep,
11221134 name: []const u8,
11231135 test_index: usize,
11241136 case: *const TestCase,
11251137
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 {
11271144 const allocator = context.b.allocator;
11281145 const ptr = allocator.create(GenHCmpOutputStep) catch unreachable;
11291146 ptr.* = GenHCmpOutputStep{
11301147 .step = build.Step.init("ParseCCmpOutput", allocator, make),
11311148 .context = context,
1132 .h_path = h_path,
1149 .obj = obj,
11331150 .name = name,
11341151 .test_index = context.test_index,
11351152 .case = case,
11361153 };
1137
1154 ptr.step.dependOn(&obj.step);
11381155 context.test_index += 1;
11391156 return ptr;
11401157 }
......@@ -1145,7 +1162,7 @@ pub const GenHContext = struct {
11451162
11461163 warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
11471164
1148 const full_h_path = b.pathFromRoot(self.h_path);
1165 const full_h_path = self.obj.getOutputHPath();
11491166 const actual_h = try io.readFileAlloc(b.allocator, full_h_path);
11501167
11511168 for (self.case.expected_lines.toSliceConst()) |expected_line| {
......@@ -1218,8 +1235,7 @@ pub const GenHContext = struct {
12181235 obj.step.dependOn(&write_src.step);
12191236 }
12201237
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);
12231239
12241240 self.step.dependOn(&cmp_h.step);
12251241 }