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 {...@@ -20,8 +20,8 @@ pub fn build(b: *Builder) !void {
20 b.allocator,20 b.allocator,
21 [][]const u8{ b.cache_root, "langref.html" },21 [][]const u8{ b.cache_root, "langref.html" },
22 ) catch unreachable;22 ) catch unreachable;
23 var docgen_cmd = b.addCommand(null, b.env_map, [][]const u8{23 var docgen_cmd = docgen_exe.run();
24 docgen_exe.getOutputPath(),24 docgen_cmd.addArgs([][]const u8{
25 rel_zig_exe,25 rel_zig_exe,
26 "doc" ++ os.path.sep_str ++ "langref.html.in",26 "doc" ++ os.path.sep_str ++ "langref.html.in",
27 langref_out_path,27 langref_out_path,
doc/docgen.zig+14-12
...@@ -1011,8 +1011,10 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var...@@ -1011,8 +1011,10 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
1011 zig_exe,1011 zig_exe,
1012 "build-exe",1012 "build-exe",
1013 tmp_source_file_name,1013 tmp_source_file_name,
1014 "--output",1014 "--output-dir",
1015 tmp_bin_file_name,1015 tmp_dir_name,
1016 "--name",
1017 code.name,
1016 });1018 });
1017 try out.print("<pre><code class=\"shell\">$ zig build-exe {}.zig", code.name);1019 try out.print("<pre><code class=\"shell\">$ zig build-exe {}.zig", code.name);
1018 switch (code.mode) {1020 switch (code.mode) {
...@@ -1085,8 +1087,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var...@@ -1085,8 +1087,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
1085 zig_exe,1087 zig_exe,
1086 "test",1088 "test",
1087 tmp_source_file_name,1089 tmp_source_file_name,
1088 "--output",1090 "--output-dir",
1089 test_out_path,1091 tmp_dir_name,
1090 });1092 });
1091 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", code.name);1093 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", code.name);
1092 switch (code.mode) {1094 switch (code.mode) {
...@@ -1122,8 +1124,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var...@@ -1122,8 +1124,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
1122 "--color",1124 "--color",
1123 "on",1125 "on",
1124 tmp_source_file_name,1126 tmp_source_file_name,
1125 "--output",1127 "--output-dir",
1126 test_out_path,1128 tmp_dir_name,
1127 });1129 });
1128 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", code.name);1130 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", code.name);
1129 switch (code.mode) {1131 switch (code.mode) {
...@@ -1179,8 +1181,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var...@@ -1179,8 +1181,8 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
1179 zig_exe,1181 zig_exe,
1180 "test",1182 "test",
1181 tmp_source_file_name,1183 tmp_source_file_name,
1182 "--output",1184 "--output-dir",
1183 test_out_path,1185 tmp_dir_name,
1184 });1186 });
1185 switch (code.mode) {1187 switch (code.mode) {
1186 builtin.Mode.Debug => {},1188 builtin.Mode.Debug => {},
...@@ -1239,10 +1241,10 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var...@@ -1239,10 +1241,10 @@ fn genHtml(allocator: *mem.Allocator, tokenizer: *Tokenizer, toc: *Toc, out: var
1239 tmp_source_file_name,1241 tmp_source_file_name,
1240 "--color",1242 "--color",
1241 "on",1243 "on",
1242 "--output",1244 "--name",
1243 tmp_obj_file_name,1245 code.name,
1244 "--output-h",1246 "--output-dir",
1245 output_h_file_name,1247 tmp_dir_name,
1246 });1248 });
12471249
1248 if (!code.is_inline) {1250 if (!code.is_inline) {
doc/langref.html.in+1-2
...@@ -7914,8 +7914,7 @@ pub fn build(b: *Builder) void {...@@ -7914,8 +7914,7 @@ pub fn build(b: *Builder) void {
79147914
7915 b.default_step.dependOn(&exe.step);7915 b.default_step.dependOn(&exe.step);
79167916
7917 const run_cmd = b.addCommand(".", b.env_map, [][]const u8{exe.getOutputPath()});7917 const run_cmd = exe.run();
7918 run_cmd.step.dependOn(&exe.step);
79197918
7920 const test_step = b.step("test", "Test the program");7919 const test_step = b.step("test", "Test the program");
7921 test_step.dependOn(&run_cmd.step);7920 test_step.dependOn(&run_cmd.step);
example/mix_o_files/build.zig+2-3
...@@ -4,14 +4,13 @@ pub fn build(b: *Builder) void {...@@ -4,14 +4,13 @@ pub fn build(b: *Builder) void {
4 const obj = b.addObject("base64", "base64.zig");4 const obj = b.addObject("base64", "base64.zig");
55
6 const exe = b.addExecutable("test", null);6 const exe = b.addExecutable("test", null);
7 exe.addCSourceFile("test.c",[][]const u8{"-std=c99"});7 exe.addCSourceFile("test.c", [][]const u8{"-std=c99"});
8 exe.addObject(obj);8 exe.addObject(obj);
9 exe.linkSystemLibrary("c");9 exe.linkSystemLibrary("c");
1010
11 b.default_step.dependOn(&exe.step);11 b.default_step.dependOn(&exe.step);
1212
13 const run_cmd = b.addCommand(".", b.env_map, [][]const u8{exe.getOutputPath()});13 const run_cmd = exe.run();
14 run_cmd.step.dependOn(&exe.step);
1514
16 const test_step = b.step("test", "Test the program");15 const test_step = b.step("test", "Test the program");
17 test_step.dependOn(&run_cmd.step);16 test_step.dependOn(&run_cmd.step);
example/shared_library/build.zig+1-2
...@@ -10,8 +10,7 @@ pub fn build(b: *Builder) void {...@@ -10,8 +10,7 @@ pub fn build(b: *Builder) void {
1010
11 b.default_step.dependOn(&exe.step);11 b.default_step.dependOn(&exe.step);
1212
13 const run_cmd = b.addCommand(".", b.env_map, [][]const u8{exe.getOutputPath()});13 const run_cmd = exe.run();
14 run_cmd.step.dependOn(&exe.step);
1514
16 const test_step = b.step("test", "Test the program");15 const test_step = b.step("test", "Test the program");
17 test_step.dependOn(&run_cmd.step);16 test_step.dependOn(&run_cmd.step);
src/all_types.hpp+5-6
...@@ -1087,7 +1087,6 @@ struct RootStruct {...@@ -1087,7 +1087,6 @@ struct RootStruct {
1087 Buf *path; // relative to root_package->root_src_dir1087 Buf *path; // relative to root_package->root_src_dir
1088 ZigList<size_t> *line_offsets;1088 ZigList<size_t> *line_offsets;
1089 Buf *source_code;1089 Buf *source_code;
1090 AstNode *c_import_node;
1091 ZigLLVMDIFile *di_file;1090 ZigLLVMDIFile *di_file;
1092};1091};
10931092
...@@ -1746,13 +1745,12 @@ struct CodeGen {...@@ -1746,13 +1745,12 @@ struct CodeGen {
17461745
1747 Buf triple_str;1746 Buf triple_str;
1748 Buf global_asm;1747 Buf global_asm;
1749 Buf *out_h_path;
1750 Buf *out_lib_path;
1751 Buf artifact_dir;
1752 Buf output_file_path;1748 Buf output_file_path;
1753 Buf o_file_output_path;1749 Buf o_file_output_path;
1754 Buf *wanted_output_file_path;
1755 Buf *cache_dir;1750 Buf *cache_dir;
1751 // As an input parameter, mutually exclusive with enable_cache. But it gets
1752 // populated in codegen_build_and_link.
1753 Buf *output_dir;
1756 Buf **libc_include_dir_list;1754 Buf **libc_include_dir_list;
1757 size_t libc_include_dir_len;1755 size_t libc_include_dir_len;
17581756
...@@ -1804,7 +1802,7 @@ struct CodeGen {...@@ -1804,7 +1802,7 @@ struct CodeGen {
1804 bool verbose_cc;1802 bool verbose_cc;
1805 bool error_during_imports;1803 bool error_during_imports;
1806 bool generate_error_name_table;1804 bool generate_error_name_table;
1807 bool enable_cache;1805 bool enable_cache; // mutually exclusive with output_dir
1808 bool enable_time_report;1806 bool enable_time_report;
1809 bool system_linker_hack;1807 bool system_linker_hack;
1810 bool reported_bad_link_libc_error;1808 bool reported_bad_link_libc_error;
...@@ -1844,6 +1842,7 @@ struct CodeGen {...@@ -1844,6 +1842,7 @@ struct CodeGen {
1844 bool each_lib_rpath;1842 bool each_lib_rpath;
1845 bool disable_pic;1843 bool disable_pic;
1846 bool is_dummy_so;1844 bool is_dummy_so;
1845 bool disable_gen_h;
18471846
1848 Buf *mmacosx_version_min;1847 Buf *mmacosx_version_min;
1849 Buf *mios_version_min;1848 Buf *mios_version_min;
src/analyze.cpp+3-28
...@@ -35,20 +35,6 @@ static bool is_top_level_struct(ZigType *import) {...@@ -35,20 +35,6 @@ static bool is_top_level_struct(ZigType *import) {
35static ErrorMsg *add_error_note_token(CodeGen *g, ErrorMsg *parent_msg, ZigType *owner, Token *token, Buf *msg) {35static ErrorMsg *add_error_note_token(CodeGen *g, ErrorMsg *parent_msg, ZigType *owner, Token *token, Buf *msg) {
36 assert(is_top_level_struct(owner));36 assert(is_top_level_struct(owner));
37 RootStruct *root_struct = owner->data.structure.root_struct;37 RootStruct *root_struct = owner->data.structure.root_struct;
38 if (root_struct->c_import_node != nullptr) {
39 // if this happens, then translate_c generated code that
40 // failed semantic analysis, which isn't supposed to happen
41
42 Buf *note_path = buf_create_from_str("?.c");
43 Buf *note_source = buf_create_from_str("TODO: remember C source location to display here ");
44 ZigList<size_t> note_line_offsets = {0};
45 note_line_offsets.append(0);
46 ErrorMsg *note = err_msg_create_with_line(note_path, 0, 0,
47 note_source, &note_line_offsets, msg);
48
49 err_msg_add_note(parent_msg, note);
50 return note;
51 }
5238
53 ErrorMsg *err = err_msg_create_with_line(root_struct->path, token->start_line, token->start_column,39 ErrorMsg *err = err_msg_create_with_line(root_struct->path, token->start_line, token->start_column,
54 root_struct->source_code, root_struct->line_offsets, msg);40 root_struct->source_code, root_struct->line_offsets, msg);
...@@ -60,17 +46,6 @@ static ErrorMsg *add_error_note_token(CodeGen *g, ErrorMsg *parent_msg, ZigType...@@ -60,17 +46,6 @@ static ErrorMsg *add_error_note_token(CodeGen *g, ErrorMsg *parent_msg, ZigType
60ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, Token *token, Buf *msg) {46ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, Token *token, Buf *msg) {
61 assert(is_top_level_struct(owner));47 assert(is_top_level_struct(owner));
62 RootStruct *root_struct = owner->data.structure.root_struct;48 RootStruct *root_struct = owner->data.structure.root_struct;
63 if (root_struct->c_import_node != nullptr) {
64 // if this happens, then translate_c generated code that
65 // failed semantic analysis, which isn't supposed to happen
66 ErrorMsg *err = add_node_error(g, root_struct->c_import_node,
67 buf_sprintf("compiler bug: @cImport generated invalid zig code"));
68
69 add_error_note_token(g, err, owner, token, msg);
70
71 g->errors.append(err);
72 return err;
73 }
74 ErrorMsg *err = err_msg_create_with_line(root_struct->path, token->start_line, token->start_column,49 ErrorMsg *err = err_msg_create_with_line(root_struct->path, token->start_line, token->start_column,
75 root_struct->source_code, root_struct->line_offsets, msg);50 root_struct->source_code, root_struct->line_offsets, msg);
7651
...@@ -1300,7 +1275,7 @@ static ZigTypeId container_to_type(ContainerKind kind) {...@@ -1300,7 +1275,7 @@ static ZigTypeId container_to_type(ContainerKind kind) {
1300}1275}
13011276
1302// This is like get_partial_container_type except it's for the implicit root struct of files.1277// 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,
1304 RootStruct *root_struct)1279 RootStruct *root_struct)
1305{1280{
1306 ZigType *entry = new_type_table_entry(ZigTypeIdStruct);1281 ZigType *entry = new_type_table_entry(ZigTypeIdStruct);
...@@ -4503,11 +4478,11 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu...@@ -4503,11 +4478,11 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu
4503 Buf *pkg_root_src_dir = &package->root_src_dir;4478 Buf *pkg_root_src_dir = &package->root_src_dir;
4504 Buf resolved_root_src_dir = os_path_resolve(&pkg_root_src_dir, 1);4479 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
4508 Buf namespace_name = BUF_INIT;4481 Buf namespace_name = BUF_INIT;
4509 buf_init_from_buf(&namespace_name, &package->pkg_path);4482 buf_init_from_buf(&namespace_name, &package->pkg_path);
4510 if (source_kind == SourceKindNonRoot) {4483 if (source_kind == SourceKindNonRoot) {
4484 assert(buf_starts_with_buf(resolved_path, &resolved_root_src_dir));
4485
4511 if (buf_len(&namespace_name) != 0) buf_append_char(&namespace_name, NAMESPACE_SEP_CHAR);4486 if (buf_len(&namespace_name) != 0) buf_append_char(&namespace_name, NAMESPACE_SEP_CHAR);
4512 buf_append_mem(&namespace_name, buf_ptr(&noextname) + buf_len(&resolved_root_src_dir) + 1,4487 buf_append_mem(&namespace_name, buf_ptr(&noextname) + buf_len(&resolved_root_src_dir) + 1,
4513 buf_len(&noextname) - (buf_len(&resolved_root_src_dir) + 1));4488 buf_len(&noextname) - (buf_len(&resolved_root_src_dir) + 1));
src/analyze.hpp+3-2
...@@ -31,8 +31,6 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size);...@@ -31,8 +31,6 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size);
31ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type);31ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type);
32ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,32ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,
33 AstNode *decl_node, const char *full_name, Buf *bare_name, ContainerLayout layout);33 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);
36ZigType *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x);34ZigType *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x);
37ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payload_type);35ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payload_type);
38ZigType *get_bound_fn_type(CodeGen *g, ZigFn *fn_entry);36ZigType *get_bound_fn_type(CodeGen *g, ZigFn *fn_entry);
...@@ -53,6 +51,7 @@ enum SourceKind {...@@ -53,6 +51,7 @@ enum SourceKind {
53 SourceKindRoot,51 SourceKindRoot,
54 SourceKindPkgMain,52 SourceKindPkgMain,
55 SourceKindNonRoot,53 SourceKindNonRoot,
54 SourceKindCImport,
56};55};
57ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *abs_full_path, Buf *source_code,56ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *abs_full_path, Buf *source_code,
58 SourceKind source_kind);57 SourceKind source_kind);
...@@ -242,4 +241,6 @@ Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_no...@@ -242,4 +241,6 @@ Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_no
242void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn);241void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn);
243Buf *type_bare_name(ZigType *t);242Buf *type_bare_name(ZigType *t);
244Buf *type_h_name(ZigType *t);243Buf *type_h_name(ZigType *t);
244Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose);
245
245#endif246#endif
src/ast_render.cpp+7-4
...@@ -317,7 +317,7 @@ static bool is_digit(uint8_t c) {...@@ -317,7 +317,7 @@ static bool is_digit(uint8_t c) {
317317
318static bool is_printable(uint8_t c) {318static bool is_printable(uint8_t c) {
319 static const uint8_t printables[] =319 static const uint8_t printables[] =
320 " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.~`!@#$%^&*()_-+=\\{}[];'\"?/<>,";320 " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.~`!@#$%^&*()_-+=\\{}[];'\"?/<>,:";
321 for (size_t i = 0; i < array_length(printables); i += 1) {321 for (size_t i = 0; i < array_length(printables); i += 1) {
322 if (c == printables[i]) return true;322 if (c == printables[i]) return true;
323 }323 }
...@@ -328,9 +328,7 @@ static void string_literal_escape(Buf *source, Buf *dest) {...@@ -328,9 +328,7 @@ static void string_literal_escape(Buf *source, Buf *dest) {
328 buf_resize(dest, 0);328 buf_resize(dest, 0);
329 for (size_t i = 0; i < buf_len(source); i += 1) {329 for (size_t i = 0; i < buf_len(source); i += 1) {
330 uint8_t c = *((uint8_t*)buf_ptr(source) + i);330 uint8_t c = *((uint8_t*)buf_ptr(source) + i);
331 if (is_printable(c)) {331 if (c == '\'') {
332 buf_append_char(dest, c);
333 } else if (c == '\'') {
334 buf_append_str(dest, "\\'");332 buf_append_str(dest, "\\'");
335 } else if (c == '"') {333 } else if (c == '"') {
336 buf_append_str(dest, "\\\"");334 buf_append_str(dest, "\\\"");
...@@ -350,6 +348,8 @@ static void string_literal_escape(Buf *source, Buf *dest) {...@@ -350,6 +348,8 @@ static void string_literal_escape(Buf *source, Buf *dest) {
350 buf_append_str(dest, "\\t");348 buf_append_str(dest, "\\t");
351 } else if (c == '\v') {349 } else if (c == '\v') {
352 buf_append_str(dest, "\\v");350 buf_append_str(dest, "\\v");
351 } else if (is_printable(c)) {
352 buf_append_char(dest, c);
353 } else {353 } else {
354 buf_appendf(dest, "\\x%x", (int)c);354 buf_appendf(dest, "\\x%x", (int)c);
355 }355 }
...@@ -470,6 +470,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -470,6 +470,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
470 fprintf(ar->f, ", ");470 fprintf(ar->f, ", ");
471 }471 }
472 }472 }
473 if (node->data.fn_proto.is_var_args) {
474 fprintf(ar->f, ", ...");
475 }
473 fprintf(ar->f, ")");476 fprintf(ar->f, ")");
474 if (node->data.fn_proto.align_expr) {477 if (node->data.fn_proto.align_expr) {
475 fprintf(ar->f, " align(");478 fprintf(ar->f, " align(");
src/cache_hash.cpp+30-20
...@@ -19,6 +19,8 @@ void cache_init(CacheHash *ch, Buf *manifest_dir) {...@@ -19,6 +19,8 @@ void cache_init(CacheHash *ch, Buf *manifest_dir) {
19 ch->manifest_dir = manifest_dir;19 ch->manifest_dir = manifest_dir;
20 ch->manifest_file_path = nullptr;20 ch->manifest_file_path = nullptr;
21 ch->manifest_dirty = false;21 ch->manifest_dirty = false;
22 ch->force_check_manifest = false;
23 ch->b64_digest = BUF_INIT;
22}24}
2325
24void cache_str(CacheHash *ch, const char *ptr) {26void cache_str(CacheHash *ch, const char *ptr) {
...@@ -243,22 +245,21 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {...@@ -243,22 +245,21 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
243 int rc = blake2b_final(&ch->blake, bin_digest, 48);245 int rc = blake2b_final(&ch->blake, bin_digest, 48);
244 assert(rc == 0);246 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) {
247 buf_resize(out_digest, 64);252 buf_resize(out_digest, 64);
248 base64_encode(buf_to_slice(out_digest), {bin_digest, 48});253 base64_encode(buf_to_slice(out_digest), {bin_digest, 48});
249 return ErrorNone;254 return ErrorNone;
250 }255 }
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
256 rc = blake2b_init(&ch->blake, 48);257 rc = blake2b_init(&ch->blake, 48);
257 assert(rc == 0);258 assert(rc == 0);
258 blake2b_update(&ch->blake, bin_digest, 48);259 blake2b_update(&ch->blake, bin_digest, 48);
259260
260 ch->manifest_file_path = buf_alloc();261 ch->manifest_file_path = buf_alloc();
261 os_path_join(ch->manifest_dir, &b64_digest, ch->manifest_file_path);262 os_path_join(ch->manifest_dir, &ch->b64_digest, ch->manifest_file_path);
262263
263 buf_append_str(ch->manifest_file_path, ".txt");264 buf_append_str(ch->manifest_file_path, ".txt");
264265
...@@ -380,7 +381,7 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {...@@ -380,7 +381,7 @@ Error cache_hit(CacheHash *ch, Buf *out_digest) {
380 blake2b_update(&ch->blake, chf->bin_digest, 48);381 blake2b_update(&ch->blake, chf->bin_digest, 48);
381 }382 }
382 }383 }
383 if (file_i < input_file_count) {384 if (file_i < input_file_count || file_i == 0) {
384 // manifest file is empty or missing entries, so this is a cache miss385 // manifest file is empty or missing entries, so this is a cache miss
385 ch->manifest_dirty = true;386 ch->manifest_dirty = true;
386 for (; file_i < input_file_count; file_i += 1) {387 for (; file_i < input_file_count; file_i += 1) {
...@@ -442,6 +443,7 @@ Error cache_add_dep_file(CacheHash *ch, Buf *dep_file_path, bool verbose) {...@@ -442,6 +443,7 @@ Error cache_add_dep_file(CacheHash *ch, Buf *dep_file_path, bool verbose) {
442 }443 }
443 if (opt_line.value.len == 0)444 if (opt_line.value.len == 0)
444 continue;445 continue;
446
445 if (opt_line.value.ptr[0] == '"') {447 if (opt_line.value.ptr[0] == '"') {
446 if (opt_line.value.len < 2) {448 if (opt_line.value.len < 2) {
447 if (verbose) {449 if (verbose) {
...@@ -460,21 +462,29 @@ Error cache_add_dep_file(CacheHash *ch, Buf *dep_file_path, bool verbose) {...@@ -460,21 +462,29 @@ Error cache_add_dep_file(CacheHash *ch, Buf *dep_file_path, bool verbose) {
460 }462 }
461 return ErrorInvalidDepFile;463 return ErrorInvalidDepFile;
462 }464 }
463 } else {465 Buf *filename_buf = buf_create_from_slice(opt_line.value);
464 if (opt_line.value.ptr[opt_line.value.len - 1] == '\\') {466 if ((err = cache_add_file(ch, filename_buf))) {
465 opt_line.value.len -= 2; // cut off ` \`467 if (verbose) {
468 fprintf(stderr, "unable to add %s to cache: %s\n", buf_ptr(filename_buf), err_str(err));
469 fprintf(stderr, "when processing .d file: %s\n", buf_ptr(dep_file_path));
470 }
471 return err;
466 }472 }
467 if (opt_line.value.len == 0)473 } else {
468 continue;474 // sometimes there are multiple files on the same line; we actually need space tokenization.
469 }475 SplitIterator line_it = memSplit(opt_line.value, str(" \t"));
470476 Slice<uint8_t> filename;
471 Buf *filename_buf = buf_create_from_slice(opt_line.value);477 while (SplitIterator_next(&line_it).unwrap(&filename)) {
472 if ((err = cache_add_file(ch, filename_buf))) {478 Buf *filename_buf = buf_create_from_slice(filename);
473 if (verbose) {479 if (buf_eql_str(filename_buf, "\\")) continue;
474 fprintf(stderr, "unable to add %s to cache: %s\n", buf_ptr(filename_buf), err_str(err));480 if ((err = cache_add_file(ch, filename_buf))) {
475 fprintf(stderr, "when processing .d file: %s\n", buf_ptr(dep_file_path));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 }
476 }487 }
477 return err;
478 }488 }
479 }489 }
480 return ErrorNone;490 return ErrorNone;
src/cache_hash.hpp+6
...@@ -25,8 +25,10 @@ struct CacheHash {...@@ -25,8 +25,10 @@ struct CacheHash {
25 ZigList<CacheHashFile> files;25 ZigList<CacheHashFile> files;
26 Buf *manifest_dir;26 Buf *manifest_dir;
27 Buf *manifest_file_path;27 Buf *manifest_file_path;
28 Buf b64_digest;
28 OsFile manifest_file;29 OsFile manifest_file;
29 bool manifest_dirty;30 bool manifest_dirty;
31 bool force_check_manifest;
30};32};
3133
32// Always call this first to set up.34// Always call this first to set up.
...@@ -51,6 +53,10 @@ void cache_file_opt(CacheHash *ch, Buf *path);...@@ -51,6 +53,10 @@ void cache_file_opt(CacheHash *ch, Buf *path);
51// If you got a cache hit, the next step is cache_release.53// If you got a cache hit, the next step is cache_release.
52// From this point on, there is a lock on the input params. Release54// From this point on, there is a lock on the input params. Release
53// the lock with cache_release.55// the lock with cache_release.
56// Set force_check_manifest if you plan to add files later, but have not
57// added any files before calling cache_hit. CacheHash::b64_digest becomes
58// available for use after this call, even in the case of a miss, and it
59// is a hash of the input parameters only.
54Error ATTRIBUTE_MUST_USE cache_hit(CacheHash *ch, Buf *out_b64_digest);60Error ATTRIBUTE_MUST_USE cache_hit(CacheHash *ch, Buf *out_b64_digest);
5561
56// If you did not get a cache hit, call this function for every file62// If you did not get a cache hit, call this function for every file
src/codegen.cpp+115-130
...@@ -23,6 +23,9 @@...@@ -23,6 +23,9 @@
23#include <stdio.h>23#include <stdio.h>
24#include <errno.h>24#include <errno.h>
2525
26#define CACHE_OUT_SUBDIR "o"
27#define CACHE_HASH_SUBDIR "h"
28
26static void init_darwin_native(CodeGen *g) {29static void init_darwin_native(CodeGen *g) {
27 char *osx_target = getenv("MACOSX_DEPLOYMENT_TARGET");30 char *osx_target = getenv("MACOSX_DEPLOYMENT_TARGET");
28 char *ios_target = getenv("IPHONEOS_DEPLOYMENT_TARGET");31 char *ios_target = getenv("IPHONEOS_DEPLOYMENT_TARGET");
...@@ -196,18 +199,6 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget...@@ -196,18 +199,6 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
196 return g;199 return g;
197}200}
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
211void codegen_set_clang_argv(CodeGen *g, const char **args, size_t len) {202void codegen_set_clang_argv(CodeGen *g, const char **args, size_t len) {
212 g->clang_argv = args;203 g->clang_argv = args;
213 g->clang_argv_len = len;204 g->clang_argv_len = len;
...@@ -256,10 +247,6 @@ void codegen_set_out_name(CodeGen *g, Buf *out_name) {...@@ -256,10 +247,6 @@ void codegen_set_out_name(CodeGen *g, Buf *out_name) {
256 g->root_out_name = out_name;247 g->root_out_name = out_name;
257}248}
258249
259void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker_path) {
260 g->dynamic_linker_path = dynamic_linker_path;
261}
262
263void codegen_add_lib_dir(CodeGen *g, const char *dir) {250void codegen_add_lib_dir(CodeGen *g, const char *dir) {
264 g->lib_dirs.append(dir);251 g->lib_dirs.append(dir);
265}252}
...@@ -7766,7 +7753,10 @@ static Error define_builtin_compile_vars(CodeGen *g) {...@@ -7766,7 +7753,10 @@ static Error define_builtin_compile_vars(CodeGen *g) {
7766 }7753 }
7767 } else {7754 } else {
7768 contents = codegen_generate_builtin_source(g);7755 contents = codegen_generate_builtin_source(g);
7769 os_write_file(builtin_zig_path, contents);7756 if ((err = os_write_file(builtin_zig_path, contents))) {
7757 fprintf(stderr, "Unable to write file '%s': %s\n", buf_ptr(builtin_zig_path), err_str(err));
7758 exit(1);
7759 }
7770 }7760 }
77717761
7772 assert(g->root_package);7762 assert(g->root_package);
...@@ -8030,7 +8020,7 @@ static void detect_libc(CodeGen *g) {...@@ -8030,7 +8020,7 @@ static void detect_libc(CodeGen *g) {
8030 }8020 }
8031}8021}
80328022
8033void codegen_translate_c(CodeGen *g, Buf *full_path) {8023AstNode *codegen_translate_c(CodeGen *g, Buf *full_path) {
8034 Buf *src_basename = buf_alloc();8024 Buf *src_basename = buf_alloc();
8035 Buf *src_dirname = buf_alloc();8025 Buf *src_dirname = buf_alloc();
8036 os_path_split(full_path, src_dirname, src_basename);8026 os_path_split(full_path, src_dirname, src_basename);
...@@ -8042,16 +8032,9 @@ void codegen_translate_c(CodeGen *g, Buf *full_path) {...@@ -8042,16 +8032,9 @@ void codegen_translate_c(CodeGen *g, Buf *full_path) {
80428032
8043 init(g);8033 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
8053 ZigList<ErrorMsg *> errors = {0};8035 ZigList<ErrorMsg *> errors = {0};
8054 Error err = parse_h_file(import, &errors, buf_ptr(full_path), g, nullptr);8036 AstNode *root_node;
8037 Error err = parse_h_file(&root_node, &errors, buf_ptr(full_path), g, nullptr);
80558038
8056 if (err == ErrorCCompileErrors && errors.length > 0) {8039 if (err == ErrorCCompileErrors && errors.length > 0) {
8057 for (size_t i = 0; i < errors.length; i += 1) {8040 for (size_t i = 0; i < errors.length; i += 1) {
...@@ -8065,6 +8048,8 @@ void codegen_translate_c(CodeGen *g, Buf *full_path) {...@@ -8065,6 +8048,8 @@ void codegen_translate_c(CodeGen *g, Buf *full_path) {
8065 fprintf(stderr, "unable to parse C file: %s\n", err_str(err));8048 fprintf(stderr, "unable to parse C file: %s\n", err_str(err));
8066 exit(1);8049 exit(1);
8067 }8050 }
8051
8052 return root_node;
8068}8053}
80698054
8070static ZigType *add_special_code(CodeGen *g, ZigPackage *package, const char *basename) {8055static ZigType *add_special_code(CodeGen *g, ZigPackage *package, const char *basename) {
...@@ -8282,32 +8267,18 @@ static Error get_tmp_filename(CodeGen *g, Buf *out, Buf *suffix) {...@@ -8282,32 +8267,18 @@ static Error get_tmp_filename(CodeGen *g, Buf *out, Buf *suffix) {
8282 return ErrorNone;8267 return ErrorNone;
8283}8268}
82848269
8285// returns true if it was a cache miss8270Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose) {
8286static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
8287 Error err;8271 Error err;
8288
8289 Buf *artifact_dir;
8290 Buf *o_final_path;
8291
8292 Buf *o_dir = buf_alloc();
8293 os_path_join(g->cache_dir, buf_create_from_str("o"), o_dir);
8294
8295 Buf *c_source_file = buf_create_from_str(c_file->source_path);
8296 Buf *c_source_basename = buf_alloc();
8297 os_path_split(c_source_file, nullptr, c_source_basename);
8298 Buf *final_o_basename = buf_alloc();
8299 os_path_extname(c_source_basename, final_o_basename, nullptr);
8300 buf_append_str(final_o_basename, target_o_file_ext(g->zig_target));
8301
8302 CacheHash *cache_hash = allocate<CacheHash>(1);8272 CacheHash *cache_hash = allocate<CacheHash>(1);
8303 Buf *manifest_dir = buf_alloc();8273 Buf *manifest_dir = buf_sprintf("%s" OS_SEP CACHE_HASH_SUBDIR, buf_ptr(g->cache_dir));
8304 os_path_join(g->cache_dir, buf_create_from_str("c"), manifest_dir);
8305 cache_init(cache_hash, manifest_dir);8274 cache_init(cache_hash, manifest_dir);
83068275
8307 Buf *compiler_id;8276 Buf *compiler_id;
8308 if ((err = get_compiler_id(&compiler_id))) {8277 if ((err = get_compiler_id(&compiler_id))) {
8309 fprintf(stderr, "unable to get compiler id: %s\n", err_str(err));8278 if (verbose) {
8310 exit(1);8279 fprintf(stderr, "unable to get compiler id: %s\n", err_str(err));
8280 }
8281 return err;
8311 }8282 }
8312 cache_buf(cache_hash, compiler_id);8283 cache_buf(cache_hash, compiler_id);
8313 cache_int(cache_hash, g->err_color);8284 cache_int(cache_hash, g->err_color);
...@@ -8321,11 +8292,38 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {...@@ -8321,11 +8292,38 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
8321 cache_int(cache_hash, g->zig_target->abi);8292 cache_int(cache_hash, g->zig_target->abi);
8322 cache_bool(cache_hash, g->strip_debug_symbols);8293 cache_bool(cache_hash, g->strip_debug_symbols);
8323 cache_int(cache_hash, g->build_mode);8294 cache_int(cache_hash, g->build_mode);
8324 cache_file(cache_hash, c_source_file);
8325 cache_bool(cache_hash, g->disable_pic);8295 cache_bool(cache_hash, g->disable_pic);
8326 for (size_t arg_i = 0; arg_i < g->clang_argv_len; arg_i += 1) {8296 for (size_t arg_i = 0; arg_i < g->clang_argv_len; arg_i += 1) {
8327 cache_str(cache_hash, g->clang_argv[arg_i]);8297 cache_str(cache_hash, g->clang_argv[arg_i]);
8328 }8298 }
8299
8300 *out_cache_hash = cache_hash;
8301 return ErrorNone;
8302}
8303
8304// returns true if it was a cache miss
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
8329 // Note: not directory args, just args that always have a file next8327 // Note: not directory args, just args that always have a file next
8330 static const char *file_args[] = {8328 static const char *file_args[] = {
8331 "-include",8329 "-include",
...@@ -8787,11 +8785,13 @@ static void gen_h_file(CodeGen *g) {...@@ -8787,11 +8785,13 @@ static void gen_h_file(CodeGen *g) {
8787 GenH *gen_h = &gen_h_data;8785 GenH *gen_h = &gen_h_data;
87888786
8789 assert(!g->is_test_build);8787 assert(!g->is_test_build);
8790 assert(g->out_h_path != nullptr);8788 assert(!g->disable_gen_h);
8789
8790 Buf *out_h_path = buf_sprintf("%s" OS_SEP "%s.h", buf_ptr(g->output_dir), buf_ptr(g->root_out_name));
87918791
8792 FILE *out_h = fopen(buf_ptr(g->out_h_path), "wb");8792 FILE *out_h = fopen(buf_ptr(out_h_path), "wb");
8793 if (!out_h)8793 if (!out_h)
8794 zig_panic("unable to open %s: %s\n", buf_ptr(g->out_h_path), strerror(errno));8794 zig_panic("unable to open %s: %s\n", buf_ptr(out_h_path), strerror(errno));
87958795
8796 Buf *export_macro = preprocessor_mangle(buf_sprintf("%s_EXPORT", buf_ptr(g->root_out_name)));8796 Buf *export_macro = preprocessor_mangle(buf_sprintf("%s_EXPORT", buf_ptr(g->root_out_name)));
8797 buf_upcase(export_macro);8797 buf_upcase(export_macro);
...@@ -9065,6 +9065,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {...@@ -9065,6 +9065,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
9065 cache_bool(ch, g->linker_rdynamic);9065 cache_bool(ch, g->linker_rdynamic);
9066 cache_bool(ch, g->each_lib_rpath);9066 cache_bool(ch, g->each_lib_rpath);
9067 cache_bool(ch, g->disable_pic);9067 cache_bool(ch, g->disable_pic);
9068 cache_bool(ch, g->disable_gen_h);
9068 cache_bool(ch, g->valgrind_support);9069 cache_bool(ch, g->valgrind_support);
9069 cache_bool(ch, g->is_dummy_so);9070 cache_bool(ch, g->is_dummy_so);
9070 cache_buf_opt(ch, g->mmacosx_version_min);9071 cache_buf_opt(ch, g->mmacosx_version_min);
...@@ -9103,99 +9104,79 @@ static bool need_llvm_module(CodeGen *g) {...@@ -9103,99 +9104,79 @@ static bool need_llvm_module(CodeGen *g) {
9103 return g->assembly_files.length != 0 || buf_len(&g->root_package->root_src_path) != 0;9104 return g->assembly_files.length != 0 || buf_len(&g->root_package->root_src_path) != 0;
9104}9105}
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
9110static void resolve_out_paths(CodeGen *g) {9107static 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);
9113 switch (g->emit_file_type) {9113 switch (g->emit_file_type) {
9114 case EmitFileTypeBinary:9114 case EmitFileTypeBinary: {
9115 {9115 switch (g->out_type) {
9116 const char *o_ext = target_o_file_ext(g->zig_target);9116 case OutTypeUnknown:
9117 buf_append_str(o_basename, o_ext);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 }
9118 break;9145 break;
9119 }9146 }
9120 case EmitFileTypeAssembly:9147 case EmitFileTypeAssembly: {
9121 {
9122 const char *asm_ext = target_asm_file_ext(g->zig_target);9148 const char *asm_ext = target_asm_file_ext(g->zig_target);
9123 buf_append_str(o_basename, asm_ext);9149 buf_append_str(o_basename, asm_ext);
9150 buf_append_str(out_basename, asm_ext);
9124 break;9151 break;
9125 }9152 }
9126 case EmitFileTypeLLVMIr:9153 case EmitFileTypeLLVMIr: {
9127 {
9128 const char *llvm_ir_ext = target_llvm_ir_file_ext(g->zig_target);9154 const char *llvm_ir_ext = target_llvm_ir_file_ext(g->zig_target);
9129 buf_append_str(o_basename, llvm_ir_ext);9155 buf_append_str(o_basename, llvm_ir_ext);
9156 buf_append_str(out_basename, llvm_ir_ext);
9130 break;9157 break;
9131 }9158 }
9132 default:
9133 zig_unreachable();
9134 }
9135
9136 if (compilation_is_already_done(g)) {
9137 buf_init_from_str(&g->o_file_output_path, buf_ptr(g->link_objects.at(0)));
9138 } else if (g->enable_cache || g->out_type != OutTypeObj) {
9139 os_path_join(&g->artifact_dir, o_basename, &g->o_file_output_path);
9140 } else if (g->wanted_output_file_path != nullptr && g->out_type == OutTypeObj) {
9141 buf_init_from_buf(&g->o_file_output_path, g->wanted_output_file_path);
9142 } else {
9143 buf_init_from_buf(&g->o_file_output_path, o_basename);
9144 }
9145
9146 if (!g->enable_cache && g->wanted_output_file_path != nullptr) {
9147 buf_init_from_buf(&g->output_file_path, g->wanted_output_file_path);
9148 return;
9149 }
9150
9151 if (compilation_is_already_done(g)) {
9152 buf_init_from_buf(&g->output_file_path, &g->o_file_output_path);
9153 return;
9154 }
9155
9156 const char *prefix = "";
9157 const char *extname;
9158 switch (g->out_type) {
9159 case OutTypeUnknown:
9160 zig_unreachable();
9161 case OutTypeObj:
9162 extname = target_o_file_ext(g->zig_target);
9163 break;
9164 case OutTypeExe:
9165 extname = target_exe_file_ext(g->zig_target);
9166 break;
9167 case OutTypeLib:
9168 prefix = target_lib_file_prefix(g->zig_target);
9169 extname = target_lib_file_ext(g->zig_target, g->is_static,
9170 g->version_major, g->version_minor, g->version_patch);
9171 break;
9172 }9159 }
91739160
9174 assert(g->root_out_name);9161 os_path_join(g->output_dir, o_basename, &g->o_file_output_path);
91759162 os_path_join(g->output_dir, out_basename, &g->output_file_path);
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 }
9185}9163}
91869164
9187void codegen_build_and_link(CodeGen *g) {9165void codegen_build_and_link(CodeGen *g) {
9188 Error err;9166 Error err;
9189 assert(g->out_type != OutTypeUnknown);9167 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
9191 detect_libc(g);9173 detect_libc(g);
9192 detect_dynamic_linker(g);9174 detect_dynamic_linker(g);
91939175
9194 Buf *artifact_dir = buf_alloc();
9195 Buf digest = BUF_INIT;9176 Buf digest = BUF_INIT;
9196 if (g->enable_cache) {9177 if (g->enable_cache) {
9197 Buf *manifest_dir = buf_alloc();9178 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
9200 if ((err = check_cache(g, manifest_dir, &digest))) {9181 if ((err = check_cache(g, manifest_dir, &digest))) {
9201 if (err == ErrorCacheUnavailable) {9182 if (err == ErrorCacheUnavailable) {
...@@ -9208,15 +9189,14 @@ void codegen_build_and_link(CodeGen *g) {...@@ -9208,15 +9189,14 @@ void codegen_build_and_link(CodeGen *g) {
9208 }9189 }
9209 exit(1);9190 exit(1);
9210 }9191 }
9211
9212 os_path_join(g->cache_dir, buf_create_from_str("artifact"), artifact_dir);
9213 } else {9192 } else {
9214 // There is a call to this in check_cache9193 // There is a call to this in check_cache
9215 gen_c_objects(g);9194 gen_c_objects(g);
9216 }9195 }
92179196
9218 if (g->enable_cache && buf_len(&digest) != 0) {9197 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));
9220 resolve_out_paths(g);9200 resolve_out_paths(g);
9221 } else {9201 } else {
9222 if (need_llvm_module(g)) {9202 if (need_llvm_module(g)) {
...@@ -9235,13 +9215,13 @@ void codegen_build_and_link(CodeGen *g) {...@@ -9235,13 +9215,13 @@ void codegen_build_and_link(CodeGen *g) {
9235 exit(1);9215 exit(1);
9236 }9216 }
9237 }9217 }
9238 os_path_join(artifact_dir, &digest, &g->artifact_dir);9218 g->output_dir = buf_sprintf("%s" OS_SEP CACHE_OUT_SUBDIR OS_SEP "%s",
9239 } else {9219 buf_ptr(g->cache_dir), buf_ptr(&digest));
9240 buf_init_from_buf(&g->artifact_dir, g->cache_dir);9220
9241 }9221 if ((err = os_make_path(g->output_dir))) {
9242 if ((err = os_make_path(&g->artifact_dir))) {9222 fprintf(stderr, "Unable to create output directory: %s\n", err_str(err));
9243 fprintf(stderr, "Unable to create artifact directory: %s\n", err_str(err));9223 exit(1);
9244 exit(1);9224 }
9245 }9225 }
9246 resolve_out_paths(g);9226 resolve_out_paths(g);
92479227
...@@ -9252,14 +9232,19 @@ void codegen_build_and_link(CodeGen *g) {...@@ -9252,14 +9232,19 @@ void codegen_build_and_link(CodeGen *g) {
9252 codegen_add_time_event(g, "LLVM Emit Output");9232 codegen_add_time_event(g, "LLVM Emit Output");
9253 zig_llvm_emit_output(g);9233 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)) {
9256 codegen_add_time_event(g, "Generate .h");9236 codegen_add_time_event(g, "Generate .h");
9257 gen_h_file(g);9237 gen_h_file(g);
9258 }9238 }
9259 }9239 }
92609240
9261 if (g->emit_file_type == EmitFileTypeBinary &&9241 // If we're outputting assembly or llvm IR we skip linking.
9262 (g->link_objects.length > 1 || g->out_type != OutTypeObj))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)))
9263 {9248 {
9264 codegen_link(g);9249 codegen_link(g);
9265 }9250 }
src/codegen.hpp+1-5
...@@ -28,7 +28,6 @@ void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type);...@@ -28,7 +28,6 @@ void codegen_set_emit_file_type(CodeGen *g, EmitFileType emit_file_type);
28void codegen_set_strip(CodeGen *codegen, bool strip);28void codegen_set_strip(CodeGen *codegen, bool strip);
29void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);29void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);
30void codegen_set_out_name(CodeGen *codegen, Buf *out_name);30void codegen_set_out_name(CodeGen *codegen, Buf *out_name);
31void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker);
32void codegen_add_lib_dir(CodeGen *codegen, const char *dir);31void codegen_add_lib_dir(CodeGen *codegen, const char *dir);
33void codegen_add_forbidden_lib(CodeGen *codegen, Buf *lib);32void codegen_add_forbidden_lib(CodeGen *codegen, Buf *lib);
34LinkLib *codegen_add_link_lib(CodeGen *codegen, Buf *lib);33LinkLib *codegen_add_link_lib(CodeGen *codegen, Buf *lib);
...@@ -41,9 +40,6 @@ void codegen_set_linker_script(CodeGen *g, const char *linker_script);...@@ -41,9 +40,6 @@ void codegen_set_linker_script(CodeGen *g, const char *linker_script);
41void codegen_set_test_filter(CodeGen *g, Buf *filter);40void codegen_set_test_filter(CodeGen *g, Buf *filter);
42void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);41void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);
43void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch);42void 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);
47void codegen_add_time_event(CodeGen *g, const char *name);43void codegen_add_time_event(CodeGen *g, const char *name);
48void codegen_print_timing_report(CodeGen *g, FILE *f);44void codegen_print_timing_report(CodeGen *g, FILE *f);
49void codegen_link(CodeGen *g);45void codegen_link(CodeGen *g);
...@@ -54,7 +50,7 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c...@@ -54,7 +50,7 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c
54void codegen_add_assembly(CodeGen *g, Buf *path);50void codegen_add_assembly(CodeGen *g, Buf *path);
55void codegen_add_object(CodeGen *g, Buf *object_path);51void 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
59Buf *codegen_generate_builtin_source(CodeGen *g);55Buf *codegen_generate_builtin_source(CodeGen *g);
6056
src/ir.cpp+121-33
...@@ -16,6 +16,8 @@...@@ -16,6 +16,8 @@
16#include "translate_c.hpp"16#include "translate_c.hpp"
17#include "util.hpp"17#include "util.hpp"
1818
19#include <errno.h>
20
19struct IrExecContext {21struct IrExecContext {
20 ZigList<ConstExprValue *> mem_slot_list;22 ZigList<ConstExprValue *> mem_slot_list;
21};23};
...@@ -18687,7 +18689,15 @@ static IrInstruction *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstruc...@@ -18687,7 +18689,15 @@ static IrInstruction *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstruc
18687 return result;18689 return result;
18688}18690}
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}
18690static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstructionCImport *instruction) {18699static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstructionCImport *instruction) {
18700 Error err;
18691 AstNode *node = instruction->base.source_node;18701 AstNode *node = instruction->base.source_node;
18692 assert(node->type == NodeTypeFnCallExpr);18702 assert(node->type == NodeTypeFnCallExpr);
18693 AstNode *block_node = node->data.fn_call_expr.params.at(0);18703 AstNode *block_node = node->data.fn_call_expr.params.at(0);
...@@ -18706,50 +18716,128 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct...@@ -18706,50 +18716,128 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
18706 Buf *namespace_name = buf_sprintf("%s.cimport:%" ZIG_PRI_usize ":%" ZIG_PRI_usize,18716 Buf *namespace_name = buf_sprintf("%s.cimport:%" ZIG_PRI_usize ":%" ZIG_PRI_usize,
18707 buf_ptr(&cur_scope_pkg->pkg_path), node->line + 1, node->column + 1);18717 buf_ptr(&cur_scope_pkg->pkg_path), node->line + 1, node->column + 1);
1870818718
18709 RootStruct *root_struct = allocate<RootStruct>(1);18719 ZigPackage *cimport_pkg = new_anonymous_package();
18710 root_struct->package = new_anonymous_package();18720 cimport_pkg->package_table.put(buf_create_from_str("builtin"), ira->codegen->compile_var_package);
18711 root_struct->package->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);
18712 root_struct->package->package_table.put(buf_create_from_str("std"), ira->codegen->std_package);18722 buf_init_from_buf(&cimport_pkg->pkg_path, namespace_name);
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);
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;18731 // Set this because we're not adding any files before checking for a hit.
18724 if ((err = parse_h_buf(child_import, &errors, &cimport_scope->buf, ira->codegen, node))) {18732 cache_hash->force_check_manifest = true;
18725 if (err != ErrorCCompileErrors) {18733
18726 ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err)));18734 Buf tmp_c_file_digest = BUF_INIT;
18735 buf_resize(&tmp_c_file_digest, 0);
18736 if ((err = cache_hit(cache_hash, &tmp_c_file_digest))) {
18737 ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to check cache: %s", err_str(err)));
18738 return ira->codegen->invalid_instruction;
18739 }
18740 ira->codegen->caches_to_release.append(cache_hash);
18741
18742 Buf *out_zig_dir = buf_alloc();
18743 Buf *out_zig_path = buf_alloc();
18744 if (buf_len(&tmp_c_file_digest) == 0 || cache_hash->files.length == 0) {
18745 // Cache Miss
18746 Buf *tmp_c_file_dir = buf_sprintf("%s" OS_SEP "o" OS_SEP "%s",
18747 buf_ptr(ira->codegen->cache_dir), buf_ptr(&cache_hash->b64_digest));
18748 Buf *resolve_paths[] = {
18749 tmp_c_file_dir,
18750 buf_create_from_str("cimport.h"),
18751 };
18752 Buf tmp_c_file_path = os_path_resolve(resolve_paths, 2);
18753
18754 if ((err = os_make_path(tmp_c_file_dir))) {
18755 ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to make dir: %s", err_str(err)));
18727 return ira->codegen->invalid_instruction;18756 return ira->codegen->invalid_instruction;
18728 }18757 }
18729 }18758
18759 if ((err = os_write_file(&tmp_c_file_path, &cimport_scope->buf))) {
18760 ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to write .h file: %s", err_str(err)));
18761 return ira->codegen->invalid_instruction;
18762 }
18763 if (ira->codegen->verbose_cimport) {
18764 fprintf(stderr, "@cImport source: %s\n", buf_ptr(&tmp_c_file_path));
18765 }
18766
18767 ZigList<ErrorMsg *> errors = {0};
18768
18769 Buf *tmp_dep_file = buf_sprintf("%s.d", buf_ptr(&tmp_c_file_path));
18770 AstNode *root_node;
18771 if ((err = parse_h_file(&root_node, &errors, buf_ptr(&tmp_c_file_path), ira->codegen, tmp_dep_file))) {
18772 if (err != ErrorCCompileErrors) {
18773 ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err)));
18774 return ira->codegen->invalid_instruction;
18775 }
18776 assert(errors.length > 0);
18777
18778 ErrorMsg *parent_err_msg = ir_add_error_node(ira, node, buf_sprintf("C import failed"));
18779 if (ira->codegen->libc_link_lib == nullptr) {
18780 add_error_note(ira->codegen, parent_err_msg, node,
18781 buf_sprintf("libc headers not available; compilation does not link against libc"));
18782 }
18783 for (size_t i = 0; i < errors.length; i += 1) {
18784 ErrorMsg *err_msg = errors.at(i);
18785 err_msg_add_note(parent_err_msg, err_msg);
18786 }
1873018787
18731 if (errors.length > 0) {18788 return ira->codegen->invalid_instruction;
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"));
18736 }18789 }
18737 for (size_t i = 0; i < errors.length; i += 1) {18790 if (ira->codegen->verbose_cimport) {
18738 ErrorMsg *err_msg = errors.at(i);18791 fprintf(stderr, "@cImport .d file: %s\n", buf_ptr(tmp_dep_file));
18739 err_msg_add_note(parent_err_msg, err_msg);
18740 }18792 }
1874118793
18742 return ira->codegen->invalid_instruction;18794 if ((err = cache_add_dep_file(cache_hash, tmp_dep_file, false))) {
18743 }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) {18803 ir_cimport_cache_paths(ira->codegen->cache_dir, &tmp_c_file_digest, out_zig_dir, out_zig_path);
18746 fprintf(stderr, "\nC imports:\n");18804 if ((err = os_make_path(out_zig_dir))) {
18747 fprintf(stderr, "-----------\n");18805 ir_add_error_node(ira, node, buf_sprintf("C import failed: unable to make output dir: %s", err_str(err)));
18748 ast_render(ira->codegen, stderr, child_import->data.structure.decl_node, 4);18806 return ira->codegen->invalid_instruction;
18749 }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);
18753 return ir_const_type(ira, &instruction->base, child_import);18841 return ir_const_type(ira, &instruction->base, child_import);
18754}18842}
1875518843
src/link.cpp+10-18
...@@ -24,7 +24,7 @@ static CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, Ou...@@ -24,7 +24,7 @@ static CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, Ou
24{24{
25 CodeGen *child_gen = codegen_create(nullptr, root_src_path, parent_gen->zig_target, out_type,25 CodeGen *child_gen = codegen_create(nullptr, root_src_path, parent_gen->zig_target, out_type,
26 parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir, libc, get_stage1_cache_path());26 parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir, libc, get_stage1_cache_path());
27 child_gen->out_h_path = nullptr;27 child_gen->disable_gen_h = true;
28 child_gen->verbose_tokenize = parent_gen->verbose_tokenize;28 child_gen->verbose_tokenize = parent_gen->verbose_tokenize;
29 child_gen->verbose_ast = parent_gen->verbose_ast;29 child_gen->verbose_ast = parent_gen->verbose_ast;
30 child_gen->verbose_link = parent_gen->verbose_link;30 child_gen->verbose_link = parent_gen->verbose_link;
...@@ -675,11 +675,8 @@ static void construct_linker_job_elf(LinkJob *lj) {...@@ -675,11 +675,8 @@ static void construct_linker_job_elf(LinkJob *lj) {
675 } else if (is_dyn_lib) {675 } else if (is_dyn_lib) {
676 lj->args.append("-shared");676 lj->args.append("-shared");
677677
678 if (buf_len(&g->output_file_path) == 0) {678 assert(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 "",679 soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize, buf_ptr(g->root_out_name), g->version_major);
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);
683 }680 }
684681
685 lj->args.append("-o");682 lj->args.append("-o");
...@@ -859,11 +856,6 @@ static void construct_linker_job_wasm(LinkJob *lj) {...@@ -859,11 +856,6 @@ static void construct_linker_job_wasm(LinkJob *lj) {
859 }856 }
860}857}
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
867static void coff_append_machine_arg(CodeGen *g, ZigList<const char *> *list) {859static void coff_append_machine_arg(CodeGen *g, ZigList<const char *> *list) {
868 if (g->zig_target->arch == ZigLLVM_x86) {860 if (g->zig_target->arch == ZigLLVM_x86) {
869 list->append("-MACHINE:X86");861 list->append("-MACHINE:X86");
...@@ -935,6 +927,7 @@ static void add_nt_link_args(LinkJob *lj, bool is_library) {...@@ -935,6 +927,7 @@ static void add_nt_link_args(LinkJob *lj, bool is_library) {
935}927}
936928
937static void construct_linker_job_coff(LinkJob *lj) {929static void construct_linker_job_coff(LinkJob *lj) {
930 Error err;
938 CodeGen *g = lj->codegen;931 CodeGen *g = lj->codegen;
939932
940 lj->args.append("/ERRORLIMIT:0");933 lj->args.append("/ERRORLIMIT:0");
...@@ -1054,11 +1047,13 @@ static void construct_linker_job_coff(LinkJob *lj) {...@@ -1054,11 +1047,13 @@ static void construct_linker_job_coff(LinkJob *lj) {
1054 buf_appendf(def_contents, "\n");1047 buf_appendf(def_contents, "\n");
10551048
1056 Buf *def_path = buf_alloc();1049 Buf *def_path = buf_alloc();
1057 os_path_join(&g->artifact_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path);1050 os_path_join(g->output_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path);
1058 os_write_file(def_path, def_contents);1051 if ((err = os_write_file(def_path, def_contents))) {
1052 zig_panic("error writing def file: %s", err_str(err));
1053 }
10591054
1060 Buf *generated_lib_path = buf_alloc();1055 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
1063 gen_lib_args.resize(0);1058 gen_lib_args.resize(0);
1064 gen_lib_args.append("link");1059 gen_lib_args.append("link");
...@@ -1220,10 +1215,7 @@ static void construct_linker_job_macho(LinkJob *lj) {...@@ -1220,10 +1215,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
1220 //lj->args.append("-install_name");1215 //lj->args.append("-install_name");
1221 //lj->args.append(buf_ptr(dylib_install_name));1216 //lj->args.append(buf_ptr(dylib_install_name));
12221217
1223 if (buf_len(&g->output_file_path) == 0) {1218 assert(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 }
1227 }1219 }
12281220
1229 lj->args.append("-arch");1221 lj->args.append("-arch");
src/main.cpp+45-41
...@@ -48,9 +48,10 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {...@@ -48,9 +48,10 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
48 "Compile Options:\n"48 "Compile Options:\n"
49 " --assembly [source] add assembly file to build\n"49 " --assembly [source] add assembly file to build\n"
50 " --c-source [options] [file] compile C source code\n"50 " --c-source [options] [file] compile C source code\n"
51 " --cache-dir [path] override the cache directory\n"51 " --cache-dir [path] override the local cache directory\n"
52 " --cache [auto|off|on] build in global cache, print out paths to stdout\n"52 " --cache [auto|off|on] build in cache, print output path to stdout\n"
53 " --color [auto|off|on] enable or disable colored error messages\n"53 " --color [auto|off|on] enable or disable colored error messages\n"
54 " --disable-gen-h do not generate a C header file (.h)\n"
54 " --disable-pic disable Position Independent Code for libraries\n"55 " --disable-pic disable Position Independent Code for libraries\n"
55 " --disable-valgrind omit valgrind client requests in debug builds\n"56 " --disable-valgrind omit valgrind client requests in debug builds\n"
56 " --enable-valgrind include valgrind client requests release builds\n"57 " --enable-valgrind include valgrind client requests release builds\n"
...@@ -58,9 +59,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {...@@ -58,9 +59,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
58 " -ftime-report print timing diagnostics\n"59 " -ftime-report print timing diagnostics\n"
59 " --libc [file] Provide a file which specifies libc paths\n"60 " --libc [file] Provide a file which specifies libc paths\n"
60 " --name [name] override output name\n"61 " --name [name] override output name\n"
61 " --output [file] override destination path\n"62 " --output-dir [dir] override output directory (defaults to cwd)\n"
62 " --output-h [file] generate header file\n"
63 " --output-lib [file] override import library path\n"
64 " --pkg-begin [name] [path] make pkg available to import and push current pkg\n"63 " --pkg-begin [name] [path] make pkg available to import and push current pkg\n"
65 " --pkg-end pop current pkg\n"64 " --pkg-end pop current pkg\n"
66 " --main-pkg-path set the directory of the root package\n"65 " --main-pkg-path set the directory of the root package\n"
...@@ -371,8 +370,14 @@ int main(int argc, char **argv) {...@@ -371,8 +370,14 @@ int main(int argc, char **argv) {
371 fprintf(stderr, "Unable to make directory: %s: %s\n", buf_ptr(out_src_dir_path), err_str(err));370 fprintf(stderr, "Unable to make directory: %s: %s\n", buf_ptr(out_src_dir_path), err_str(err));
372 return EXIT_FAILURE;371 return EXIT_FAILURE;
373 }372 }
374 os_write_file(out_build_zig_path, modified_build_zig_contents);373 if ((err = os_write_file(out_build_zig_path, modified_build_zig_contents))) {
375 os_write_file(out_main_zig_path, main_zig_contents);374 fprintf(stderr, "Unable to write file: %s: %s\n", buf_ptr(out_build_zig_path), err_str(err));
375 return EXIT_FAILURE;
376 }
377 if ((err = os_write_file(out_main_zig_path, main_zig_contents))) {
378 fprintf(stderr, "Unable to write file: %s: %s\n", buf_ptr(out_main_zig_path), err_str(err));
379 return EXIT_FAILURE;
380 }
376 fprintf(stderr, "Created %s\n", buf_ptr(out_build_zig_path));381 fprintf(stderr, "Created %s\n", buf_ptr(out_build_zig_path));
377 fprintf(stderr, "Created %s\n", buf_ptr(out_main_zig_path));382 fprintf(stderr, "Created %s\n", buf_ptr(out_main_zig_path));
378 if (init_kind == InitKindExe) {383 if (init_kind == InitKindExe) {
...@@ -390,9 +395,7 @@ int main(int argc, char **argv) {...@@ -390,9 +395,7 @@ int main(int argc, char **argv) {
390 Cmd cmd = CmdNone;395 Cmd cmd = CmdNone;
391 EmitFileType emit_file_type = EmitFileTypeBinary;396 EmitFileType emit_file_type = EmitFileTypeBinary;
392 const char *in_file = nullptr;397 const char *in_file = nullptr;
393 const char *out_file = nullptr;398 Buf *output_dir = nullptr;
394 const char *out_file_h = nullptr;
395 const char *out_file_lib = nullptr;
396 bool strip = false;399 bool strip = false;
397 bool is_static = false;400 bool is_static = false;
398 OutType out_type = OutTypeUnknown;401 OutType out_type = OutTypeUnknown;
...@@ -406,7 +409,7 @@ int main(int argc, char **argv) {...@@ -406,7 +409,7 @@ int main(int argc, char **argv) {
406 bool verbose_cc = false;409 bool verbose_cc = false;
407 ErrColor color = ErrColorAuto;410 ErrColor color = ErrColorAuto;
408 CacheOpt enable_cache = CacheOptAuto;411 CacheOpt enable_cache = CacheOptAuto;
409 const char *dynamic_linker = nullptr;412 Buf *dynamic_linker = nullptr;
410 const char *libc_txt = nullptr;413 const char *libc_txt = nullptr;
411 ZigList<const char *> clang_argv = {0};414 ZigList<const char *> clang_argv = {0};
412 ZigList<const char *> lib_dirs = {0};415 ZigList<const char *> lib_dirs = {0};
...@@ -438,6 +441,7 @@ int main(int argc, char **argv) {...@@ -438,6 +441,7 @@ int main(int argc, char **argv) {
438 bool system_linker_hack = false;441 bool system_linker_hack = false;
439 TargetSubsystem subsystem = TargetSubsystemAuto;442 TargetSubsystem subsystem = TargetSubsystemAuto;
440 bool is_single_threaded = false;443 bool is_single_threaded = false;
444 bool disable_gen_h = false;
441 Buf *override_std_dir = nullptr;445 Buf *override_std_dir = nullptr;
442 Buf *main_pkg_path = nullptr;446 Buf *main_pkg_path = nullptr;
443 ValgrindSupport valgrind_support = ValgrindSupportAuto;447 ValgrindSupport valgrind_support = ValgrindSupportAuto;
...@@ -648,6 +652,8 @@ int main(int argc, char **argv) {...@@ -648,6 +652,8 @@ int main(int argc, char **argv) {
648 system_linker_hack = true;652 system_linker_hack = true;
649 } else if (strcmp(arg, "--single-threaded") == 0) {653 } else if (strcmp(arg, "--single-threaded") == 0) {
650 is_single_threaded = true;654 is_single_threaded = true;
655 } else if (strcmp(arg, "--disable-gen-h") == 0) {
656 disable_gen_h = true;
651 } else if (strcmp(arg, "--test-cmd-bin") == 0) {657 } else if (strcmp(arg, "--test-cmd-bin") == 0) {
652 test_exec_args.append(nullptr);658 test_exec_args.append(nullptr);
653 } else if (arg[1] == 'L' && arg[2] != 0) {659 } else if (arg[1] == 'L' && arg[2] != 0) {
...@@ -677,12 +683,8 @@ int main(int argc, char **argv) {...@@ -677,12 +683,8 @@ int main(int argc, char **argv) {
677 return print_error_usage(arg0);683 return print_error_usage(arg0);
678 } else {684 } else {
679 i += 1;685 i += 1;
680 if (strcmp(arg, "--output") == 0) {686 if (strcmp(arg, "--output-dir") == 0) {
681 out_file = argv[i];687 output_dir = buf_create_from_str(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 } else if (strcmp(arg, "--color") == 0) {688 } else if (strcmp(arg, "--color") == 0) {
687 if (strcmp(argv[i], "auto") == 0) {689 if (strcmp(argv[i], "auto") == 0) {
688 color = ErrColorAuto;690 color = ErrColorAuto;
...@@ -719,7 +721,7 @@ int main(int argc, char **argv) {...@@ -719,7 +721,7 @@ int main(int argc, char **argv) {
719 } else if (strcmp(arg, "--name") == 0) {721 } else if (strcmp(arg, "--name") == 0) {
720 out_name = argv[i];722 out_name = argv[i];
721 } else if (strcmp(arg, "--dynamic-linker") == 0) {723 } else if (strcmp(arg, "--dynamic-linker") == 0) {
722 dynamic_linker = argv[i];724 dynamic_linker = buf_create_from_str(argv[i]);
723 } else if (strcmp(arg, "--libc") == 0) {725 } else if (strcmp(arg, "--libc") == 0) {
724 libc_txt = argv[i];726 libc_txt = argv[i];
725 } else if (strcmp(arg, "-isystem") == 0) {727 } else if (strcmp(arg, "-isystem") == 0) {
...@@ -901,6 +903,21 @@ int main(int argc, char **argv) {...@@ -901,6 +903,21 @@ int main(int argc, char **argv) {
901 }903 }
902 }904 }
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
904 switch (cmd) {921 switch (cmd) {
905 case CmdLibC: {922 case CmdLibC: {
906 if (in_file) {923 if (in_file) {
...@@ -1008,6 +1025,7 @@ int main(int argc, char **argv) {...@@ -1008,6 +1025,7 @@ int main(int argc, char **argv) {
1008 }1025 }
1009 CodeGen *g = codegen_create(main_pkg_path, zig_root_source_file, &target, out_type, build_mode,1026 CodeGen *g = codegen_create(main_pkg_path, zig_root_source_file, &target, out_type, build_mode,
1010 get_zig_lib_dir(), override_std_dir, libc, cache_dir_buf);1027 get_zig_lib_dir(), override_std_dir, libc, cache_dir_buf);
1028 if (llvm_argv.length >= 2) codegen_set_llvm_argv(g, llvm_argv.items + 1, llvm_argv.length - 2);
1011 g->valgrind_support = valgrind_support;1029 g->valgrind_support = valgrind_support;
1012 g->subsystem = subsystem;1030 g->subsystem = subsystem;
10131031
...@@ -1030,16 +1048,9 @@ int main(int argc, char **argv) {...@@ -1030,16 +1048,9 @@ int main(int argc, char **argv) {
10301048
1031 codegen_set_clang_argv(g, clang_argv.items, clang_argv.length);1049 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);
1039 codegen_set_strip(g, strip);1051 codegen_set_strip(g, strip);
1040 g->is_static = is_static;1052 g->is_static = is_static;
1041 if (dynamic_linker != nullptr)1053 g->dynamic_linker_path = dynamic_linker;
1042 codegen_set_dynamic_linker(g, buf_create_from_str(dynamic_linker));
1043 g->verbose_tokenize = verbose_tokenize;1054 g->verbose_tokenize = verbose_tokenize;
1044 g->verbose_ast = verbose_ast;1055 g->verbose_ast = verbose_ast;
1045 g->verbose_link = verbose_link;1056 g->verbose_link = verbose_link;
...@@ -1047,6 +1058,8 @@ int main(int argc, char **argv) {...@@ -1047,6 +1058,8 @@ int main(int argc, char **argv) {
1047 g->verbose_llvm_ir = verbose_llvm_ir;1058 g->verbose_llvm_ir = verbose_llvm_ir;
1048 g->verbose_cimport = verbose_cimport;1059 g->verbose_cimport = verbose_cimport;
1049 g->verbose_cc = verbose_cc;1060 g->verbose_cc = verbose_cc;
1061 g->output_dir = output_dir;
1062 g->disable_gen_h = disable_gen_h;
1050 codegen_set_errmsg_color(g, color);1063 codegen_set_errmsg_color(g, color);
1051 g->system_linker_hack = system_linker_hack;1064 g->system_linker_hack = system_linker_hack;
10521065
...@@ -1090,13 +1103,6 @@ int main(int argc, char **argv) {...@@ -1090,13 +1103,6 @@ int main(int argc, char **argv) {
1090 codegen_set_test_name_prefix(g, buf_create_from_str(test_name_prefix));1103 codegen_set_test_name_prefix(g, buf_create_from_str(test_name_prefix));
1091 }1104 }
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
1100 add_package(g, cur_pkg, g->root_package);1106 add_package(g, cur_pkg, g->root_package);
11011107
1102 if (cmd == CmdBuild || cmd == CmdRun || cmd == CmdTest) {1108 if (cmd == CmdBuild || cmd == CmdRun || cmd == CmdTest) {
...@@ -1135,20 +1141,18 @@ int main(int argc, char **argv) {...@@ -1135,20 +1141,18 @@ int main(int argc, char **argv) {
1135 return term.code;1141 return term.code;
1136 } else if (cmd == CmdBuild) {1142 } else if (cmd == CmdBuild) {
1137 if (g->enable_cache) {1143 if (g->enable_cache) {
1138 printf("%s\n", buf_ptr(&g->output_file_path));1144 if (printf("%s\n", buf_ptr(&g->output_file_path)) < 0)
1139 if (g->out_h_path != nullptr) {1145 return EXIT_FAILURE;
1140 printf("%s\n", buf_ptr(g->out_h_path));
1141 }
1142 }1146 }
1143 return EXIT_SUCCESS;1147 return EXIT_SUCCESS;
1144 } else {1148 } else {
1145 zig_unreachable();1149 zig_unreachable();
1146 }1150 }
1147 } else if (cmd == CmdTranslateC) {1151 } else if (cmd == CmdTranslateC) {
1148 codegen_translate_c(g, in_file_buf);1152 AstNode *root_node = codegen_translate_c(g, in_file_buf);
1149 ast_render(g, stdout, g->root_import->data.structure.decl_node, 4);1153 ast_render(g, stdout, root_node, 4);
1150 if (timing_info)1154 if (timing_info)
1151 codegen_print_timing_report(g, stdout);1155 codegen_print_timing_report(g, stderr);
1152 return EXIT_SUCCESS;1156 return EXIT_SUCCESS;
1153 } else if (cmd == CmdTest) {1157 } else if (cmd == CmdTest) {
1154 codegen_set_emit_file_type(g, emit_file_type);1158 codegen_set_emit_file_type(g, emit_file_type);
...@@ -1156,7 +1160,7 @@ int main(int argc, char **argv) {...@@ -1156,7 +1160,7 @@ int main(int argc, char **argv) {
1156 ZigTarget native;1160 ZigTarget native;
1157 get_native_target(&native);1161 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);
1160 codegen_build_and_link(g);1164 codegen_build_and_link(g);
11611165
1162 if (timing_info) {1166 if (timing_info) {
src/os.cpp+2-86
...@@ -1031,7 +1031,7 @@ Error os_exec_process(const char *exe, ZigList<const char *> &args,...@@ -1031,7 +1031,7 @@ Error os_exec_process(const char *exe, ZigList<const char *> &args,
1031#endif1031#endif
1032}1032}
10331033
1034void os_write_file(Buf *full_path, Buf *contents) {1034Error os_write_file(Buf *full_path, Buf *contents) {
1035 FILE *f = fopen(buf_ptr(full_path), "wb");1035 FILE *f = fopen(buf_ptr(full_path), "wb");
1036 if (!f) {1036 if (!f) {
1037 zig_panic("os_write_file failed for %s", buf_ptr(full_path));1037 zig_panic("os_write_file failed for %s", buf_ptr(full_path));
...@@ -1041,6 +1041,7 @@ void os_write_file(Buf *full_path, Buf *contents) {...@@ -1041,6 +1041,7 @@ void os_write_file(Buf *full_path, Buf *contents) {
1041 zig_panic("write failed: %s", strerror(errno));1041 zig_panic("write failed: %s", strerror(errno));
1042 if (fclose(f))1042 if (fclose(f))
1043 zig_panic("close failed");1043 zig_panic("close failed");
1044 return ErrorNone;
1044}1045}
10451046
1046Error os_copy_file(Buf *src_path, Buf *dest_path) {1047Error os_copy_file(Buf *src_path, Buf *dest_path) {
...@@ -1208,91 +1209,6 @@ bool os_stderr_tty(void) {...@@ -1208,91 +1209,6 @@ bool os_stderr_tty(void) {
1208#endif1209#endif
1209}1210}
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
1296Error os_delete_file(Buf *path) {1212Error os_delete_file(Buf *path) {
1297 if (remove(buf_ptr(path))) {1213 if (remove(buf_ptr(path))) {
1298 return ErrorFileSystem;1214 return ErrorFileSystem;
src/os.hpp+2-4
...@@ -110,8 +110,8 @@ Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents);...@@ -110,8 +110,8 @@ Error ATTRIBUTE_MUST_USE os_file_read_all(OsFile file, Buf *contents);
110Error ATTRIBUTE_MUST_USE os_file_overwrite(OsFile file, Buf *contents);110Error ATTRIBUTE_MUST_USE os_file_overwrite(OsFile file, Buf *contents);
111void os_file_close(OsFile file);111void os_file_close(OsFile file);
112112
113void os_write_file(Buf *full_path, Buf *contents);113Error ATTRIBUTE_MUST_USE os_write_file(Buf *full_path, Buf *contents);
114Error os_copy_file(Buf *src_path, Buf *dest_path);114Error ATTRIBUTE_MUST_USE os_copy_file(Buf *src_path, Buf *dest_path);
115115
116Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents, bool skip_shebang);116Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents, bool skip_shebang);
117Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang);117Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang);
...@@ -121,8 +121,6 @@ Error ATTRIBUTE_MUST_USE os_get_cwd(Buf *out_cwd);...@@ -121,8 +121,6 @@ Error ATTRIBUTE_MUST_USE os_get_cwd(Buf *out_cwd);
121bool os_stderr_tty(void);121bool os_stderr_tty(void);
122void os_stderr_set_color(TermColor color);122void 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);
126Error os_delete_file(Buf *path);124Error os_delete_file(Buf *path);
127125
128Error ATTRIBUTE_MUST_USE os_file_exists(Buf *full_path, bool *result);126Error ATTRIBUTE_MUST_USE os_file_exists(Buf *full_path, bool *result);
src/target.cpp+5-1
...@@ -942,8 +942,12 @@ const char *target_lib_file_ext(const ZigTarget *target, bool is_static,...@@ -942,8 +942,12 @@ const char *target_lib_file_ext(const ZigTarget *target, bool is_static,
942 } else {942 } else {
943 if (is_static) {943 if (is_static) {
944 return ".a";944 return ".a";
945 } else if (target_is_darwin(target)) {
946 return buf_ptr(buf_sprintf(".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib",
947 version_major, version_minor, version_patch));
945 } else {948 } else {
946 return buf_ptr(buf_sprintf(".so.%" ZIG_PRI_usize, version_major));949 return buf_ptr(buf_sprintf(".so.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize,
950 version_major, version_minor, version_patch));
947 }951 }
948 }952 }
949}953}
src/translate_c.cpp+6-42
...@@ -76,7 +76,6 @@ struct TransScopeWhile {...@@ -76,7 +76,6 @@ struct TransScopeWhile {
76};76};
7777
78struct Context {78struct Context {
79 ZigType *import;
80 ZigList<ErrorMsg *> *errors;79 ZigList<ErrorMsg *> *errors;
81 VisibMod visib_mod;80 VisibMod visib_mod;
82 bool want_export;81 bool want_export;
...@@ -86,7 +85,6 @@ struct Context {...@@ -86,7 +85,6 @@ struct Context {
86 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table;85 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table;
87 ZigClangSourceManager *source_manager;86 ZigClangSourceManager *source_manager;
88 ZigList<Alias> aliases;87 ZigList<Alias> aliases;
89 AstNode *source_node;
90 bool warnings_on;88 bool warnings_on;
9189
92 CodeGen *codegen;90 CodeGen *codegen;
...@@ -190,7 +188,6 @@ static Buf *trans_lookup_zig_symbol(Context *c, TransScope *scope, Buf *c_symbol...@@ -190,7 +188,6 @@ static Buf *trans_lookup_zig_symbol(Context *c, TransScope *scope, Buf *c_symbol
190static AstNode * trans_create_node(Context *c, NodeType id) {188static AstNode * trans_create_node(Context *c, NodeType id) {
191 AstNode *node = allocate<AstNode>(1);189 AstNode *node = allocate<AstNode>(1);
192 node->type = id;190 node->type = id;
193 node->owner = c->import;
194 // TODO line/column. mapping to C file??191 // TODO line/column. mapping to C file??
195 return node;192 return node;
196}193}
...@@ -4732,29 +4729,12 @@ static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) {...@@ -4732,29 +4729,12 @@ static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) {
4732 }4729 }
4733}4730}
47344731
4735Error parse_h_buf(ZigType *import, ZigList<ErrorMsg *> *errors, Buf *source,4732Error parse_h_file(AstNode **out_root_node, ZigList<ErrorMsg *> *errors, const char *target_file,
4736 CodeGen *codegen, AstNode *source_node)4733 CodeGen *codegen, Buf *tmp_dep_file)
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)
4753{4734{
4754 Context context = {0};4735 Context context = {0};
4755 Context *c = &context;4736 Context *c = &context;
4756 c->warnings_on = codegen->verbose_cimport;4737 c->warnings_on = codegen->verbose_cimport;
4757 c->import = import;
4758 c->errors = errors;4738 c->errors = errors;
4759 if (buf_ends_with_str(buf_create_from_str(target_file), ".h")) {4739 if (buf_ends_with_str(buf_create_from_str(target_file), ".h")) {
4760 c->visib_mod = VisibModPub;4740 c->visib_mod = VisibModPub;
...@@ -4768,7 +4748,6 @@ Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *tar...@@ -4768,7 +4748,6 @@ Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *tar
4768 c->global_table.init(8);4748 c->global_table.init(8);
4769 c->ptr_params.init(8);4749 c->ptr_params.init(8);
4770 c->codegen = codegen;4750 c->codegen = codegen;
4771 c->source_node = source_node;
4772 c->global_scope = trans_scope_root_create(c);4751 c->global_scope = trans_scope_root_create(c);
47734752
4774 ZigList<const char *> clang_argv = {0};4753 ZigList<const char *> clang_argv = {0};
...@@ -4776,14 +4755,11 @@ Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *tar...@@ -4776,14 +4755,11 @@ Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *tar
4776 clang_argv.append("-x");4755 clang_argv.append("-x");
4777 clang_argv.append("c");4756 clang_argv.append("c");
47784757
4779 Buf *out_dep_path = nullptr;4758 if (tmp_dep_file != 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"));
4783 clang_argv.append("-MD");4759 clang_argv.append("-MD");
4784 clang_argv.append("-MV");4760 clang_argv.append("-MV");
4785 clang_argv.append("-MF");4761 clang_argv.append("-MF");
4786 clang_argv.append(buf_ptr(out_dep_path));4762 clang_argv.append(buf_ptr(tmp_dep_file));
4787 }4763 }
47884764
4789 if (c->codegen->zig_target->is_native) {4765 if (c->codegen->zig_target->is_native) {
...@@ -4847,7 +4823,7 @@ Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *tar...@@ -4847,7 +4823,7 @@ Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *tar
48474823
4848 clang_argv.append(target_file);4824 clang_argv.append(target_file);
48494825
4850 if (codegen->verbose_cimport) {4826 if (codegen->verbose_cc) {
4851 fprintf(stderr, "clang");4827 fprintf(stderr, "clang");
4852 for (size_t i = 0; i < clang_argv.length; i += 1) {4828 for (size_t i = 0; i < clang_argv.length; i += 1) {
4853 fprintf(stderr, " %s", clang_argv.at(i));4829 fprintf(stderr, " %s", clang_argv.at(i));
...@@ -4932,17 +4908,6 @@ Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *tar...@@ -4932,17 +4908,6 @@ Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *tar
4932 return ErrorCCompileErrors;4908 return ErrorCCompileErrors;
4933 }4909 }
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
4946 c->ctx = ZigClangASTUnit_getASTContext(ast_unit);4911 c->ctx = ZigClangASTUnit_getASTContext(ast_unit);
4947 c->source_manager = ZigClangASTUnit_getSourceManager(ast_unit);4912 c->source_manager = ZigClangASTUnit_getSourceManager(ast_unit);
4948 c->root = trans_create_node(c, NodeTypeContainerDecl);4913 c->root = trans_create_node(c, NodeTypeContainerDecl);
...@@ -4955,8 +4920,7 @@ Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *tar...@@ -4955,8 +4920,7 @@ Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *tar
4955 render_macros(c);4920 render_macros(c);
4956 render_aliases(c);4921 render_aliases(c);
49574922
4958 import->data.structure.decl_node = c->root;4923 *out_root_node = c->root;
4959 import->data.structure.decls_scope->base.source_node = c->root;
49604924
4961 return ErrorNone;4925 return ErrorNone;
4962}4926}
src/translate_c.hpp+2-5
...@@ -11,10 +11,7 @@...@@ -11,10 +11,7 @@
1111
12#include "all_types.hpp"12#include "all_types.hpp"
1313
14Error parse_h_file(ZigType *import, ZigList<ErrorMsg *> *errors, const char *target_file,14Error parse_h_file(AstNode **out_root_node, ZigList<ErrorMsg *> *errors, const char *target_file,
15 CodeGen *codegen, AstNode *source_node);15 CodeGen *codegen, Buf *tmp_dep_file);
16
17Error parse_h_buf(ZigType *import, ZigList<ErrorMsg *> *errors, Buf *source,
18 CodeGen *codegen, AstNode *source_node);
1916
20#endif17#endif
std/build.zig+303-185
...@@ -183,9 +183,20 @@ pub const Builder = struct {...@@ -183,9 +183,20 @@ pub const Builder = struct {
183 return obj_step;183 return obj_step;
184 }184 }
185185
186 /// ::argv is copied.186 /// Initializes a RunStep with argv, which must at least have the path to the
187 pub fn addCommand(self: *Builder, cwd: ?[]const u8, env_map: *const BufMap, argv: []const []const u8) *CommandStep {187 /// executable. More command line arguments can be added with `addArg`,
188 return CommandStep.create(self, cwd, env_map, argv);188 /// `addArgs`, and `addArtifactArg`.
189 /// Be careful using this function, as it introduces a system dependency.
190 /// To run an executable built with zig build, see `LibExeObjStep.run`.
191 pub fn addSystemCommand(self: *Builder, argv: []const []const u8) *RunStep {
192 assert(argv.len >= 1);
193 const run_step = RunStep.create(self, self.fmt("run {}", argv[0]));
194 run_step.addArgs(argv);
195 return run_step;
196 }
197
198 fn dupe(self: *Builder, bytes: []const u8) []u8 {
199 return mem.dupe(self.allocator, u8, bytes) catch unreachable;
189 }200 }
190201
191 pub fn addWriteFile(self: *Builder, file_path: []const u8, data: []const u8) *WriteFileStep {202 pub fn addWriteFile(self: *Builder, file_path: []const u8, data: []const u8) *WriteFileStep {
...@@ -702,25 +713,42 @@ pub const Builder = struct {...@@ -702,25 +713,42 @@ pub const Builder = struct {
702 }713 }
703714
704 pub fn exec(self: *Builder, argv: []const []const u8) ![]u8 {715 pub fn exec(self: *Builder, argv: []const []const u8) ![]u8 {
716 assert(argv.len != 0);
717
705 const max_output_size = 100 * 1024;718 const max_output_size = 100 * 1024;
706 const result = try os.ChildProcess.exec(self.allocator, argv, null, null, max_output_size);719 const child = try os.ChildProcess.init(argv, self.allocator);
707 switch (result.term) {720 defer child.deinit();
721
722 child.stdin_behavior = os.ChildProcess.StdIo.Ignore;
723 child.stdout_behavior = os.ChildProcess.StdIo.Pipe;
724 child.stderr_behavior = os.ChildProcess.StdIo.Inherit;
725
726 try child.spawn();
727
728 var stdout = std.Buffer.initNull(self.allocator);
729 defer std.Buffer.deinit(&stdout);
730
731 var stdout_file_in_stream = child.stdout.?.inStream();
732 try stdout_file_in_stream.stream.readAllBuffer(&stdout, max_output_size);
733
734 const term = child.wait() catch |err| std.debug.panic("unable to spawn {}: {}", argv[0], err);
735 switch (term) {
708 os.ChildProcess.Term.Exited => |code| {736 os.ChildProcess.Term.Exited => |code| {
709 if (code != 0) {737 if (code != 0) {
710 warn("The following command exited with error code {}:\n", code);738 warn("The following command exited with error code {}:\n", code);
711 printCmd(null, argv);739 printCmd(null, argv);
712 warn("stderr:{}\n", result.stderr);740 std.debug.panic("exec failed");
713 std.debug.panic("command failed");
714 }741 }
715 return result.stdout;742 return stdout.toOwnedSlice();
716 },743 },
717 else => {744 else => {
718 warn("The following command terminated unexpectedly:\n");745 warn("The following command terminated unexpectedly:\n");
719 printCmd(null, argv);746 printCmd(null, argv);
720 warn("stderr:{}\n", result.stderr);747 std.debug.panic("exec failed");
721 std.debug.panic("command failed");
722 },748 },
723 }749 }
750
751 return stdout.toOwnedSlice();
724 }752 }
725753
726 pub fn addSearchPrefix(self: *Builder, search_prefix: []const u8) void {754 pub fn addSearchPrefix(self: *Builder, search_prefix: []const u8) void {
...@@ -837,26 +865,20 @@ pub const LibExeObjStep = struct {...@@ -837,26 +865,20 @@ pub const LibExeObjStep = struct {
837 builder: *Builder,865 builder: *Builder,
838 name: []const u8,866 name: []const u8,
839 target: Target,867 target: Target,
840 link_libs: BufSet,
841 linker_script: ?[]const u8,868 linker_script: ?[]const u8,
842 out_filename: []const u8,869 out_filename: []const u8,
843 output_path: ?[]const u8,
844 output_lib_path: ?[]const u8,
845 static: bool,870 static: bool,
846 version: Version,871 version: Version,
847 object_files: ArrayList([]const u8),
848 build_mode: builtin.Mode,872 build_mode: builtin.Mode,
849 kind: Kind,873 kind: Kind,
850 major_only_filename: []const u8,874 major_only_filename: []const u8,
851 name_only_filename: []const u8,875 name_only_filename: []const u8,
852 strip: bool,876 strip: bool,
853 full_path_libs: ArrayList([]const u8),
854 need_flat_namespace_hack: bool,
855 include_dirs: ArrayList([]const u8),
856 lib_paths: ArrayList([]const u8),877 lib_paths: ArrayList([]const u8),
857 frameworks: BufSet,878 frameworks: BufSet,
858 verbose_link: bool,879 verbose_link: bool,
859 verbose_cc: bool,880 verbose_cc: bool,
881 disable_gen_h: bool,
860 c_std: Builder.CStd,882 c_std: Builder.CStd,
861 override_std_dir: ?[]const u8,883 override_std_dir: ?[]const u8,
862 main_pkg_path: ?[]const u8,884 main_pkg_path: ?[]const u8,
...@@ -865,17 +887,31 @@ pub const LibExeObjStep = struct {...@@ -865,17 +887,31 @@ pub const LibExeObjStep = struct {
865 filter: ?[]const u8,887 filter: ?[]const u8,
866888
867 root_src: ?[]const u8,889 root_src: ?[]const u8,
868 output_h_path: ?[]const u8,
869 out_h_filename: []const u8,890 out_h_filename: []const u8,
870 out_lib_filename: []const u8,891 out_lib_filename: []const u8,
871 assembly_files: ArrayList([]const u8),
872 packages: ArrayList(Pkg),892 packages: ArrayList(Pkg),
873 build_options_contents: std.Buffer,893 build_options_contents: std.Buffer,
874 system_linker_hack: bool,894 system_linker_hack: bool,
875895
876 c_source_files: ArrayList(*CSourceFile),
877 object_src: []const u8,896 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
879 const Kind = enum {915 const Kind = enum {
880 Exe,916 Exe,
881 Lib,917 Lib,
...@@ -926,25 +962,17 @@ pub const LibExeObjStep = struct {...@@ -926,25 +962,17 @@ pub const LibExeObjStep = struct {
926 .name = name,962 .name = name,
927 .target = Target.Native,963 .target = Target.Native,
928 .linker_script = null,964 .linker_script = null,
929 .link_libs = BufSet.init(builder.allocator),
930 .frameworks = BufSet.init(builder.allocator),965 .frameworks = BufSet.init(builder.allocator),
931 .step = Step.init(name, builder.allocator, make),966 .step = Step.init(name, builder.allocator, make),
932 .output_path = null,
933 .output_lib_path = null,
934 .output_h_path = null,
935 .version = ver,967 .version = ver,
936 .out_filename = undefined,968 .out_filename = undefined,
937 .out_h_filename = builder.fmt("{}.h", name),969 .out_h_filename = builder.fmt("{}.h", name),
938 .out_lib_filename = undefined,970 .out_lib_filename = undefined,
939 .major_only_filename = undefined,971 .major_only_filename = undefined,
940 .name_only_filename = undefined,972 .name_only_filename = undefined,
941 .object_files = ArrayList([]const u8).init(builder.allocator),
942 .assembly_files = ArrayList([]const u8).init(builder.allocator),
943 .packages = ArrayList(Pkg).init(builder.allocator),973 .packages = ArrayList(Pkg).init(builder.allocator),
944 .full_path_libs = ArrayList([]const u8).init(builder.allocator),974 .include_dirs = ArrayList(IncludeDir).init(builder.allocator),
945 .need_flat_namespace_hack = false,975 .link_objects = ArrayList(LinkObject).init(builder.allocator),
946 .c_source_files = ArrayList(*CSourceFile).init(builder.allocator),
947 .include_dirs = ArrayList([]const u8).init(builder.allocator),
948 .lib_paths = ArrayList([]const u8).init(builder.allocator),976 .lib_paths = ArrayList([]const u8).init(builder.allocator),
949 .object_src = undefined,977 .object_src = undefined,
950 .build_options_contents = std.Buffer.initSize(builder.allocator, 0) catch unreachable,978 .build_options_contents = std.Buffer.initSize(builder.allocator, 0) catch unreachable,
...@@ -955,6 +983,8 @@ pub const LibExeObjStep = struct {...@@ -955,6 +983,8 @@ pub const LibExeObjStep = struct {
955 .exec_cmd_args = null,983 .exec_cmd_args = null,
956 .name_prefix = "",984 .name_prefix = "",
957 .filter = null,985 .filter = null,
986 .disable_gen_h = false,
987 .output_dir = null,
958 };988 };
959 self.computeOutFileNames();989 self.computeOutFileNames();
960 return self;990 return self;
...@@ -1022,7 +1052,20 @@ pub const LibExeObjStep = struct {...@@ -1022,7 +1052,20 @@ pub const LibExeObjStep = struct {
1022 self.computeOutFileNames();1052 self.computeOutFileNames();
1023 }1053 }
10241054
1025 // TODO respect this in the C args1055 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
1026 pub fn setLinkerScriptPath(self: *LibExeObjStep, path: []const u8) void {1069 pub fn setLinkerScriptPath(self: *LibExeObjStep, path: []const u8) void {
1027 self.linker_script = path;1070 self.linker_script = path;
1028 }1071 }
...@@ -1032,37 +1075,28 @@ pub const LibExeObjStep = struct {...@@ -1032,37 +1075,28 @@ pub const LibExeObjStep = struct {
1032 self.frameworks.put(framework_name) catch unreachable;1075 self.frameworks.put(framework_name) catch unreachable;
1033 }1076 }
10341077
1035 pub fn linkLibrary(self: *LibExeObjStep, lib: *LibExeObjStep) void {1078 /// Returns whether the library, executable, or object depends on a particular system library.
1036 assert(self.kind != Kind.Obj);1079 pub fn dependsOnSystemLibrary(self: LibExeObjStep, name: []const u8) bool {
1037 assert(lib.kind == Kind.Lib);1080 for (self.link_objects.toSliceConst()) |link_object| {
10381081 switch (link_object) {
1039 self.step.dependOn(&lib.step);1082 LinkObject.SystemLib => |n| if (mem.eql(u8, n, name)) return true,
10401083 else => continue,
1041 if (lib.static or self.target.isWindows()) {1084 }
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;
1049 }1085 }
1086 return false;
1087 }
10501088
1051 // TODO should be some kind of isolated directory that only has this header in it1089 pub fn linkLibrary(self: *LibExeObjStep, lib: *LibExeObjStep) void {
1052 self.include_dirs.append(self.builder.cache_root) catch unreachable;1090 assert(lib.kind == Kind.Lib);
1053 self.need_flat_namespace_hack = true;1091 self.linkLibraryOrObject(lib);
1092 }
10541093
1055 // inherit the object's frameworks1094 pub fn isDynamicLibrary(self: *LibExeObjStep) bool {
1056 if (self.target.isDarwin() and lib.static) {1095 return self.kind == Kind.Lib and !self.static;
1057 var it = lib.frameworks.iterator();
1058 while (it.next()) |entry| {
1059 self.frameworks.put(entry.key) catch unreachable;
1060 }
1061 }
1062 }1096 }
10631097
1064 pub fn linkSystemLibrary(self: *LibExeObjStep, name: []const u8) void {1098 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;
1066 }1100 }
10671101
1068 pub fn setNamePrefix(self: *LibExeObjStep, text: []const u8) void {1102 pub fn setNamePrefix(self: *LibExeObjStep, text: []const u8) void {
...@@ -1077,11 +1111,15 @@ pub const LibExeObjStep = struct {...@@ -1077,11 +1111,15 @@ pub const LibExeObjStep = struct {
10771111
1078 pub fn addCSourceFile(self: *LibExeObjStep, file: []const u8, args: []const []const u8) void {1112 pub fn addCSourceFile(self: *LibExeObjStep, file: []const u8, args: []const []const u8) void {
1079 const c_source_file = self.builder.allocator.create(CSourceFile) catch unreachable;1113 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 }
1080 c_source_file.* = CSourceFile{1118 c_source_file.* = CSourceFile{
1081 .source_path = file,1119 .source_path = self.builder.dupe(file),
1082 .args = args,1120 .args = args_copy,
1083 };1121 };
1084 self.c_source_files.append(c_source_file) catch unreachable;1122 self.link_objects.append(LinkObject{ .CSourceFile = c_source_file }) catch unreachable;
1085 }1123 }
10861124
1087 pub fn setVerboseLink(self: *LibExeObjStep, value: bool) void {1125 pub fn setVerboseLink(self: *LibExeObjStep, value: bool) void {
...@@ -1104,78 +1142,48 @@ pub const LibExeObjStep = struct {...@@ -1104,78 +1142,48 @@ pub const LibExeObjStep = struct {
1104 self.main_pkg_path = dir_path;1142 self.main_pkg_path = dir_path;
1105 }1143 }
11061144
1107 pub fn setOutputPath(self: *LibExeObjStep, file_path: []const u8) void {1145 /// Unless setOutputDir was called, this function must be called only in
1108 self.output_path = file_path;1146 /// the make step, from a step that has declared a dependency on this one.
11091147 /// To run an executable built with zig build, use `run`, or create an install step and invoke it.
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
1116 pub fn getOutputPath(self: *LibExeObjStep) []const u8 {1148 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(
1118 self.builder.allocator,1150 self.builder.allocator,
1119 [][]const u8{ self.builder.cache_root, self.out_filename },1151 [][]const u8{ self.output_dir.?, self.out_filename },
1120 ) catch unreachable;1152 ) catch unreachable;
1121 }1153 }
11221154
1123 pub fn setOutputLibPath(self: *LibExeObjStep, file_path: []const u8) void {1155 /// Unless setOutputDir was called, this function must be called only in
1124 assert(self.kind == Kind.Lib);1156 /// the make step, from a step that has declared a dependency on this one.
1125 if (self.static)
1126 return self.setOutputPath(file_path);
1127
1128 self.output_lib_path = file_path;
1129 }
1130
1131 pub fn getOutputLibPath(self: *LibExeObjStep) []const u8 {1157 pub fn getOutputLibPath(self: *LibExeObjStep) []const u8 {
1132 assert(self.kind == Kind.Lib);1158 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(
1134 self.builder.allocator,1160 self.builder.allocator,
1135 [][]const u8{ self.builder.cache_root, self.out_lib_filename },1161 [][]const u8{ self.output_dir.?, self.out_lib_filename },
1136 ) catch unreachable;1162 ) catch unreachable;
1137 }1163 }
11381164
1139 pub fn setOutputHPath(self: *LibExeObjStep, file_path: []const u8) void {1165 /// Unless setOutputDir was called, this function must be called only in
1140 self.output_h_path = file_path;1166 /// the make step, from a step that has declared a dependency on this one.
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
1148 pub fn getOutputHPath(self: *LibExeObjStep) []const u8 {1167 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(
1150 self.builder.allocator,1171 self.builder.allocator,
1151 [][]const u8{ self.builder.cache_root, self.out_h_filename },1172 [][]const u8{ self.output_dir.?, self.out_h_filename },
1152 ) catch unreachable;1173 ) catch unreachable;
1153 }1174 }
11541175
1155 pub fn addAssemblyFile(self: *LibExeObjStep, path: []const u8) void {1176 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;
1157 }1178 }
11581179
1159 pub fn addObjectFile(self: *LibExeObjStep, path: []const u8) void {1180 pub fn addObjectFile(self: *LibExeObjStep, path: []const u8) void {
1160 assert(self.kind != Kind.Obj);1181 self.link_objects.append(LinkObject{ .StaticPath = self.builder.dupe(path) }) catch unreachable;
1161
1162 self.object_files.append(path) catch unreachable;
1163 }1182 }
11641183
1165 pub fn addObject(self: *LibExeObjStep, obj: *LibExeObjStep) void {1184 pub fn addObject(self: *LibExeObjStep, obj: *LibExeObjStep) void {
1166 assert(obj.kind == Kind.Obj);1185 assert(obj.kind == Kind.Obj);
1167 assert(self.kind != Kind.Obj);1186 self.linkLibraryOrObject(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 }
1179 }1187 }
11801188
1181 pub fn addBuildOption(self: *LibExeObjStep, comptime T: type, name: []const u8, value: T) void {1189 pub fn addBuildOption(self: *LibExeObjStep, comptime T: type, name: []const u8, value: T) void {
...@@ -1184,7 +1192,7 @@ pub const LibExeObjStep = struct {...@@ -1184,7 +1192,7 @@ pub const LibExeObjStep = struct {
1184 }1192 }
11851193
1186 pub fn addIncludeDir(self: *LibExeObjStep, path: []const u8) void {1194 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;
1188 }1196 }
11891197
1190 pub fn addLibPath(self: *LibExeObjStep, path: []const u8) void {1198 pub fn addLibPath(self: *LibExeObjStep, path: []const u8) void {
...@@ -1207,13 +1215,30 @@ pub const LibExeObjStep = struct {...@@ -1207,13 +1215,30 @@ pub const LibExeObjStep = struct {
1207 self.system_linker_hack = true;1215 self.system_linker_hack = true;
1208 }1216 }
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
1210 fn make(step: *Step) !void {1237 fn make(step: *Step) !void {
1211 const self = @fieldParentPtr(LibExeObjStep, "step", step);1238 const self = @fieldParentPtr(LibExeObjStep, "step", step);
1212 const builder = self.builder;1239 const builder = self.builder;
12131240
1214 if (self.root_src == null and self.object_files.len == 0 and1241 if (self.root_src == null and self.link_objects.len == 0) {
1215 self.assembly_files.len == 0 and self.c_source_files.len == 0)
1216 {
1217 warn("{}: linker needs 1 or more objects to link\n", self.step.name);1242 warn("{}: linker needs 1 or more objects to link\n", self.step.name);
1218 return error.NeedAnObject;1243 return error.NeedAnObject;
1219 }1244 }
...@@ -1235,12 +1260,52 @@ pub const LibExeObjStep = struct {...@@ -1235,12 +1260,52 @@ pub const LibExeObjStep = struct {
1235 zig_args.append(builder.pathFromRoot(root_src)) catch unreachable;1260 zig_args.append(builder.pathFromRoot(root_src)) catch unreachable;
1236 }1261 }
12371262
1238 for (self.c_source_files.toSliceConst()) |c_source_file| {1263 for (self.link_objects.toSlice()) |link_object| {
1239 try zig_args.append("--c-source");1264 switch (link_object) {
1240 for (c_source_file.args) |arg| {1265 LinkObject.StaticPath => |static_path| {
1241 try zig_args.append(arg);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 },
1242 }1308 }
1243 try zig_args.append(self.builder.pathFromRoot(c_source_file.source_path));
1244 }1309 }
12451310
1246 if (self.build_options_contents.len() > 0) {1311 if (self.build_options_contents.len() > 0) {
...@@ -1265,16 +1330,6 @@ pub const LibExeObjStep = struct {...@@ -1265,16 +1330,6 @@ pub const LibExeObjStep = struct {
1265 try zig_args.append(self.name_prefix);1330 try zig_args.append(self.name_prefix);
1266 }1331 }
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
1278 if (builder.verbose_tokenize) zig_args.append("--verbose-tokenize") catch unreachable;1333 if (builder.verbose_tokenize) zig_args.append("--verbose-tokenize") catch unreachable;
1279 if (builder.verbose_ast) zig_args.append("--verbose-ast") catch unreachable;1334 if (builder.verbose_ast) zig_args.append("--verbose-ast") catch unreachable;
1280 if (builder.verbose_cimport) zig_args.append("--verbose-cimport") catch unreachable;1335 if (builder.verbose_cimport) zig_args.append("--verbose-cimport") catch unreachable;
...@@ -1294,24 +1349,8 @@ pub const LibExeObjStep = struct {...@@ -1294,24 +1349,8 @@ pub const LibExeObjStep = struct {
1294 builtin.Mode.ReleaseSmall => zig_args.append("--release-small") catch unreachable,1349 builtin.Mode.ReleaseSmall => zig_args.append("--release-small") catch unreachable,
1295 }1350 }
12961351
1297 zig_args.append("--cache-dir") catch unreachable;1352 try zig_args.append("--cache-dir");
1298 zig_args.append(builder.pathFromRoot(builder.cache_root)) catch unreachable;1353 try zig_args.append(builder.pathFromRoot(builder.cache_root));
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 }
13151354
1316 zig_args.append("--name") catch unreachable;1355 zig_args.append("--name") catch unreachable;
1317 zig_args.append(self.name) catch unreachable;1356 zig_args.append(self.name) catch unreachable;
...@@ -1351,15 +1390,6 @@ pub const LibExeObjStep = struct {...@@ -1351,15 +1390,6 @@ pub const LibExeObjStep = struct {
1351 zig_args.append(linker_script) catch unreachable;1390 zig_args.append(linker_script) catch unreachable;
1352 }1391 }
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
1363 if (self.exec_cmd_args) |exec_cmd_args| {1393 if (self.exec_cmd_args) |exec_cmd_args| {
1364 for (exec_cmd_args) |cmd_arg| {1394 for (exec_cmd_args) |cmd_arg| {
1365 if (cmd_arg) |arg| {1395 if (cmd_arg) |arg| {
...@@ -1377,9 +1407,18 @@ pub const LibExeObjStep = struct {...@@ -1377,9 +1407,18 @@ pub const LibExeObjStep = struct {
1377 zig_args.append("--pkg-end") catch unreachable;1407 zig_args.append("--pkg-end") catch unreachable;
1378 }1408 }
13791409
1380 for (self.include_dirs.toSliceConst()) |include_path| {1410 for (self.include_dirs.toSliceConst()) |include_dir| {
1381 zig_args.append("-isystem") catch unreachable;1411 switch (include_dir) {
1382 zig_args.append(self.builder.pathFromRoot(include_path)) catch unreachable;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 }
1383 }1422 }
13841423
1385 for (builder.include_paths.toSliceConst()) |include_path| {1424 for (builder.include_paths.toSliceConst()) |include_path| {
...@@ -1402,17 +1441,6 @@ pub const LibExeObjStep = struct {...@@ -1402,17 +1441,6 @@ pub const LibExeObjStep = struct {
1402 zig_args.append(lib_path) catch unreachable;1441 zig_args.append(lib_path) catch unreachable;
1403 }1442 }
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
1416 if (self.target.isDarwin()) {1444 if (self.target.isDarwin()) {
1417 var it = self.frameworks.iterator();1445 var it = self.frameworks.iterator();
1418 while (it.next()) |entry| {1446 while (it.next()) |entry| {
...@@ -1435,42 +1463,132 @@ pub const LibExeObjStep = struct {...@@ -1435,42 +1463,132 @@ pub const LibExeObjStep = struct {
1435 try zig_args.append(builder.pathFromRoot(dir));1463 try zig_args.append(builder.pathFromRoot(dir));
1436 }1464 }
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
1440 if (self.kind == Kind.Lib and !self.static and self.target.wantSharedLibSymLinks()) {1482 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);
1442 }1484 }
1443 }1485 }
1444};1486};
14451487
1446pub const CommandStep = struct {1488pub const RunStep = struct {
1447 step: Step,1489 step: Step,
1448 builder: *Builder,1490 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
1450 cwd: ?[]const u8,1496 cwd: ?[]const u8,
1451 env_map: *const BufMap,
14521497
1453 /// ::argv is copied.1498 /// Override this field to modify the environment, or use setEnvironmentVariable
1454 pub fn create(builder: *Builder, cwd: ?[]const u8, env_map: *const BufMap, argv: []const []const u8) *CommandStep {1499 env_map: ?*BufMap,
1455 const self = builder.allocator.create(CommandStep) catch unreachable;1500
1456 self.* = CommandStep{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{
1457 .builder = builder,1509 .builder = builder,
1458 .step = Step.init(argv[0], builder.allocator, make),1510 .step = Step.init(name, builder.allocator, make),
1459 .argv = builder.allocator.alloc([]u8, argv.len) catch unreachable,1511 .argv = ArrayList(Arg).init(builder.allocator),
1460 .cwd = cwd,1512 .cwd = null,
1461 .env_map = env_map,1513 .env_map = null,
1462 };1514 };
1463
1464 mem.copy([]const u8, self.argv, argv);
1465 self.step.name = self.argv[0];
1466 return self;1515 return self;
1467 }1516 }
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
1469 fn make(step: *Step) !void {1558 fn make(step: *Step) !void {
1470 const self = @fieldParentPtr(CommandStep, "step", step);1559 const self = @fieldParentPtr(RunStep, "step", step);
14711560
1472 const cwd = if (self.cwd) |cwd| self.builder.pathFromRoot(cwd) else self.builder.build_root;1561 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 }
1474 }1592 }
1475};1593};
14761594
std/event/future.zig+1-1
...@@ -86,7 +86,7 @@ pub fn Future(comptime T: type) type {...@@ -86,7 +86,7 @@ pub fn Future(comptime T: type) type {
8686
87test "std.event.Future" {87test "std.event.Future" {
88 // https://github.com/ziglang/zig/issues/190888 // 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
91 var da = std.heap.DirectAllocator.init();91 var da = std.heap.DirectAllocator.init();
92 defer da.deinit();92 defer da.deinit();
std/os/windows/util.zig+7-1
...@@ -167,7 +167,7 @@ pub fn windowsOpen(...@@ -167,7 +167,7 @@ pub fn windowsOpen(
167pub fn createWindowsEnvBlock(allocator: *mem.Allocator, env_map: *const BufMap) ![]u16 {167pub fn createWindowsEnvBlock(allocator: *mem.Allocator, env_map: *const BufMap) ![]u16 {
168 // count bytes needed168 // count bytes needed
169 const max_chars_needed = x: {169 const max_chars_needed = x: {
170 var max_chars_needed: usize = 1; // 1 for the final null byte170 var max_chars_needed: usize = 4; // 4 for the final 4 null bytes
171 var it = env_map.iterator();171 var it = env_map.iterator();
172 while (it.next()) |pair| {172 while (it.next()) |pair| {
173 // +1 for '='173 // +1 for '='
...@@ -191,6 +191,12 @@ pub fn createWindowsEnvBlock(allocator: *mem.Allocator, env_map: *const BufMap)...@@ -191,6 +191,12 @@ pub fn createWindowsEnvBlock(allocator: *mem.Allocator, env_map: *const BufMap)
191 }191 }
192 result[i] = 0;192 result[i] = 0;
193 i += 1;193 i += 1;
194 result[i] = 0;
195 i += 1;
196 result[i] = 0;
197 i += 1;
198 result[i] = 0;
199 i += 1;
194 return allocator.shrink(u16, result, i);200 return allocator.shrink(u16, result, i);
195}201}
196202
std/special/init-exe/build.zig+2-2
...@@ -5,10 +5,10 @@ pub fn build(b: *Builder) void {...@@ -5,10 +5,10 @@ pub fn build(b: *Builder) void {
5 const exe = b.addExecutable("$", "src/main.zig");5 const exe = b.addExecutable("$", "src/main.zig");
6 exe.setBuildMode(mode);6 exe.setBuildMode(mode);
77
8 const run_cmd = exe.run();
9
8 const run_step = b.step("run", "Run the app");10 const run_step = b.step("run", "Run the app");
9 const run_cmd = b.addCommand(".", b.env_map, [][]const u8{exe.getOutputPath()});
10 run_step.dependOn(&run_cmd.step);11 run_step.dependOn(&run_cmd.step);
11 run_cmd.step.dependOn(&exe.step);
1212
13 b.default_step.dependOn(&exe.step);13 b.default_step.dependOn(&exe.step);
14 b.installArtifact(exe);14 b.installArtifact(exe);
test/cli.zig+3-3
...@@ -116,12 +116,12 @@ fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void {...@@ -116,12 +116,12 @@ fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void {
116 const args = [][]const u8{116 const args = [][]const u8{
117 zig_exe, "build-obj",117 zig_exe, "build-obj",
118 "--cache-dir", dir_path,118 "--cache-dir", dir_path,
119 "--output", example_s_path,119 "--name", "example",
120 "--output-h", "/dev/null",120 "--output-dir", dir_path,
121 "--emit", "asm",121 "--emit", "asm",
122 "-mllvm", "--x86-asm-syntax=intel",122 "-mllvm", "--x86-asm-syntax=intel",
123 "--strip", "--release-fast",123 "--strip", "--release-fast",
124 example_zig_path,124 example_zig_path, "--disable-gen-h",
125 };125 };
126 _ = try exec(dir_path, args);126 _ = 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 {...@@ -9,12 +9,8 @@ pub fn build(b: *Builder) void {
9 const main = b.addExecutable("main", "main.zig");9 const main = b.addExecutable("main", "main.zig");
10 main.setBuildMode(opts);10 main.setBuildMode(opts);
1111
12 const run = b.addCommand(".", b.env_map, [][]const u8{12 const run = main.run();
13 main.getOutputPath(),13 run.addArtifactArg(lib);
14 lib.getOutputPath(),
15 });
16 run.step.dependOn(&lib.step);
17 run.step.dependOn(&main.step);
1814
19 const test_step = b.step("test", "Test the program");15 const test_step = b.step("test", "Test the program");
20 test_step.dependOn(&run.step);16 test_step.dependOn(&run.step);
test/standalone/pkg_import/build.zig+1-2
...@@ -9,8 +9,7 @@ pub fn build(b: *Builder) void {...@@ -9,8 +9,7 @@ pub fn build(b: *Builder) void {
9 exe.setBuildMode(b.standardReleaseOptions());9 exe.setBuildMode(b.standardReleaseOptions());
10 exe.setBuildMode(b.standardReleaseOptions());10 exe.setBuildMode(b.standardReleaseOptions());
1111
12 const run = b.addCommand(".", b.env_map, [][]const u8{exe.getOutputPath()});12 const run = exe.run();
13 run.step.dependOn(&exe.step);
1413
15 const test_step = b.step("test", "Test it");14 const test_step = b.step("test", "Test it");
16 test_step.dependOn(&run.step);15 test_step.dependOn(&run.step);
test/tests.zig+49-33
...@@ -12,6 +12,7 @@ const fmt = std.fmt;...@@ -12,6 +12,7 @@ const fmt = std.fmt;
12const ArrayList = std.ArrayList;12const ArrayList = std.ArrayList;
13const builtin = @import("builtin");13const builtin = @import("builtin");
14const Mode = builtin.Mode;14const Mode = builtin.Mode;
15const LibExeObjStep = build.LibExeObjStep;
1516
16const compare_output = @import("compare_output.zig");17const compare_output = @import("compare_output.zig");
17const build_examples = @import("build_examples.zig");18const build_examples = @import("build_examples.zig");
...@@ -111,12 +112,11 @@ pub fn addCliTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const M...@@ -111,12 +112,11 @@ pub fn addCliTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const M
111 const step = b.step("test-cli", "Test the command line interface");112 const step = b.step("test-cli", "Test the command line interface");
112113
113 const exe = b.addExecutable("test-cli", "test/cli.zig");114 const exe = b.addExecutable("test-cli", "test/cli.zig");
114 const run_cmd = b.addCommand(null, b.env_map, [][]const u8{115 const run_cmd = exe.run();
115 b.pathFromRoot(exe.getOutputPath()),116 run_cmd.addArgs([][]const u8{
116 os.path.realAlloc(b.allocator, b.zig_exe) catch unreachable,117 os.path.realAlloc(b.allocator, b.zig_exe) catch unreachable,
117 b.pathFromRoot(b.cache_root),118 b.pathFromRoot(b.cache_root),
118 });119 });
119 run_cmd.step.dependOn(&exe.step);
120120
121 step.dependOn(&run_cmd.step);121 step.dependOn(&run_cmd.step);
122 return step;122 return step;
...@@ -246,24 +246,31 @@ pub const CompareOutputContext = struct {...@@ -246,24 +246,31 @@ pub const CompareOutputContext = struct {
246 const RunCompareOutputStep = struct {246 const RunCompareOutputStep = struct {
247 step: build.Step,247 step: build.Step,
248 context: *CompareOutputContext,248 context: *CompareOutputContext,
249 exe_path: []const u8,249 exe: *LibExeObjStep,
250 name: []const u8,250 name: []const u8,
251 expected_output: []const u8,251 expected_output: []const u8,
252 test_index: usize,252 test_index: usize,
253 cli_args: []const []const u8,253 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 {
256 const allocator = context.b.allocator;262 const allocator = context.b.allocator;
257 const ptr = allocator.create(RunCompareOutputStep) catch unreachable;263 const ptr = allocator.create(RunCompareOutputStep) catch unreachable;
258 ptr.* = RunCompareOutputStep{264 ptr.* = RunCompareOutputStep{
259 .context = context,265 .context = context,
260 .exe_path = exe_path,266 .exe = exe,
261 .name = name,267 .name = name,
262 .expected_output = expected_output,268 .expected_output = expected_output,
263 .test_index = context.test_index,269 .test_index = context.test_index,
264 .step = build.Step.init("RunCompareOutput", allocator, make),270 .step = build.Step.init("RunCompareOutput", allocator, make),
265 .cli_args = cli_args,271 .cli_args = cli_args,
266 };272 };
273 ptr.step.dependOn(&exe.step);
267 context.test_index += 1;274 context.test_index += 1;
268 return ptr;275 return ptr;
269 }276 }
...@@ -272,7 +279,7 @@ pub const CompareOutputContext = struct {...@@ -272,7 +279,7 @@ pub const CompareOutputContext = struct {
272 const self = @fieldParentPtr(RunCompareOutputStep, "step", step);279 const self = @fieldParentPtr(RunCompareOutputStep, "step", step);
273 const b = self.context.b;280 const b = self.context.b;
274281
275 const full_exe_path = b.pathFromRoot(self.exe_path);282 const full_exe_path = self.exe.getOutputPath();
276 var args = ArrayList([]const u8).init(b.allocator);283 var args = ArrayList([]const u8).init(b.allocator);
277 defer args.deinit();284 defer args.deinit();
278285
...@@ -336,21 +343,21 @@ pub const CompareOutputContext = struct {...@@ -336,21 +343,21 @@ pub const CompareOutputContext = struct {
336 const RuntimeSafetyRunStep = struct {343 const RuntimeSafetyRunStep = struct {
337 step: build.Step,344 step: build.Step,
338 context: *CompareOutputContext,345 context: *CompareOutputContext,
339 exe_path: []const u8,346 exe: *LibExeObjStep,
340 name: []const u8,347 name: []const u8,
341 test_index: usize,348 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 {
344 const allocator = context.b.allocator;351 const allocator = context.b.allocator;
345 const ptr = allocator.create(RuntimeSafetyRunStep) catch unreachable;352 const ptr = allocator.create(RuntimeSafetyRunStep) catch unreachable;
346 ptr.* = RuntimeSafetyRunStep{353 ptr.* = RuntimeSafetyRunStep{
347 .context = context,354 .context = context,
348 .exe_path = exe_path,355 .exe = exe,
349 .name = name,356 .name = name,
350 .test_index = context.test_index,357 .test_index = context.test_index,
351 .step = build.Step.init("RuntimeSafetyRun", allocator, make),358 .step = build.Step.init("RuntimeSafetyRun", allocator, make),
352 };359 };
353360 ptr.step.dependOn(&exe.step);
354 context.test_index += 1;361 context.test_index += 1;
355 return ptr;362 return ptr;
356 }363 }
...@@ -359,11 +366,11 @@ pub const CompareOutputContext = struct {...@@ -359,11 +366,11 @@ pub const CompareOutputContext = struct {
359 const self = @fieldParentPtr(RuntimeSafetyRunStep, "step", step);366 const self = @fieldParentPtr(RuntimeSafetyRunStep, "step", step);
360 const b = self.context.b;367 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
364 warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);371 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;
367 defer child.deinit();374 defer child.deinit();
368375
369 child.env_map = b.env_map;376 child.env_map = b.env_map;
...@@ -463,8 +470,13 @@ pub const CompareOutputContext = struct {...@@ -463,8 +470,13 @@ pub const CompareOutputContext = struct {
463 exe.step.dependOn(&write_src.step);470 exe.step.dependOn(&write_src.step);
464 }471 }
465472
466 const run_and_cmp_output = RunCompareOutputStep.create(self, exe.getOutputPath(), annotated_case_name, case.expected_output, case.cli_args);473 const run_and_cmp_output = RunCompareOutputStep.create(
467 run_and_cmp_output.step.dependOn(&exe.step);474 self,
475 exe,
476 annotated_case_name,
477 case.expected_output,
478 case.cli_args,
479 );
468480
469 self.step.dependOn(&run_and_cmp_output.step);481 self.step.dependOn(&run_and_cmp_output.step);
470 },482 },
...@@ -490,8 +502,13 @@ pub const CompareOutputContext = struct {...@@ -490,8 +502,13 @@ pub const CompareOutputContext = struct {
490 exe.step.dependOn(&write_src.step);502 exe.step.dependOn(&write_src.step);
491 }503 }
492504
493 const run_and_cmp_output = RunCompareOutputStep.create(self, exe.getOutputPath(), annotated_case_name, case.expected_output, case.cli_args);505 const run_and_cmp_output = RunCompareOutputStep.create(
494 run_and_cmp_output.step.dependOn(&exe.step);506 self,
507 exe,
508 annotated_case_name,
509 case.expected_output,
510 case.cli_args,
511 );
495512
496 self.step.dependOn(&run_and_cmp_output.step);513 self.step.dependOn(&run_and_cmp_output.step);
497 }514 }
...@@ -516,8 +533,7 @@ pub const CompareOutputContext = struct {...@@ -516,8 +533,7 @@ pub const CompareOutputContext = struct {
516 exe.step.dependOn(&write_src.step);533 exe.step.dependOn(&write_src.step);
517 }534 }
518535
519 const run_and_cmp_output = RuntimeSafetyRunStep.create(self, exe.getOutputPath(), annotated_case_name);536 const run_and_cmp_output = RuntimeSafetyRunStep.create(self, exe, annotated_case_name);
520 run_and_cmp_output.step.dependOn(&exe.step);
521537
522 self.step.dependOn(&run_and_cmp_output.step);538 self.step.dependOn(&run_and_cmp_output.step);
523 },539 },
...@@ -608,10 +624,6 @@ pub const CompileErrorContext = struct {...@@ -608,10 +624,6 @@ pub const CompileErrorContext = struct {
608 b.allocator,624 b.allocator,
609 [][]const u8{ b.cache_root, self.case.sources.items[0].filename },625 [][]const u8{ b.cache_root, self.case.sources.items[0].filename },
610 ) catch unreachable;626 ) catch unreachable;
611 const obj_path = os.path.join(
612 b.allocator,
613 [][]const u8{ b.cache_root, "test.o" },
614 ) catch unreachable;
615627
616 var zig_args = ArrayList([]const u8).init(b.allocator);628 var zig_args = ArrayList([]const u8).init(b.allocator);
617 zig_args.append(b.zig_exe) catch unreachable;629 zig_args.append(b.zig_exe) catch unreachable;
...@@ -628,8 +640,8 @@ pub const CompileErrorContext = struct {...@@ -628,8 +640,8 @@ pub const CompileErrorContext = struct {
628 zig_args.append("--name") catch unreachable;640 zig_args.append("--name") catch unreachable;
629 zig_args.append("test") catch unreachable;641 zig_args.append("test") catch unreachable;
630642
631 zig_args.append("--output") catch unreachable;643 zig_args.append("--output-dir") catch unreachable;
632 zig_args.append(b.pathFromRoot(obj_path)) catch unreachable;644 zig_args.append(b.pathFromRoot(b.cache_root)) catch unreachable;
633645
634 switch (self.build_mode) {646 switch (self.build_mode) {
635 Mode.Debug => {},647 Mode.Debug => {},
...@@ -851,7 +863,7 @@ pub const BuildExamplesContext = struct {...@@ -851,7 +863,7 @@ pub const BuildExamplesContext = struct {
851 zig_args.append("--verbose") catch unreachable;863 zig_args.append("--verbose") catch unreachable;
852 }864 }
853865
854 const run_cmd = b.addCommand(null, b.env_map, zig_args.toSliceConst());866 const run_cmd = b.addSystemCommand(zig_args.toSliceConst());
855867
856 const log_step = b.addLog("PASS {}\n", annotated_case_name);868 const log_step = b.addLog("PASS {}\n", annotated_case_name);
857 log_step.step.dependOn(&run_cmd.step);869 log_step.step.dependOn(&run_cmd.step);
...@@ -1118,23 +1130,28 @@ pub const GenHContext = struct {...@@ -1118,23 +1130,28 @@ pub const GenHContext = struct {
1118 const GenHCmpOutputStep = struct {1130 const GenHCmpOutputStep = struct {
1119 step: build.Step,1131 step: build.Step,
1120 context: *GenHContext,1132 context: *GenHContext,
1121 h_path: []const u8,1133 obj: *LibExeObjStep,
1122 name: []const u8,1134 name: []const u8,
1123 test_index: usize,1135 test_index: usize,
1124 case: *const TestCase,1136 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 {
1127 const allocator = context.b.allocator;1144 const allocator = context.b.allocator;
1128 const ptr = allocator.create(GenHCmpOutputStep) catch unreachable;1145 const ptr = allocator.create(GenHCmpOutputStep) catch unreachable;
1129 ptr.* = GenHCmpOutputStep{1146 ptr.* = GenHCmpOutputStep{
1130 .step = build.Step.init("ParseCCmpOutput", allocator, make),1147 .step = build.Step.init("ParseCCmpOutput", allocator, make),
1131 .context = context,1148 .context = context,
1132 .h_path = h_path,1149 .obj = obj,
1133 .name = name,1150 .name = name,
1134 .test_index = context.test_index,1151 .test_index = context.test_index,
1135 .case = case,1152 .case = case,
1136 };1153 };
11371154 ptr.step.dependOn(&obj.step);
1138 context.test_index += 1;1155 context.test_index += 1;
1139 return ptr;1156 return ptr;
1140 }1157 }
...@@ -1145,7 +1162,7 @@ pub const GenHContext = struct {...@@ -1145,7 +1162,7 @@ pub const GenHContext = struct {
11451162
1146 warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);1163 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();
1149 const actual_h = try io.readFileAlloc(b.allocator, full_h_path);1166 const actual_h = try io.readFileAlloc(b.allocator, full_h_path);
11501167
1151 for (self.case.expected_lines.toSliceConst()) |expected_line| {1168 for (self.case.expected_lines.toSliceConst()) |expected_line| {
...@@ -1218,8 +1235,7 @@ pub const GenHContext = struct {...@@ -1218,8 +1235,7 @@ pub const GenHContext = struct {
1218 obj.step.dependOn(&write_src.step);1235 obj.step.dependOn(&write_src.step);
1219 }1236 }
12201237
1221 const cmp_h = GenHCmpOutputStep.create(self, obj.getOutputHPath(), annotated_case_name, case);1238 const cmp_h = GenHCmpOutputStep.create(self, obj, annotated_case_name, case);
1222 cmp_h.step.dependOn(&obj.step);
12231239
1224 self.step.dependOn(&cmp_h.step);1240 self.step.dependOn(&cmp_h.step);
1225 }1241 }