authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-30 18:56:24-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-30 18:56:24-04:00
log363d9038c9b52878054505e905e133310b53086e
tree643a613f7502dab37a743049e1b28ee8cfe5b06a
parent38a04a267c11fdedc62102ab8e5989cafa3073ef

zig build: organize build artifacts

closes #328

16 files changed, 357 insertions(+), 146 deletions(-)

.gitignore+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1zig-cache/
1build/2build/
2build-release/3build-release/
3/.cproject4/.cproject
4/.project5/.project
5/.settings/6/.settings/
6/test_artifacts/
build.zig+8-11
...@@ -5,19 +5,16 @@ pub fn build(b: &Builder) {...@@ -5,19 +5,16 @@ pub fn build(b: &Builder) {
5 const test_filter = b.option([]const u8, "test-filter", "Skip tests that do not match filter");5 const test_filter = b.option([]const u8, "test-filter", "Skip tests that do not match filter");
6 const test_step = b.step("test", "Run all the tests");6 const test_step = b.step("test", "Run all the tests");
77
8 const cleanup = b.addRemoveDirTree("test_artifacts");8 test_step.dependOn(tests.addPkgTests(b, test_filter,
9 test_step.dependOn(&cleanup.step);
10
11 cleanup.step.dependOn(tests.addPkgTests(b, test_filter,
12 "test/behavior.zig", "behavior", "Run the behavior tests"));9 "test/behavior.zig", "behavior", "Run the behavior tests"));
1310
14 cleanup.step.dependOn(tests.addPkgTests(b, test_filter,11 test_step.dependOn(tests.addPkgTests(b, test_filter,
15 "std/index.zig", "std", "Run the standard library tests"));12 "std/index.zig", "std", "Run the standard library tests"));
1613
17 cleanup.step.dependOn(tests.addCompareOutputTests(b, test_filter));14 test_step.dependOn(tests.addCompareOutputTests(b, test_filter));
18 cleanup.step.dependOn(tests.addBuildExampleTests(b, test_filter));15 test_step.dependOn(tests.addBuildExampleTests(b, test_filter));
19 cleanup.step.dependOn(tests.addCompileErrorTests(b, test_filter));16 test_step.dependOn(tests.addCompileErrorTests(b, test_filter));
20 cleanup.step.dependOn(tests.addAssembleAndLinkTests(b, test_filter));17 test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter));
21 cleanup.step.dependOn(tests.addDebugSafetyTests(b, test_filter));18 test_step.dependOn(tests.addDebugSafetyTests(b, test_filter));
22 cleanup.step.dependOn(tests.addParseHTests(b, test_filter));19 test_step.dependOn(tests.addParseHTests(b, test_filter));
23}20}
example/mix_o_files/build.zig+1-1
...@@ -12,7 +12,7 @@ pub fn build(b: &Builder) {...@@ -12,7 +12,7 @@ pub fn build(b: &Builder) {
1212
13 b.default_step.dependOn(&exe.step);13 b.default_step.dependOn(&exe.step);
1414
15 const run_cmd = b.addCommand(b.out_dir, b.env_map, "./test", [][]const u8{});15 const run_cmd = b.addCommand(b.cache_root, b.env_map, "./test", [][]const u8{});
16 run_cmd.step.dependOn(&exe.step);16 run_cmd.step.dependOn(&exe.step);
1717
18 const test_step = b.step("test", "Test the program");18 const test_step = b.step("test", "Test the program");
example/shared_library/build.zig+1-1
...@@ -12,7 +12,7 @@ pub fn build(b: &Builder) {...@@ -12,7 +12,7 @@ pub fn build(b: &Builder) {
1212
13 b.default_step.dependOn(&exe.step);13 b.default_step.dependOn(&exe.step);
1414
15 const run_cmd = b.addCommand(b.out_dir, b.env_map, "./test", [][]const u8{});15 const run_cmd = b.addCommand(b.cache_root, b.env_map, "./test", [][]const u8{});
16 run_cmd.step.dependOn(&exe.step);16 run_cmd.step.dependOn(&exe.step);
1717
18 const test_step = b.step("test", "Test the program");18 const test_step = b.step("test", "Test the program");
src/all_types.hpp+1
...@@ -1488,6 +1488,7 @@ struct CodeGen {...@@ -1488,6 +1488,7 @@ struct CodeGen {
1488 ZigList<TimeEvent> timing_events;1488 ZigList<TimeEvent> timing_events;
14891489
1490 Buf *cache_dir;1490 Buf *cache_dir;
1491 Buf *out_h_path;
1491};1492};
14921493
1493enum VarLinkage {1494enum VarLinkage {
src/codegen.cpp+29-19
...@@ -55,11 +55,12 @@ PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_pa...@@ -55,11 +55,12 @@ PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_pa
55 return entry;55 return entry;
56}56}
5757
58CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target) {58CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type) {
59 CodeGen *g = allocate<CodeGen>(1);59 CodeGen *g = allocate<CodeGen>(1);
6060
61 codegen_add_time_event(g, "Initialize");61 codegen_add_time_event(g, "Initialize");
6262
63 g->out_type = out_type;
63 g->import_table.init(32);64 g->import_table.init(32);
64 g->builtin_fn_table.init(32);65 g->builtin_fn_table.init(32);
65 g->primitive_type_table.init(32);66 g->primitive_type_table.init(32);
...@@ -74,7 +75,7 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target) {...@@ -74,7 +75,7 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target) {
74 g->external_prototypes.init(8);75 g->external_prototypes.init(8);
75 g->is_release_build = false;76 g->is_release_build = false;
76 g->is_test_build = false;77 g->is_test_build = false;
77 g->want_h_file = true;78 g->want_h_file = (out_type == OutTypeObj || out_type == OutTypeLib);
7879
79 buf_resize(&g->global_asm, 0);80 buf_resize(&g->global_asm, 0);
8081
...@@ -145,6 +146,10 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target) {...@@ -145,6 +146,10 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target) {
145 return g;146 return g;
146}147}
147148
149void codegen_set_output_h_path(CodeGen *g, Buf *h_path) {
150 g->out_h_path = h_path;
151}
152
148void codegen_set_clang_argv(CodeGen *g, const char **args, size_t len) {153void codegen_set_clang_argv(CodeGen *g, const char **args, size_t len) {
149 g->clang_argv = args;154 g->clang_argv = args;
150 g->clang_argv_len = len;155 g->clang_argv_len = len;
...@@ -196,10 +201,6 @@ void codegen_set_strip(CodeGen *g, bool strip) {...@@ -196,10 +201,6 @@ void codegen_set_strip(CodeGen *g, bool strip) {
196 g->strip_debug_symbols = strip;201 g->strip_debug_symbols = strip;
197}202}
198203
199void codegen_set_out_type(CodeGen *g, OutType out_type) {
200 g->out_type = out_type;
201}
202
203void codegen_set_out_name(CodeGen *g, Buf *out_name) {204void codegen_set_out_name(CodeGen *g, Buf *out_name) {
204 g->root_out_name = out_name;205 g->root_out_name = out_name;
205}206}
...@@ -4808,15 +4809,6 @@ static void gen_global_asm(CodeGen *g) {...@@ -4808,15 +4809,6 @@ static void gen_global_asm(CodeGen *g) {
4808 }4809 }
4809}4810}
48104811
4811void codegen_build(CodeGen *g) {
4812 assert(g->out_type != OutTypeUnknown);
4813 init(g);
4814
4815 gen_global_asm(g);
4816 gen_root_source(g);
4817 do_code_gen(g);
4818}
4819
4820void codegen_add_object(CodeGen *g, Buf *object_path) {4812void codegen_add_object(CodeGen *g, Buf *object_path) {
4821 g->link_objects.append(object_path);4813 g->link_objects.append(object_path);
4822}4814}
...@@ -4946,13 +4938,21 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) {...@@ -4946,13 +4938,21 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) {
4946 }4938 }
4947}4939}
49484940
4949void codegen_generate_h_file(CodeGen *g) {4941static void gen_h_file(CodeGen *g) {
4942 if (!g->want_h_file)
4943 return;
4944
4945 codegen_add_time_event(g, "Generate .h");
4946
4950 assert(!g->is_test_build);4947 assert(!g->is_test_build);
49514948
4952 Buf *h_file_out_path = buf_sprintf("%s.h", buf_ptr(g->root_out_name));4949 if (!g->out_h_path) {
4953 FILE *out_h = fopen(buf_ptr(h_file_out_path), "wb");4950 g->out_h_path = buf_sprintf("%s.h", buf_ptr(g->root_out_name));
4951 }
4952
4953 FILE *out_h = fopen(buf_ptr(g->out_h_path), "wb");
4954 if (!out_h)4954 if (!out_h)
4955 zig_panic("unable to open %s: %s", buf_ptr(h_file_out_path), strerror(errno));4955 zig_panic("unable to open %s: %s", buf_ptr(g->out_h_path), strerror(errno));
49564956
4957 Buf *export_macro = buf_sprintf("%s_EXPORT", buf_ptr(g->root_out_name));4957 Buf *export_macro = buf_sprintf("%s_EXPORT", buf_ptr(g->root_out_name));
4958 buf_upcase(export_macro);4958 buf_upcase(export_macro);
...@@ -5056,3 +5056,13 @@ void codegen_print_timing_report(CodeGen *g, FILE *f) {...@@ -5056,3 +5056,13 @@ void codegen_print_timing_report(CodeGen *g, FILE *f) {
5056void codegen_add_time_event(CodeGen *g, const char *name) {5056void codegen_add_time_event(CodeGen *g, const char *name) {
5057 g->timing_events.append({os_get_time(), name});5057 g->timing_events.append({os_get_time(), name});
5058}5058}
5059
5060void codegen_build(CodeGen *g) {
5061 assert(g->out_type != OutTypeUnknown);
5062 init(g);
5063
5064 gen_global_asm(g);
5065 gen_root_source(g);
5066 do_code_gen(g);
5067 gen_h_file(g);
5068}
src/codegen.hpp+2-3
...@@ -14,7 +14,7 @@...@@ -14,7 +14,7 @@
1414
15#include <stdio.h>15#include <stdio.h>
1616
17CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target);17CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type);
1818
19void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);19void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
20void codegen_set_is_release(CodeGen *codegen, bool is_release);20void codegen_set_is_release(CodeGen *codegen, bool is_release);
...@@ -25,7 +25,6 @@ void codegen_set_is_static(CodeGen *codegen, bool is_static);...@@ -25,7 +25,6 @@ void codegen_set_is_static(CodeGen *codegen, bool is_static);
25void codegen_set_strip(CodeGen *codegen, bool strip);25void codegen_set_strip(CodeGen *codegen, bool strip);
26void codegen_set_verbose(CodeGen *codegen, bool verbose);26void codegen_set_verbose(CodeGen *codegen, bool verbose);
27void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);27void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);
28void codegen_set_out_type(CodeGen *codegen, OutType out_type);
29void codegen_set_out_name(CodeGen *codegen, Buf *out_name);28void codegen_set_out_name(CodeGen *codegen, Buf *out_name);
30void codegen_set_libc_lib_dir(CodeGen *codegen, Buf *libc_lib_dir);29void codegen_set_libc_lib_dir(CodeGen *codegen, Buf *libc_lib_dir);
31void codegen_set_libc_static_lib_dir(CodeGen *g, Buf *libc_static_lib_dir);30void codegen_set_libc_static_lib_dir(CodeGen *g, Buf *libc_static_lib_dir);
...@@ -48,6 +47,7 @@ void codegen_set_test_filter(CodeGen *g, Buf *filter);...@@ -48,6 +47,7 @@ void codegen_set_test_filter(CodeGen *g, Buf *filter);
48void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);47void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);
49void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch);48void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch);
50void codegen_set_cache_dir(CodeGen *g, Buf *cache_dir);49void codegen_set_cache_dir(CodeGen *g, Buf *cache_dir);
50void codegen_set_output_h_path(CodeGen *g, Buf *h_path);
51void codegen_add_time_event(CodeGen *g, const char *name);51void codegen_add_time_event(CodeGen *g, const char *name);
52void codegen_print_timing_report(CodeGen *g, FILE *f);52void codegen_print_timing_report(CodeGen *g, FILE *f);
53void codegen_build(CodeGen *g);53void codegen_build(CodeGen *g);
...@@ -59,6 +59,5 @@ void codegen_add_object(CodeGen *g, Buf *object_path);...@@ -59,6 +59,5 @@ void codegen_add_object(CodeGen *g, Buf *object_path);
59void codegen_parseh(CodeGen *g, Buf *path);59void codegen_parseh(CodeGen *g, Buf *path);
60void codegen_render_ast(CodeGen *g, FILE *f, int indent_size);60void codegen_render_ast(CodeGen *g, FILE *f, int indent_size);
6161
62void codegen_generate_h_file(CodeGen *g);
6362
64#endif63#endif
src/link.cpp+5-15
...@@ -37,7 +37,7 @@ static Buf *build_o(CodeGen *parent_gen, const char *oname) {...@@ -37,7 +37,7 @@ static Buf *build_o(CodeGen *parent_gen, const char *oname) {
37 os_path_join(parent_gen->zig_std_special_dir, source_basename, full_path);37 os_path_join(parent_gen->zig_std_special_dir, source_basename, full_path);
3838
39 ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target;39 ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target;
40 CodeGen *child_gen = codegen_create(full_path, child_target);40 CodeGen *child_gen = codegen_create(full_path, child_target, OutTypeObj);
41 child_gen->link_libc = parent_gen->link_libc;41 child_gen->link_libc = parent_gen->link_libc;
4242
43 child_gen->link_libs.resize(parent_gen->link_libs.length);43 child_gen->link_libs.resize(parent_gen->link_libs.length);
...@@ -55,7 +55,6 @@ static Buf *build_o(CodeGen *parent_gen, const char *oname) {...@@ -55,7 +55,6 @@ static Buf *build_o(CodeGen *parent_gen, const char *oname) {
55 codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);55 codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);
56 codegen_set_is_static(child_gen, parent_gen->is_static);56 codegen_set_is_static(child_gen, parent_gen->is_static);
5757
58 codegen_set_out_type(child_gen, OutTypeObj);
59 codegen_set_out_name(child_gen, buf_create_from_str(oname));58 codegen_set_out_name(child_gen, buf_create_from_str(oname));
6059
61 codegen_set_verbose(child_gen, parent_gen->verbose);60 codegen_set_verbose(child_gen, parent_gen->verbose);
...@@ -186,9 +185,10 @@ static void construct_linker_job_elf(LinkJob *lj) {...@@ -186,9 +185,10 @@ static void construct_linker_job_elf(LinkJob *lj) {
186 } else if (shared) {185 } else if (shared) {
187 lj->args.append("-shared");186 lj->args.append("-shared");
188187
189 buf_resize(&lj->out_file, 0);188 if (buf_len(&lj->out_file) == 0) {
190 buf_appendf(&lj->out_file, "lib%s.so.%zu.%zu.%zu",189 buf_appendf(&lj->out_file, "lib%s.so.%zu.%zu.%zu",
191 buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch);190 buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch);
191 }
192 soname = buf_sprintf("lib%s.so.%zu", buf_ptr(g->root_out_name), g->version_major);192 soname = buf_sprintf("lib%s.so.%zu", buf_ptr(g->root_out_name), g->version_major);
193 }193 }
194194
...@@ -752,9 +752,6 @@ void codegen_link(CodeGen *g, const char *out_file) {...@@ -752,9 +752,6 @@ void codegen_link(CodeGen *g, const char *out_file) {
752 }752 }
753753
754 if (g->out_type == OutTypeObj) {754 if (g->out_type == OutTypeObj) {
755 if (g->want_h_file) {
756 codegen_generate_h_file(g);
757 }
758 if (override_out_file) {755 if (override_out_file) {
759 assert(g->link_objects.length == 1);756 assert(g->link_objects.length == 1);
760 Buf *o_file_path = g->link_objects.at(0);757 Buf *o_file_path = g->link_objects.at(0);
...@@ -798,13 +795,6 @@ void codegen_link(CodeGen *g, const char *out_file) {...@@ -798,13 +795,6 @@ void codegen_link(CodeGen *g, const char *out_file) {
798 fprintf(stderr, "%s\n", buf_ptr(&diag));795 fprintf(stderr, "%s\n", buf_ptr(&diag));
799 exit(1);796 exit(1);
800 }797 }
801 codegen_add_time_event(g, "Generate .h");
802
803 if (g->out_type == OutTypeLib ||
804 g->out_type == OutTypeObj)
805 {
806 codegen_generate_h_file(g);
807 }
808798
809 codegen_add_time_event(g, "Done");799 codegen_add_time_event(g, "Done");
810800
src/main.cpp+22-11
...@@ -35,6 +35,7 @@ static int usage(const char *arg0) {...@@ -35,6 +35,7 @@ static int usage(const char *arg0) {
35 " --libc-include-dir [path] directory where libc stdlib.h resides\n"35 " --libc-include-dir [path] directory where libc stdlib.h resides\n"
36 " --name [name] override output name\n"36 " --name [name] override output name\n"
37 " --output [file] override destination path\n"37 " --output [file] override destination path\n"
38 " --output-h [file] override generated header file path\n"
38 " --release build with optimizations on and debug protection off\n"39 " --release build with optimizations on and debug protection off\n"
39 " --static output will be statically linked\n"40 " --static output will be statically linked\n"
40 " --strip exclude debug symbols\n"41 " --strip exclude debug symbols\n"
...@@ -118,6 +119,8 @@ enum Cmd {...@@ -118,6 +119,8 @@ enum Cmd {
118 CmdTargets,119 CmdTargets,
119};120};
120121
122static const char *default_zig_cache_name = "zig-cache";
123
121int main(int argc, char **argv) {124int main(int argc, char **argv) {
122 os_init();125 os_init();
123126
...@@ -125,6 +128,7 @@ int main(int argc, char **argv) {...@@ -125,6 +128,7 @@ int main(int argc, char **argv) {
125 Cmd cmd = CmdInvalid;128 Cmd cmd = CmdInvalid;
126 const char *in_file = nullptr;129 const char *in_file = nullptr;
127 const char *out_file = nullptr;130 const char *out_file = nullptr;
131 const char *out_file_h = nullptr;
128 bool is_release_build = false;132 bool is_release_build = false;
129 bool strip = false;133 bool strip = false;
130 bool is_static = false;134 bool is_static = false;
...@@ -163,7 +167,7 @@ int main(int argc, char **argv) {...@@ -163,7 +167,7 @@ int main(int argc, char **argv) {
163 size_t ver_minor = 0;167 size_t ver_minor = 0;
164 size_t ver_patch = 0;168 size_t ver_patch = 0;
165 bool timing_info = false;169 bool timing_info = false;
166 const char *cache_dir = "zig-cache";170 const char *cache_dir = nullptr;
167171
168 if (argc >= 2 && strcmp(argv[1], "build") == 0) {172 if (argc >= 2 && strcmp(argv[1], "build") == 0) {
169 const char *zig_exe_path = arg0;173 const char *zig_exe_path = arg0;
...@@ -200,9 +204,8 @@ int main(int argc, char **argv) {...@@ -200,9 +204,8 @@ int main(int argc, char **argv) {
200 }204 }
201 }205 }
202206
203 CodeGen *g = codegen_create(build_runner_path, nullptr);207 CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe);
204 codegen_set_out_name(g, buf_create_from_str("build"));208 codegen_set_out_name(g, buf_create_from_str("build"));
205 codegen_set_out_type(g, OutTypeExe);
206 codegen_set_verbose(g, verbose);209 codegen_set_verbose(g, verbose);
207210
208 Buf build_file_abs = BUF_INIT;211 Buf build_file_abs = BUF_INIT;
...@@ -212,7 +215,12 @@ int main(int argc, char **argv) {...@@ -212,7 +215,12 @@ int main(int argc, char **argv) {
212 os_path_split(&build_file_abs, &build_file_dirname, &build_file_basename);215 os_path_split(&build_file_abs, &build_file_dirname, &build_file_basename);
213216
214 Buf *full_cache_dir = buf_alloc();217 Buf *full_cache_dir = buf_alloc();
215 os_path_resolve(buf_create_from_str("."), buf_create_from_str(cache_dir), full_cache_dir);218 if (cache_dir == nullptr) {
219 os_path_join(&build_file_dirname, buf_create_from_str(default_zig_cache_name), full_cache_dir);
220 } else {
221 os_path_resolve(buf_create_from_str("."), buf_create_from_str(cache_dir), full_cache_dir);
222 }
223
216 Buf *path_to_build_exe = buf_alloc();224 Buf *path_to_build_exe = buf_alloc();
217 os_path_join(full_cache_dir, buf_create_from_str("build"), path_to_build_exe);225 os_path_join(full_cache_dir, buf_create_from_str("build"), path_to_build_exe);
218 codegen_set_cache_dir(g, full_cache_dir);226 codegen_set_cache_dir(g, full_cache_dir);
...@@ -309,6 +317,8 @@ int main(int argc, char **argv) {...@@ -309,6 +317,8 @@ int main(int argc, char **argv) {
309 return usage(arg0);317 return usage(arg0);
310 } else if (strcmp(arg, "--output") == 0) {318 } else if (strcmp(arg, "--output") == 0) {
311 out_file = argv[i];319 out_file = argv[i];
320 } else if (strcmp(arg, "--output-h") == 0) {
321 out_file_h = argv[i];
312 } else if (strcmp(arg, "--color") == 0) {322 } else if (strcmp(arg, "--color") == 0) {
313 if (strcmp(argv[i], "auto") == 0) {323 if (strcmp(argv[i], "auto") == 0) {
314 color = ErrColorAuto;324 color = ErrColorAuto;
...@@ -396,6 +406,7 @@ int main(int argc, char **argv) {...@@ -396,6 +406,7 @@ int main(int argc, char **argv) {
396 cmd = CmdParseH;406 cmd = CmdParseH;
397 } else if (strcmp(arg, "test") == 0) {407 } else if (strcmp(arg, "test") == 0) {
398 cmd = CmdTest;408 cmd = CmdTest;
409 out_type = OutTypeExe;
399 } else if (strcmp(arg, "targets") == 0) {410 } else if (strcmp(arg, "targets") == 0) {
400 cmd = CmdTargets;411 cmd = CmdTargets;
401 } else {412 } else {
...@@ -495,9 +506,11 @@ int main(int argc, char **argv) {...@@ -495,9 +506,11 @@ int main(int argc, char **argv) {
495 Buf *zig_root_source_file = (cmd == CmdParseH) ? nullptr : in_file_buf;506 Buf *zig_root_source_file = (cmd == CmdParseH) ? nullptr : in_file_buf;
496507
497 Buf *full_cache_dir = buf_alloc();508 Buf *full_cache_dir = buf_alloc();
498 os_path_resolve(buf_create_from_str("."), buf_create_from_str(cache_dir), full_cache_dir);509 os_path_resolve(buf_create_from_str("."),
510 buf_create_from_str((cache_dir == nullptr) ? default_zig_cache_name : cache_dir),
511 full_cache_dir);
499512
500 CodeGen *g = codegen_create(zig_root_source_file, target);513 CodeGen *g = codegen_create(zig_root_source_file, target, out_type);
501 codegen_set_out_name(g, buf_out_name);514 codegen_set_out_name(g, buf_out_name);
502 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);515 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
503 codegen_set_is_release(g, is_release_build);516 codegen_set_is_release(g, is_release_build);
...@@ -510,11 +523,6 @@ int main(int argc, char **argv) {...@@ -510,11 +523,6 @@ int main(int argc, char **argv) {
510 codegen_set_clang_argv(g, clang_argv.items, clang_argv.length);523 codegen_set_clang_argv(g, clang_argv.items, clang_argv.length);
511 codegen_set_strip(g, strip);524 codegen_set_strip(g, strip);
512 codegen_set_is_static(g, is_static);525 codegen_set_is_static(g, is_static);
513 if (out_type != OutTypeUnknown) {
514 codegen_set_out_type(g, out_type);
515 } else if (cmd == CmdTest) {
516 codegen_set_out_type(g, OutTypeExe);
517 }
518 if (libc_lib_dir)526 if (libc_lib_dir)
519 codegen_set_libc_lib_dir(g, buf_create_from_str(libc_lib_dir));527 codegen_set_libc_lib_dir(g, buf_create_from_str(libc_lib_dir));
520 if (libc_static_lib_dir)528 if (libc_static_lib_dir)
...@@ -568,6 +576,9 @@ int main(int argc, char **argv) {...@@ -568,6 +576,9 @@ int main(int argc, char **argv) {
568 codegen_set_test_name_prefix(g, buf_create_from_str(test_name_prefix));576 codegen_set_test_name_prefix(g, buf_create_from_str(test_name_prefix));
569 }577 }
570578
579 if (out_file_h)
580 codegen_set_output_h_path(g, buf_create_from_str(out_file_h));
581
571 if (cmd == CmdBuild) {582 if (cmd == CmdBuild) {
572 for (size_t i = 0; i < objects.length; i += 1) {583 for (size_t i = 0; i < objects.length; i += 1) {
573 codegen_add_object(g, buf_create_from_str(objects.at(i)));584 codegen_add_object(g, buf_create_from_str(objects.at(i)));
std/build.zig+138-62
...@@ -37,7 +37,6 @@ pub const Builder = struct {...@@ -37,7 +37,6 @@ pub const Builder = struct {
37 top_level_steps: List(&TopLevelStep),37 top_level_steps: List(&TopLevelStep),
38 prefix: []const u8,38 prefix: []const u8,
39 lib_dir: []const u8,39 lib_dir: []const u8,
40 out_dir: []u8, // TODO get rid of this
41 installed_files: List([]const u8),40 installed_files: List([]const u8),
42 build_root: []const u8,41 build_root: []const u8,
43 cache_root: []const u8,42 cache_root: []const u8,
...@@ -97,7 +96,6 @@ pub const Builder = struct {...@@ -97,7 +96,6 @@ pub const Builder = struct {
97 .env_map = %%os.getEnvMap(allocator),96 .env_map = %%os.getEnvMap(allocator),
98 .prefix = undefined,97 .prefix = undefined,
99 .lib_dir = undefined,98 .lib_dir = undefined,
100 .out_dir = %%os.getCwd(allocator),
101 .installed_files = List([]const u8).init(allocator),99 .installed_files = List([]const u8).init(allocator),
102 .uninstall_tls = TopLevelStep {100 .uninstall_tls = TopLevelStep {
103 .step = Step.init("uninstall", allocator, makeUninstall),101 .step = Step.init("uninstall", allocator, makeUninstall),
...@@ -111,7 +109,6 @@ pub const Builder = struct {...@@ -111,7 +109,6 @@ pub const Builder = struct {
111 }109 }
112110
113 pub fn deinit(self: &Builder) {111 pub fn deinit(self: &Builder) {
114 self.allocator.free(self.out_dir);
115 self.lib_paths.deinit();112 self.lib_paths.deinit();
116 self.include_paths.deinit();113 self.include_paths.deinit();
117 self.rpaths.deinit();114 self.rpaths.deinit();
...@@ -172,12 +169,10 @@ pub const Builder = struct {...@@ -172,12 +169,10 @@ pub const Builder = struct {
172 return exe;169 return exe;
173 }170 }
174171
175 pub fn addCommand(self: &Builder, cwd: []const u8, env_map: &const BufMap,172 pub fn addCommand(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap,
176 path: []const u8, args: []const []const u8) -> &CommandStep173 path: []const u8, args: []const []const u8) -> &CommandStep
177 {174 {
178 const cmd = %%self.allocator.create(CommandStep);175 return CommandStep.create(self, cwd, env_map, path, args);
179 *cmd = CommandStep.init(self, cwd, env_map, path, args);
180 return cmd;
181 }176 }
182177
183 pub fn addWriteFile(self: &Builder, file_path: []const u8, data: []const u8) -> &WriteFileStep {178 pub fn addWriteFile(self: &Builder, file_path: []const u8, data: []const u8) -> &WriteFileStep {
...@@ -489,21 +484,22 @@ pub const Builder = struct {...@@ -489,21 +484,22 @@ pub const Builder = struct {
489 }484 }
490485
491 fn spawnChild(self: &Builder, exe_path: []const u8, args: []const []const u8) -> %void {486 fn spawnChild(self: &Builder, exe_path: []const u8, args: []const []const u8) -> %void {
492 return self.spawnChildEnvMap(&self.env_map, exe_path, args);487 return self.spawnChildEnvMap(null, &self.env_map, exe_path, args);
493 }488 }
494489
495 fn spawnChildEnvMap(self: &Builder, env_map: &const BufMap, exe_path: []const u8,490 fn spawnChildEnvMap(self: &Builder, cwd: ?[]const u8, env_map: &const BufMap,
496 args: []const []const u8) -> %void491 exe_path: []const u8, args: []const []const u8) -> %void
497 {492 {
498 if (self.verbose) {493 if (self.verbose) {
499 %%io.stderr.printf("{}", exe_path);494 test (cwd) |yes_cwd| %%io.stderr.print("cd {}; ", yes_cwd);
495 %%io.stderr.print("{}", exe_path);
500 for (args) |arg| {496 for (args) |arg| {
501 %%io.stderr.printf(" {}", arg);497 %%io.stderr.print(" {}", arg);
502 }498 }
503 %%io.stderr.printf("\n");499 %%io.stderr.printf("\n");
504 }500 }
505501
506 var child = os.ChildProcess.spawn(exe_path, args, env_map,502 var child = os.ChildProcess.spawn(exe_path, args, cwd, env_map,
507 StdIo.Ignore, StdIo.Inherit, StdIo.Inherit, self.allocator) %% |err|503 StdIo.Ignore, StdIo.Inherit, StdIo.Inherit, self.allocator) %% |err|
508 {504 {
509 %%io.stderr.printf("Unable to spawn {}: {}\n", exe_path, @errorName(err));505 %%io.stderr.printf("Unable to spawn {}: {}\n", exe_path, @errorName(err));
...@@ -511,6 +507,7 @@ pub const Builder = struct {...@@ -511,6 +507,7 @@ pub const Builder = struct {
511 };507 };
512508
513 const term = child.wait() %% |err| {509 const term = child.wait() %% |err| {
510 test (cwd) |yes_cwd| %%io.stderr.printf("cwd: {}\n", yes_cwd);
514 %%io.stderr.printf("Unable to spawn {}: {}\n", exe_path, @errorName(err));511 %%io.stderr.printf("Unable to spawn {}: {}\n", exe_path, @errorName(err));
515 return err;512 return err;
516 };513 };
...@@ -560,11 +557,12 @@ pub const Builder = struct {...@@ -560,11 +557,12 @@ pub const Builder = struct {
560557
561 fn copyFile(self: &Builder, source_path: []const u8, dest_path: []const u8) {558 fn copyFile(self: &Builder, source_path: []const u8, dest_path: []const u8) {
562 const dirname = os.path.dirname(dest_path);559 const dirname = os.path.dirname(dest_path);
560 const abs_source_path = self.pathFromRoot(source_path);
563 os.makePath(self.allocator, dirname) %% |err| {561 os.makePath(self.allocator, dirname) %% |err| {
564 debug.panic("Unable to create path {}: {}", dirname, @errorName(err));562 debug.panic("Unable to create path {}: {}", dirname, @errorName(err));
565 };563 };
566 os.copyFile(self.allocator, source_path, dest_path) %% |err| {564 os.copyFile(self.allocator, abs_source_path, dest_path) %% |err| {
567 debug.panic("Unable to copy {} to {}: {}", source_path, dest_path, @errorName(err));565 debug.panic("Unable to copy {} to {}: {}", abs_source_path, dest_path, @errorName(err));
568 };566 };
569 }567 }
570568
...@@ -628,8 +626,10 @@ pub const LibExeObjStep = struct {...@@ -628,8 +626,10 @@ pub const LibExeObjStep = struct {
628 release: bool,626 release: bool,
629 static: bool,627 static: bool,
630 output_path: ?[]const u8,628 output_path: ?[]const u8,
629 output_h_path: ?[]const u8,
631 kind: Kind,630 kind: Kind,
632 version: Version,631 version: Version,
632 out_h_filename: []const u8,
633 out_filename: []const u8,633 out_filename: []const u8,
634 out_filename_major_only: []const u8,634 out_filename_major_only: []const u8,
635 out_filename_name_only: []const u8,635 out_filename_name_only: []const u8,
...@@ -684,8 +684,10 @@ pub const LibExeObjStep = struct {...@@ -684,8 +684,10 @@ pub const LibExeObjStep = struct {
684 .link_libs = BufSet.init(builder.allocator),684 .link_libs = BufSet.init(builder.allocator),
685 .step = Step.init(name, builder.allocator, make),685 .step = Step.init(name, builder.allocator, make),
686 .output_path = null,686 .output_path = null,
687 .output_h_path = null,
687 .version = *ver,688 .version = *ver,
688 .out_filename = undefined,689 .out_filename = undefined,
690 .out_h_filename = builder.fmt("{}.h", name),
689 .out_filename_major_only = undefined,691 .out_filename_major_only = undefined,
690 .out_filename_name_only = undefined,692 .out_filename_name_only = undefined,
691 .object_files = List([]const u8).init(builder.allocator),693 .object_files = List([]const u8).init(builder.allocator),
...@@ -747,6 +749,27 @@ pub const LibExeObjStep = struct {...@@ -747,6 +749,27 @@ pub const LibExeObjStep = struct {
747 self.output_path = value;749 self.output_path = value;
748 }750 }
749751
752 pub fn getOutputPath(self: &LibExeObjStep) -> []const u8 {
753 test (self.output_path) |output_path| {
754 output_path
755 } else {
756 const wanted_path = %%os.path.join(self.builder.allocator, self.builder.cache_root, self.out_filename);
757 %%os.path.relative(self.builder.allocator, self.builder.build_root, wanted_path)
758 }
759 }
760
761 pub fn setOutputHPath(self: &LibExeObjStep, value: []const u8) {
762 self.output_h_path = value;
763 }
764
765 pub fn getOutputHPath(self: &LibExeObjStep) -> []const u8 {
766 test (self.output_h_path) |output_h_path| {
767 output_h_path
768 } else {
769 %%os.path.join(self.builder.allocator, self.builder.cache_root, self.out_h_filename)
770 }
771 }
772
750 pub fn addAssemblyFile(self: &LibExeObjStep, path: []const u8) {773 pub fn addAssemblyFile(self: &LibExeObjStep, path: []const u8) {
751 %%self.assembly_files.append(path);774 %%self.assembly_files.append(path);
752 }775 }
...@@ -763,14 +786,7 @@ pub const LibExeObjStep = struct {...@@ -763,14 +786,7 @@ pub const LibExeObjStep = struct {
763786
764 self.step.dependOn(&obj.step);787 self.step.dependOn(&obj.step);
765788
766 const path_to_obj = test (obj.output_path) |explicit_out_path| {789 %%self.object_files.append(obj.getOutputPath());
767 explicit_out_path
768 } else {
769 // TODO make it so we always know where this will be
770 %%os.path.join(self.builder.allocator, self.builder.cache_root,
771 self.builder.fmt("{}{}", obj.name, obj.target.oFileExt()))
772 };
773 %%self.object_files.append(path_to_obj);
774 }790 }
775791
776 fn make(step: &Step) -> %void {792 fn make(step: &Step) -> %void {
...@@ -814,10 +830,16 @@ pub const LibExeObjStep = struct {...@@ -814,10 +830,16 @@ pub const LibExeObjStep = struct {
814 %%zig_args.append("--release");830 %%zig_args.append("--release");
815 }831 }
816832
817 test (self.output_path) |output_path| {833 %%zig_args.append("--cache-dir");
818 %%zig_args.append("--output");834 %%zig_args.append(builder.cache_root);
819 %%zig_args.append(builder.pathFromRoot(output_path));835
820 }836 const output_path = builder.pathFromRoot(self.getOutputPath());
837 %%zig_args.append("--output");
838 %%zig_args.append(output_path);
839
840 const output_h_path = self.getOutputHPath();
841 %%zig_args.append("--output-h");
842 %%zig_args.append(builder.pathFromRoot(output_h_path));
821843
822 %%zig_args.append("--name");844 %%zig_args.append("--name");
823 %%zig_args.append(self.name);845 %%zig_args.append(self.name);
...@@ -879,10 +901,8 @@ pub const LibExeObjStep = struct {...@@ -879,10 +901,8 @@ pub const LibExeObjStep = struct {
879 %return builder.spawnChild(builder.zig_exe, zig_args.toSliceConst());901 %return builder.spawnChild(builder.zig_exe, zig_args.toSliceConst());
880902
881 if (self.kind == Kind.Lib and !self.static) {903 if (self.kind == Kind.Lib and !self.static) {
882 // sym link for libfoo.so.1 to libfoo.so.1.2.3904 %return doAtomicSymLinks(builder.allocator, output_path, self.out_filename_major_only,
883 %%os.atomicSymLink(builder.allocator, self.out_filename, self.out_filename_major_only);905 self.out_filename_name_only);
884 // sym link for libfoo.so to libfoo.so.1
885 %%os.atomicSymLink(builder.allocator, self.out_filename_major_only, self.out_filename_name_only);
886 }906 }
887 }907 }
888};908};
...@@ -987,10 +1007,12 @@ pub const TestStep = struct {...@@ -987,10 +1007,12 @@ pub const TestStep = struct {
987 }1007 }
988};1008};
9891009
1010// TODO merge with CExecutable
990pub const CLibrary = struct {1011pub const CLibrary = struct {
991 step: Step,1012 step: Step,
992 name: []const u8,1013 name: []const u8,
993 out_filename: []const u8,1014 out_filename: []const u8,
1015 output_path: ?[]const u8,
994 static: bool,1016 static: bool,
995 version: Version,1017 version: Version,
996 cflags: List([]const u8),1018 cflags: List([]const u8),
...@@ -1024,6 +1046,7 @@ pub const CLibrary = struct {...@@ -1024,6 +1046,7 @@ pub const CLibrary = struct {
1024 .step = Step.init(name, builder.allocator, make),1046 .step = Step.init(name, builder.allocator, make),
1025 .link_libs = BufSet.init(builder.allocator),1047 .link_libs = BufSet.init(builder.allocator),
1026 .include_dirs = List([]const u8).init(builder.allocator),1048 .include_dirs = List([]const u8).init(builder.allocator),
1049 .output_path = null,
1027 .out_filename = undefined,1050 .out_filename = undefined,
1028 .major_only_filename = undefined,1051 .major_only_filename = undefined,
1029 .name_only_filename = undefined,1052 .name_only_filename = undefined,
...@@ -1043,6 +1066,19 @@ pub const CLibrary = struct {...@@ -1043,6 +1066,19 @@ pub const CLibrary = struct {
1043 }1066 }
1044 }1067 }
10451068
1069 pub fn setOutputPath(self: &CLibrary, value: []const u8) {
1070 self.output_path = value;
1071 }
1072
1073 pub fn getOutputPath(self: &CLibrary) -> []const u8 {
1074 test (self.output_path) |output_path| {
1075 output_path
1076 } else {
1077 const wanted_path = %%os.path.join(self.builder.allocator, self.builder.cache_root, self.out_filename);
1078 %%os.path.relative(self.builder.allocator, self.builder.build_root, wanted_path)
1079 }
1080 }
1081
1046 pub fn linkSystemLibrary(self: &CLibrary, name: []const u8) {1082 pub fn linkSystemLibrary(self: &CLibrary, name: []const u8) {
1047 %%self.link_libs.put(name);1083 %%self.link_libs.put(name);
1048 }1084 }
...@@ -1131,8 +1167,9 @@ pub const CLibrary = struct {...@@ -1131,8 +1167,9 @@ pub const CLibrary = struct {
1131 defer builder.allocator.free(soname_arg);1167 defer builder.allocator.free(soname_arg);
1132 %%cc_args.append(soname_arg);1168 %%cc_args.append(soname_arg);
11331169
1170 const output_path = builder.pathFromRoot(self.getOutputPath());
1134 %%cc_args.append("-o");1171 %%cc_args.append("-o");
1135 %%cc_args.append(self.out_filename);1172 %%cc_args.append(output_path);
11361173
1137 for (self.object_files.toSliceConst()) |object_file| {1174 for (self.object_files.toSliceConst()) |object_file| {
1138 %%cc_args.append(builder.pathFromRoot(object_file));1175 %%cc_args.append(builder.pathFromRoot(object_file));
...@@ -1140,10 +1177,8 @@ pub const CLibrary = struct {...@@ -1140,10 +1177,8 @@ pub const CLibrary = struct {
11401177
1141 %return builder.spawnChild(cc, cc_args.toSliceConst());1178 %return builder.spawnChild(cc, cc_args.toSliceConst());
11421179
1143 // sym link for libfoo.so.1 to libfoo.so.1.2.31180 %return doAtomicSymLinks(builder.allocator, output_path, self.major_only_filename,
1144 %%os.atomicSymLink(builder.allocator, self.out_filename, self.major_only_filename);1181 self.name_only_filename);
1145 // sym link for libfoo.so to libfoo.so.1
1146 %%os.atomicSymLink(builder.allocator, self.major_only_filename, self.name_only_filename);
1147 }1182 }
1148 }1183 }
11491184
...@@ -1169,9 +1204,11 @@ pub const CExecutable = struct {...@@ -1169,9 +1204,11 @@ pub const CExecutable = struct {
1169 link_libs: BufSet,1204 link_libs: BufSet,
1170 target: Target,1205 target: Target,
1171 include_dirs: List([]const u8),1206 include_dirs: List([]const u8),
1207 output_path: ?[]const u8,
1208 out_filename: []const u8,
11721209
1173 pub fn init(builder: &Builder, name: []const u8) -> CExecutable {1210 pub fn init(builder: &Builder, name: []const u8) -> CExecutable {
1174 CExecutable {1211 var self = CExecutable {
1175 .builder = builder,1212 .builder = builder,
1176 .name = name,1213 .name = name,
1177 .target = Target.Native,1214 .target = Target.Native,
...@@ -1182,6 +1219,27 @@ pub const CExecutable = struct {...@@ -1182,6 +1219,27 @@ pub const CExecutable = struct {
1182 .step = Step.init(name, builder.allocator, make),1219 .step = Step.init(name, builder.allocator, make),
1183 .link_libs = BufSet.init(builder.allocator),1220 .link_libs = BufSet.init(builder.allocator),
1184 .include_dirs = List([]const u8).init(builder.allocator),1221 .include_dirs = List([]const u8).init(builder.allocator),
1222 .output_path = null,
1223 .out_filename = undefined,
1224 };
1225 self.computeOutFileName();
1226 return self;
1227 }
1228
1229 fn computeOutFileName(self: &CExecutable) {
1230 self.out_filename = self.builder.fmt("{}{}", self.name, self.target.exeFileExt());
1231 }
1232
1233 pub fn setOutputPath(self: &CExecutable, value: []const u8) {
1234 self.output_path = value;
1235 }
1236
1237 pub fn getOutputPath(self: &CExecutable) -> []const u8 {
1238 test (self.output_path) |output_path| {
1239 self.builder.pathFromRoot(output_path)
1240 } else {
1241 const wanted_path = %%os.path.join(self.builder.allocator, self.builder.cache_root, self.out_filename);
1242 %%os.path.relative(self.builder.allocator, self.builder.build_root, wanted_path)
1185 }1243 }
1186 }1244 }
11871245
...@@ -1191,15 +1249,15 @@ pub const CExecutable = struct {...@@ -1191,15 +1249,15 @@ pub const CExecutable = struct {
11911249
1192 pub fn linkCLibrary(self: &CExecutable, clib: &CLibrary) {1250 pub fn linkCLibrary(self: &CExecutable, clib: &CLibrary) {
1193 self.step.dependOn(&clib.step);1251 self.step.dependOn(&clib.step);
1194 %%self.full_path_libs.append(clib.out_filename);1252 %%self.full_path_libs.append(clib.getOutputPath());
1195 }1253 }
11961254
1197 pub fn linkLibrary(self: &CExecutable, lib: &LibExeObjStep) {1255 pub fn linkLibrary(self: &CExecutable, lib: &LibExeObjStep) {
1198 assert(lib.kind == LibExeObjStep.Kind.Lib);1256 assert(lib.kind == LibExeObjStep.Kind.Lib);
1199 self.step.dependOn(&lib.step);1257 self.step.dependOn(&lib.step);
1200 %%self.full_path_libs.append(lib.out_filename);1258 %%self.full_path_libs.append(lib.getOutputPath());
1201 // TODO should be some kind of isolated directory that only has this header in it1259 // TODO should be some kind of isolated directory that only has this header in it
1202 %%self.include_dirs.append(self.builder.out_dir);1260 %%self.include_dirs.append(self.builder.cache_root);
1203 }1261 }
12041262
1205 pub fn addObject(self: &CExecutable, obj: &LibExeObjStep) {1263 pub fn addObject(self: &CExecutable, obj: &LibExeObjStep) {
...@@ -1207,12 +1265,10 @@ pub const CExecutable = struct {...@@ -1207,12 +1265,10 @@ pub const CExecutable = struct {
12071265
1208 self.step.dependOn(&obj.step);1266 self.step.dependOn(&obj.step);
12091267
1210 // TODO make it so we always know where this will be1268 %%self.object_files.append(obj.getOutputPath());
1211 %%self.object_files.append(%%os.path.join(self.builder.allocator, self.builder.cache_root,
1212 self.builder.fmt("{}{}", obj.name, obj.target.oFileExt())));
12131269
1214 // TODO should be some kind of isolated directory that only has this header in it1270 // TODO should be some kind of isolated directory that only has this header in it
1215 %%self.include_dirs.append(self.builder.out_dir);1271 %%self.include_dirs.append(self.builder.cache_root);
1216 }1272 }
12171273
1218 pub fn addSourceFile(self: &CExecutable, file: []const u8) {1274 pub fn addSourceFile(self: &CExecutable, file: []const u8) {
...@@ -1256,7 +1312,6 @@ pub const CExecutable = struct {...@@ -1256,7 +1312,6 @@ pub const CExecutable = struct {
1256 %%cc_args.append("-c");1312 %%cc_args.append("-c");
1257 %%cc_args.append(builder.pathFromRoot(source_file));1313 %%cc_args.append(builder.pathFromRoot(source_file));
12581314
1259 // TODO don't dump the .o file in the same place as the source file
1260 const rel_src_path = %%os.path.relative(builder.allocator, builder.build_root, source_file);1315 const rel_src_path = %%os.path.relative(builder.allocator, builder.build_root, source_file);
1261 const cache_o_src = %%os.path.join(builder.allocator, builder.cache_root, rel_src_path);1316 const cache_o_src = %%os.path.join(builder.allocator, builder.cache_root, rel_src_path);
1262 const cache_o_dir = os.path.dirname(cache_o_src);1317 const cache_o_dir = os.path.dirname(cache_o_src);
...@@ -1276,26 +1331,28 @@ pub const CExecutable = struct {...@@ -1276,26 +1331,28 @@ pub const CExecutable = struct {
12761331
1277 %return builder.spawnChild(cc, cc_args.toSliceConst());1332 %return builder.spawnChild(cc, cc_args.toSliceConst());
12781333
1279 %%self.object_files.append(cache_o_file);1334 %%self.object_files.append(%%os.path.relative(builder.allocator, builder.build_root, cache_o_file));
1280 }1335 }
12811336
1282 %%cc_args.resize(0);1337 %%cc_args.resize(0);
12831338
1284 for (self.object_files.toSliceConst()) |object_file| {1339 for (self.object_files.toSliceConst()) |object_file| {
1285 %%cc_args.append(object_file);1340 %%cc_args.append(builder.pathFromRoot(object_file));
1286 }1341 }
12871342
1343 const output_path = builder.pathFromRoot(self.getOutputPath());
1288 %%cc_args.append("-o");1344 %%cc_args.append("-o");
1289 %%cc_args.append(self.name);1345 %%cc_args.append(output_path);
12901346
1291 const rpath_arg = builder.fmt("-Wl,-rpath,{}", builder.out_dir);1347 const rpath_arg = builder.fmt("-Wl,-rpath,{}",
1348 %%os.path.real(builder.allocator, builder.cache_root));
1292 defer builder.allocator.free(rpath_arg);1349 defer builder.allocator.free(rpath_arg);
1293 %%cc_args.append(rpath_arg);1350 %%cc_args.append(rpath_arg);
12941351
1295 %%cc_args.append("-rdynamic");1352 %%cc_args.append("-rdynamic");
12961353
1297 for (self.full_path_libs.toSliceConst()) |full_path_lib| {1354 for (self.full_path_libs.toSliceConst()) |full_path_lib| {
1298 %%cc_args.append(full_path_lib);1355 %%cc_args.append(builder.pathFromRoot(full_path_lib));
1299 }1356 }
13001357
1301 %return builder.spawnChild(cc, cc_args.toSliceConst());1358 %return builder.spawnChild(cc, cc_args.toSliceConst());
...@@ -1317,27 +1374,29 @@ pub const CommandStep = struct {...@@ -1317,27 +1374,29 @@ pub const CommandStep = struct {
1317 builder: &Builder,1374 builder: &Builder,
1318 exe_path: []const u8,1375 exe_path: []const u8,
1319 args: []const []const u8,1376 args: []const []const u8,
1320 cwd: []const u8,1377 cwd: ?[]const u8,
1321 env_map: &const BufMap,1378 env_map: &const BufMap,
13221379
1323 pub fn init(builder: &Builder, cwd: []const u8, env_map: &const BufMap,1380 pub fn create(builder: &Builder, cwd: ?[]const u8, env_map: &const BufMap,
1324 exe_path: []const u8, args: []const []const u8) -> CommandStep1381 exe_path: []const u8, args: []const []const u8) -> &CommandStep
1325 {1382 {
1326 CommandStep {1383 const self = %%builder.allocator.create(CommandStep);
1384 *self = CommandStep {
1327 .builder = builder,1385 .builder = builder,
1328 .step = Step.init(exe_path, builder.allocator, make),1386 .step = Step.init(exe_path, builder.allocator, make),
1329 .exe_path = exe_path,1387 .exe_path = exe_path,
1330 .args = args,1388 .args = args,
1331 .cwd = cwd,1389 .cwd = cwd,
1332 .env_map = env_map,1390 .env_map = env_map,
1333 }1391 };
1392 return self;
1334 }1393 }
13351394
1336 fn make(step: &Step) -> %void {1395 fn make(step: &Step) -> %void {
1337 const self = @fieldParentPtr(CommandStep, "step", step);1396 const self = @fieldParentPtr(CommandStep, "step", step);
13381397
1339 // TODO set cwd1398 const cwd = test (self.cwd) |cwd| self.builder.pathFromRoot(cwd) else null;
1340 return self.builder.spawnChildEnvMap(self.env_map, self.exe_path, self.args);1399 return self.builder.spawnChildEnvMap(cwd, self.env_map, self.exe_path, self.args);
1341 }1400 }
1342};1401};
13431402
...@@ -1367,12 +1426,10 @@ pub const InstallCLibraryStep = struct {...@@ -1367,12 +1426,10 @@ pub const InstallCLibraryStep = struct {
1367 const self = @fieldParentPtr(InstallCLibraryStep, "step", step);1426 const self = @fieldParentPtr(InstallCLibraryStep, "step", step);
1368 const builder = self.builder;1427 const builder = self.builder;
13691428
1370 self.builder.copyFile(self.lib.out_filename, self.dest_file);1429 self.builder.copyFile(self.lib.getOutputPath(), self.dest_file);
1371 if (!self.lib.static) {1430 if (!self.lib.static) {
1372 const dest_major_only = %%os.path.join(builder.allocator, builder.lib_dir, self.lib.major_only_filename);1431 %return doAtomicSymLinks(self.builder.allocator, self.dest_file, self.lib.major_only_filename,
1373 const dest_name_only = %%os.path.join(builder.allocator, builder.lib_dir, self.lib.name_only_filename);1432 self.lib.name_only_filename);
1374 %%os.atomicSymLink(self.builder.allocator, self.lib.out_filename, dest_major_only);
1375 %%os.atomicSymLink(self.builder.allocator, self.lib.major_only_filename, dest_name_only);
1376 }1433 }
1377 }1434 }
1378};1435};
...@@ -1506,3 +1563,22 @@ pub const Step = struct {...@@ -1506,3 +1563,22 @@ pub const Step = struct {
15061563
1507 fn makeNoOp(self: &Step) -> %void {}1564 fn makeNoOp(self: &Step) -> %void {}
1508};1565};
1566
1567fn doAtomicSymLinks(allocator: &Allocator, output_path: []const u8, filename_major_only: []const u8,
1568 filename_name_only: []const u8) -> %void
1569{
1570 const out_dir = os.path.dirname(output_path);
1571 const out_basename = os.path.basename(output_path);
1572 // sym link for libfoo.so.1 to libfoo.so.1.2.3
1573 const major_only_path = %%os.path.join(allocator, out_dir, filename_major_only);
1574 os.atomicSymLink(allocator, out_basename, major_only_path) %% |err| {
1575 %%io.stderr.printf("Unable to symlink {} -> {}\n", major_only_path, out_basename);
1576 return err;
1577 };
1578 // sym link for libfoo.so to libfoo.so.1
1579 const name_only_path = %%os.path.join(allocator, out_dir, filename_name_only);
1580 os.atomicSymLink(allocator, filename_major_only, name_only_path) %% |err| {
1581 %%io.stderr.printf("Unable to symlink {} -> {}\n", name_only_path, filename_major_only);
1582 return err;
1583 };
1584}
std/fmt.zig+3-3
...@@ -345,17 +345,17 @@ fn bufPrintWrite(context: &BufPrintContext, bytes: []const u8) -> bool {...@@ -345,17 +345,17 @@ fn bufPrintWrite(context: &BufPrintContext, bytes: []const u8) -> bool {
345 return true;345 return true;
346}346}
347347
348pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) {348pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) -> []u8 {
349 var context = BufPrintContext { .remaining = buf, };349 var context = BufPrintContext { .remaining = buf, };
350 _ = format(&context, bufPrintWrite, fmt, args);350 _ = format(&context, bufPrintWrite, fmt, args);
351 return buf[0...buf.len - context.remaining.len];
351}352}
352353
353pub fn allocPrint(allocator: &mem.Allocator, comptime fmt: []const u8, args: ...) -> %[]u8 {354pub fn allocPrint(allocator: &mem.Allocator, comptime fmt: []const u8, args: ...) -> %[]u8 {
354 var size: usize = 0;355 var size: usize = 0;
355 _ = format(&size, countSize, fmt, args);356 _ = format(&size, countSize, fmt, args);
356 const buf = %return allocator.alloc(u8, size);357 const buf = %return allocator.alloc(u8, size);
357 bufPrint(buf, fmt, args);358 return bufPrint(buf, fmt, args);
358 return buf;
359}359}
360360
361fn countSize(size: &usize, bytes: []const u8) -> bool {361fn countSize(size: &usize, bytes: []const u8) -> bool {
std/os/child_process.zig+10-3
...@@ -30,12 +30,13 @@ pub const ChildProcess = struct {...@@ -30,12 +30,13 @@ pub const ChildProcess = struct {
30 Close,30 Close,
31 };31 };
3232
33 pub fn spawn(exe_path: []const u8, args: []const []const u8, env_map: &const BufMap,33 pub fn spawn(exe_path: []const u8, args: []const []const u8,
34 cwd: ?[]const u8, env_map: &const BufMap,
34 stdin: StdIo, stdout: StdIo, stderr: StdIo, allocator: &Allocator) -> %ChildProcess35 stdin: StdIo, stdout: StdIo, stderr: StdIo, allocator: &Allocator) -> %ChildProcess
35 {36 {
36 switch (@compileVar("os")) {37 switch (@compileVar("os")) {
37 Os.linux, Os.macosx, Os.ios, Os.darwin => {38 Os.linux, Os.macosx, Os.ios, Os.darwin => {
38 return spawnPosix(exe_path, args, env_map, stdin, stdout, stderr, allocator);39 return spawnPosix(exe_path, args, cwd, env_map, stdin, stdout, stderr, allocator);
39 },40 },
40 else => @compileError("Unsupported OS"),41 else => @compileError("Unsupported OS"),
41 }42 }
...@@ -98,7 +99,8 @@ pub const ChildProcess = struct {...@@ -98,7 +99,8 @@ pub const ChildProcess = struct {
98 };99 };
99 }100 }
100101
101 fn spawnPosix(exe_path: []const u8, args: []const []const u8, env_map: &const BufMap,102 fn spawnPosix(exe_path: []const u8, args: []const []const u8,
103 maybe_cwd: ?[]const u8, env_map: &const BufMap,
102 stdin: StdIo, stdout: StdIo, stderr: StdIo, allocator: &Allocator) -> %ChildProcess104 stdin: StdIo, stdout: StdIo, stderr: StdIo, allocator: &Allocator) -> %ChildProcess
103 {105 {
104 // TODO issue #295106 // TODO issue #295
...@@ -155,6 +157,11 @@ pub const ChildProcess = struct {...@@ -155,6 +157,11 @@ pub const ChildProcess = struct {
155 setUpChildIo(stderr, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) %%157 setUpChildIo(stderr, stderr_pipe[1], posix.STDERR_FILENO, dev_null_fd) %%
156 |err| forkChildErrReport(err_pipe[1], err);158 |err| forkChildErrReport(err_pipe[1], err);
157159
160 test (maybe_cwd) |cwd| {
161 os.changeCurDir(allocator, cwd) %%
162 |err| forkChildErrReport(err_pipe[1], err);
163 }
164
158 os.posixExecve(exe_path, args, env_map, allocator) %%165 os.posixExecve(exe_path, args, env_map, allocator) %%
159 |err| forkChildErrReport(err_pipe[1], err);166 |err| forkChildErrReport(err_pipe[1], err);
160 }167 }
std/os/index.zig+57
...@@ -780,3 +780,60 @@ pub const Dir = struct {...@@ -780,3 +780,60 @@ pub const Dir = struct {
780 };780 };
781 }781 }
782};782};
783
784pub fn changeCurDir(allocator: &Allocator, dir_path: []const u8) -> %void {
785 const path_buf = %return allocator.alloc(u8, dir_path.len + 1);
786 defer allocator.free(path_buf);
787
788 mem.copy(u8, path_buf, dir_path);
789 path_buf[dir_path.len] = 0;
790
791 const err = posix.getErrno(posix.chdir(path_buf.ptr));
792 if (err > 0) {
793 return switch (err) {
794 errno.EACCES => error.AccessDenied,
795 errno.EFAULT => unreachable,
796 errno.EIO => error.FileSystem,
797 errno.ELOOP => error.SymLinkLoop,
798 errno.ENAMETOOLONG => error.NameTooLong,
799 errno.ENOENT => error.FileNotFound,
800 errno.ENOMEM => error.SystemResources,
801 errno.ENOTDIR => error.NotDir,
802 else => error.Unexpected,
803 };
804 }
805}
806
807/// Read value of a symbolic link.
808pub fn readLink(allocator: &Allocator, pathname: []const u8) -> %[]u8 {
809 const path_buf = %return allocator.alloc(u8, pathname.len + 1);
810 defer allocator.free(path_buf);
811
812 mem.copy(u8, path_buf, pathname);
813 path_buf[pathname.len] = 0;
814
815 var result_buf = %return allocator.alloc(u8, 1024);
816 %defer allocator.free(result_buf);
817 while (true) {
818 const ret_val = posix.readlink(path_buf.ptr, result_buf.ptr, result_buf.len);
819 const err = posix.getErrno(ret_val);
820 if (err > 0) {
821 return switch (err) {
822 errno.EACCES => error.AccessDenied,
823 errno.EFAULT, errno.EINVAL => unreachable,
824 errno.EIO => error.FileSystem,
825 errno.ELOOP => error.SymLinkLoop,
826 errno.ENAMETOOLONG => error.NameTooLong,
827 errno.ENOENT => error.FileNotFound,
828 errno.ENOMEM => error.SystemResources,
829 errno.ENOTDIR => error.NotDir,
830 else => error.Unexpected,
831 };
832 }
833 if (ret_val == result_buf.len) {
834 result_buf = %return allocator.realloc(u8, result_buf, result_buf.len * 2);
835 continue;
836 }
837 return result_buf[0...ret_val];
838 }
839}
std/os/linux.zig+8
...@@ -335,6 +335,10 @@ pub fn dup2(old: i32, new: i32) -> usize {...@@ -335,6 +335,10 @@ pub fn dup2(old: i32, new: i32) -> usize {
335 arch.syscall2(arch.SYS_dup2, usize(old), usize(new))335 arch.syscall2(arch.SYS_dup2, usize(old), usize(new))
336}336}
337337
338pub fn chdir(path: &const u8) -> usize {
339 arch.syscall1(arch.SYS_chdir, usize(path))
340}
341
338pub fn execve(path: &const u8, argv: &const ?&const u8, envp: &const ?&const u8) -> usize {342pub fn execve(path: &const u8, argv: &const ?&const u8, envp: &const ?&const u8) -> usize {
339 arch.syscall3(arch.SYS_execve, usize(path), usize(argv), usize(envp))343 arch.syscall3(arch.SYS_execve, usize(path), usize(argv), usize(envp))
340}344}
...@@ -356,6 +360,10 @@ pub fn isatty(fd: i32) -> bool {...@@ -356,6 +360,10 @@ pub fn isatty(fd: i32) -> bool {
356 return arch.syscall3(arch.SYS_ioctl, usize(fd), TIOCGWINSZ, usize(&wsz)) == 0;360 return arch.syscall3(arch.SYS_ioctl, usize(fd), TIOCGWINSZ, usize(&wsz)) == 0;
357}361}
358362
363pub fn readlink(noalias path: &const u8, noalias buf_ptr: &u8, buf_len: usize) -> usize {
364 arch.syscall3(arch.SYS_readlink, usize(path), usize(buf_ptr), buf_len)
365}
366
359pub fn mkdir(path: &const u8, mode: usize) -> usize {367pub fn mkdir(path: &const u8, mode: usize) -> usize {
360 arch.syscall2(arch.SYS_mkdir, usize(path), mode)368 arch.syscall2(arch.SYS_mkdir, usize(path), mode)
361}369}
std/os/path.zig+55
...@@ -1,9 +1,11 @@...@@ -1,9 +1,11 @@
1const debug = @import("../debug.zig");1const debug = @import("../debug.zig");
2const assert = debug.assert;2const assert = debug.assert;
3const mem = @import("../mem.zig");3const mem = @import("../mem.zig");
4const fmt = @import("../fmt.zig");
4const Allocator = mem.Allocator;5const Allocator = mem.Allocator;
5const os = @import("index.zig");6const os = @import("index.zig");
6const math = @import("../math.zig");7const math = @import("../math.zig");
8const posix = os.posix;
79
8pub const sep = switch (@compileVar("os")) {10pub const sep = switch (@compileVar("os")) {
9 Os.windows => '\\',11 Os.windows => '\\',
...@@ -185,6 +187,45 @@ fn testDirname(input: []const u8, expected_output: []const u8) {...@@ -185,6 +187,45 @@ fn testDirname(input: []const u8, expected_output: []const u8) {
185 assert(mem.eql(u8, dirname(input), expected_output));187 assert(mem.eql(u8, dirname(input), expected_output));
186}188}
187189
190pub fn basename(path: []const u8) -> []const u8 {
191 if (path.len == 0)
192 return []u8{};
193
194 var end_index: usize = path.len - 1;
195 while (path[end_index] == '/') {
196 if (end_index == 0)
197 return []u8{};
198 end_index -= 1;
199 }
200 var start_index: usize = end_index;
201 end_index += 1;
202 while (path[start_index] != '/') {
203 if (start_index == 0)
204 return path[0...end_index];
205 start_index -= 1;
206 }
207
208 return path[start_index + 1...end_index];
209}
210
211test "os.path.basename" {
212 testBasename("", "");
213 testBasename("/", "");
214 testBasename("/dir/basename.ext", "basename.ext");
215 testBasename("/basename.ext", "basename.ext");
216 testBasename("basename.ext", "basename.ext");
217 testBasename("basename.ext/", "basename.ext");
218 testBasename("basename.ext//", "basename.ext");
219 testBasename("/aaa/bbb", "bbb");
220 testBasename("/aaa/", "aaa");
221 testBasename("/aaa/b", "b");
222 testBasename("/a/b", "b");
223 testBasename("//a", "a");
224}
225fn testBasename(input: []const u8, expected_output: []const u8) {
226 assert(mem.eql(u8, basename(input), expected_output));
227}
228
188/// Returns the relative path from ::from to ::to. If ::from and ::to each229/// Returns the relative path from ::from to ::to. If ::from and ::to each
189/// resolve to the same path (after calling ::resolve on each), a zero-length230/// resolve to the same path (after calling ::resolve on each), a zero-length
190/// string is returned.231/// string is returned.
...@@ -252,3 +293,17 @@ fn testRelative(from: []const u8, to: []const u8, expected_output: []const u8) {...@@ -252,3 +293,17 @@ fn testRelative(from: []const u8, to: []const u8, expected_output: []const u8) {
252 const result = %%relative(&debug.global_allocator, from, to);293 const result = %%relative(&debug.global_allocator, from, to);
253 assert(mem.eql(u8, result, expected_output));294 assert(mem.eql(u8, result, expected_output));
254}295}
296
297/// Return the canonicalized absolute pathname.
298/// Expands all symbolic links and resolves references to `.`, `..`, and
299/// extra `/` characters in ::pathname.
300/// Caller must deallocate result.
301pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 {
302 const fd = %return os.posixOpen(pathname, posix.O_PATH|posix.O_NONBLOCK|posix.O_CLOEXEC, 0, allocator);
303 defer os.posixClose(fd);
304
305 var buf: ["/proc/self/fd/-2147483648".len]u8 = undefined;
306 const proc_path = fmt.bufPrint(buf[0...], "/proc/self/fd/{}", fd);
307
308 return os.readLink(allocator, proc_path);
309}
test/tests.zig+16-16
...@@ -189,7 +189,7 @@ pub const CompareOutputContext = struct {...@@ -189,7 +189,7 @@ pub const CompareOutputContext = struct {
189189
190 %%io.stderr.printf("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);190 %%io.stderr.printf("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);
191191
192 var child = os.ChildProcess.spawn(full_exe_path, [][]u8{}, &b.env_map,192 var child = os.ChildProcess.spawn(full_exe_path, [][]u8{}, null, &b.env_map,
193 StdIo.Ignore, StdIo.Pipe, StdIo.Pipe, b.allocator) %% |err|193 StdIo.Ignore, StdIo.Pipe, StdIo.Pipe, b.allocator) %% |err|
194 {194 {
195 debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err));195 debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err));
...@@ -264,7 +264,7 @@ pub const CompareOutputContext = struct {...@@ -264,7 +264,7 @@ pub const CompareOutputContext = struct {
264264
265 %%io.stderr.printf("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);265 %%io.stderr.printf("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);
266266
267 var child = os.ChildProcess.spawn(full_exe_path, [][]u8{}, &b.env_map,267 var child = os.ChildProcess.spawn(full_exe_path, [][]u8{}, null, &b.env_map,
268 StdIo.Ignore, StdIo.Pipe, StdIo.Pipe, b.allocator) %% |err|268 StdIo.Ignore, StdIo.Pipe, StdIo.Pipe, b.allocator) %% |err|
269 {269 {
270 debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err));270 debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err));
...@@ -344,8 +344,8 @@ pub const CompareOutputContext = struct {...@@ -344,8 +344,8 @@ pub const CompareOutputContext = struct {
344 pub fn addCase(self: &CompareOutputContext, case: &const TestCase) {344 pub fn addCase(self: &CompareOutputContext, case: &const TestCase) {
345 const b = self.b;345 const b = self.b;
346346
347 const root_src = %%os.path.join(b.allocator, "test_artifacts", case.sources.items[0].filename);347 const root_src = %%os.path.join(b.allocator, b.cache_root, case.sources.items[0].filename);
348 const exe_path = %%os.path.join(b.allocator, "test_artifacts", "test");348 const exe_path = %%os.path.join(b.allocator, b.cache_root, "test");
349349
350 switch (case.special) {350 switch (case.special) {
351 Special.Asm => {351 Special.Asm => {
...@@ -360,7 +360,7 @@ pub const CompareOutputContext = struct {...@@ -360,7 +360,7 @@ pub const CompareOutputContext = struct {
360 exe.setOutputPath(exe_path);360 exe.setOutputPath(exe_path);
361361
362 for (case.sources.toSliceConst()) |src_file| {362 for (case.sources.toSliceConst()) |src_file| {
363 const expanded_src_path = %%os.path.join(b.allocator, "test_artifacts", src_file.filename);363 const expanded_src_path = %%os.path.join(b.allocator, b.cache_root, src_file.filename);
364 const write_src = b.addWriteFile(expanded_src_path, src_file.source);364 const write_src = b.addWriteFile(expanded_src_path, src_file.source);
365 exe.step.dependOn(&write_src.step);365 exe.step.dependOn(&write_src.step);
366 }366 }
...@@ -388,7 +388,7 @@ pub const CompareOutputContext = struct {...@@ -388,7 +388,7 @@ pub const CompareOutputContext = struct {
388 }388 }
389389
390 for (case.sources.toSliceConst()) |src_file| {390 for (case.sources.toSliceConst()) |src_file| {
391 const expanded_src_path = %%os.path.join(b.allocator, "test_artifacts", src_file.filename);391 const expanded_src_path = %%os.path.join(b.allocator, b.cache_root, src_file.filename);
392 const write_src = b.addWriteFile(expanded_src_path, src_file.source);392 const write_src = b.addWriteFile(expanded_src_path, src_file.source);
393 exe.step.dependOn(&write_src.step);393 exe.step.dependOn(&write_src.step);
394 }394 }
...@@ -401,7 +401,7 @@ pub const CompareOutputContext = struct {...@@ -401,7 +401,7 @@ pub const CompareOutputContext = struct {
401 }401 }
402 },402 },
403 Special.DebugSafety => {403 Special.DebugSafety => {
404 const obj_path = %%os.path.join(b.allocator, "test_artifacts", "test.o");404 const obj_path = %%os.path.join(b.allocator, b.cache_root, "test.o");
405 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "debug-safety {}", case.name);405 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "debug-safety {}", case.name);
406 test (self.test_filter) |filter| {406 test (self.test_filter) |filter| {
407 if (mem.indexOf(u8, annotated_case_name, filter) == null)407 if (mem.indexOf(u8, annotated_case_name, filter) == null)
...@@ -415,7 +415,7 @@ pub const CompareOutputContext = struct {...@@ -415,7 +415,7 @@ pub const CompareOutputContext = struct {
415 }415 }
416416
417 for (case.sources.toSliceConst()) |src_file| {417 for (case.sources.toSliceConst()) |src_file| {
418 const expanded_src_path = %%os.path.join(b.allocator, "test_artifacts", src_file.filename);418 const expanded_src_path = %%os.path.join(b.allocator, b.cache_root, src_file.filename);
419 const write_src = b.addWriteFile(expanded_src_path, src_file.source);419 const write_src = b.addWriteFile(expanded_src_path, src_file.source);
420 exe.step.dependOn(&write_src.step);420 exe.step.dependOn(&write_src.step);
421 }421 }
...@@ -488,8 +488,8 @@ pub const CompileErrorContext = struct {...@@ -488,8 +488,8 @@ pub const CompileErrorContext = struct {
488 const self = @fieldParentPtr(CompileCmpOutputStep, "step", step);488 const self = @fieldParentPtr(CompileCmpOutputStep, "step", step);
489 const b = self.context.b;489 const b = self.context.b;
490490
491 const root_src = %%os.path.join(b.allocator, "test_artifacts", self.case.sources.items[0].filename);491 const root_src = %%os.path.join(b.allocator, b.cache_root, self.case.sources.items[0].filename);
492 const obj_path = %%os.path.join(b.allocator, "test_artifacts", "test.o");492 const obj_path = %%os.path.join(b.allocator, b.cache_root, "test.o");
493493
494 var zig_args = List([]const u8).init(b.allocator);494 var zig_args = List([]const u8).init(b.allocator);
495 %%zig_args.append(if (self.case.is_exe) "build_exe" else "build_obj");495 %%zig_args.append(if (self.case.is_exe) "build_exe" else "build_obj");
...@@ -511,7 +511,7 @@ pub const CompileErrorContext = struct {...@@ -511,7 +511,7 @@ pub const CompileErrorContext = struct {
511 printInvocation(b.zig_exe, zig_args.toSliceConst());511 printInvocation(b.zig_exe, zig_args.toSliceConst());
512 }512 }
513513
514 var child = os.ChildProcess.spawn(b.zig_exe, zig_args.toSliceConst(), &b.env_map,514 var child = os.ChildProcess.spawn(b.zig_exe, zig_args.toSliceConst(), null, &b.env_map,
515 StdIo.Ignore, StdIo.Pipe, StdIo.Pipe, b.allocator) %% |err|515 StdIo.Ignore, StdIo.Pipe, StdIo.Pipe, b.allocator) %% |err|
516 {516 {
517 debug.panic("Unable to spawn {}: {}\n", b.zig_exe, @errorName(err));517 debug.panic("Unable to spawn {}: {}\n", b.zig_exe, @errorName(err));
...@@ -632,7 +632,7 @@ pub const CompileErrorContext = struct {...@@ -632,7 +632,7 @@ pub const CompileErrorContext = struct {
632 self.step.dependOn(&compile_and_cmp_errors.step);632 self.step.dependOn(&compile_and_cmp_errors.step);
633633
634 for (case.sources.toSliceConst()) |src_file| {634 for (case.sources.toSliceConst()) |src_file| {
635 const expanded_src_path = %%os.path.join(b.allocator, "test_artifacts", src_file.filename);635 const expanded_src_path = %%os.path.join(b.allocator, b.cache_root, src_file.filename);
636 const write_src = b.addWriteFile(expanded_src_path, src_file.source);636 const write_src = b.addWriteFile(expanded_src_path, src_file.source);
637 compile_and_cmp_errors.step.dependOn(&write_src.step);637 compile_and_cmp_errors.step.dependOn(&write_src.step);
638 }638 }
...@@ -675,7 +675,7 @@ pub const BuildExamplesContext = struct {...@@ -675,7 +675,7 @@ pub const BuildExamplesContext = struct {
675 %%zig_args.append("--verbose");675 %%zig_args.append("--verbose");
676 }676 }
677677
678 const run_cmd = b.addCommand(b.cache_root, b.env_map, b.zig_exe, zig_args.toSliceConst());678 const run_cmd = b.addCommand(null, b.env_map, b.zig_exe, zig_args.toSliceConst());
679679
680 const log_step = b.addLog("PASS {}\n", annotated_case_name);680 const log_step = b.addLog("PASS {}\n", annotated_case_name);
681 log_step.step.dependOn(&run_cmd.step);681 log_step.step.dependOn(&run_cmd.step);
...@@ -762,7 +762,7 @@ pub const ParseHContext = struct {...@@ -762,7 +762,7 @@ pub const ParseHContext = struct {
762 const self = @fieldParentPtr(ParseHCmpOutputStep, "step", step);762 const self = @fieldParentPtr(ParseHCmpOutputStep, "step", step);
763 const b = self.context.b;763 const b = self.context.b;
764764
765 const root_src = %%os.path.join(b.allocator, "test_artifacts", self.case.sources.items[0].filename);765 const root_src = %%os.path.join(b.allocator, b.cache_root, self.case.sources.items[0].filename);
766766
767 var zig_args = List([]const u8).init(b.allocator);767 var zig_args = List([]const u8).init(b.allocator);
768 %%zig_args.append("parseh");768 %%zig_args.append("parseh");
...@@ -774,7 +774,7 @@ pub const ParseHContext = struct {...@@ -774,7 +774,7 @@ pub const ParseHContext = struct {
774 printInvocation(b.zig_exe, zig_args.toSliceConst());774 printInvocation(b.zig_exe, zig_args.toSliceConst());
775 }775 }
776776
777 var child = os.ChildProcess.spawn(b.zig_exe, zig_args.toSliceConst(), &b.env_map,777 var child = os.ChildProcess.spawn(b.zig_exe, zig_args.toSliceConst(), null, &b.env_map,
778 StdIo.Ignore, StdIo.Pipe, StdIo.Pipe, b.allocator) %% |err|778 StdIo.Ignore, StdIo.Pipe, StdIo.Pipe, b.allocator) %% |err|
779 {779 {
780 debug.panic("Unable to spawn {}: {}\n", b.zig_exe, @errorName(err));780 debug.panic("Unable to spawn {}: {}\n", b.zig_exe, @errorName(err));
...@@ -886,7 +886,7 @@ pub const ParseHContext = struct {...@@ -886,7 +886,7 @@ pub const ParseHContext = struct {
886 self.step.dependOn(&parseh_and_cmp.step);886 self.step.dependOn(&parseh_and_cmp.step);
887887
888 for (case.sources.toSliceConst()) |src_file| {888 for (case.sources.toSliceConst()) |src_file| {
889 const expanded_src_path = %%os.path.join(b.allocator, "test_artifacts", src_file.filename);889 const expanded_src_path = %%os.path.join(b.allocator, b.cache_root, src_file.filename);
890 const write_src = b.addWriteFile(expanded_src_path, src_file.source);890 const write_src = b.addWriteFile(expanded_src_path, src_file.source);
891 parseh_and_cmp.step.dependOn(&write_src.step);891 parseh_and_cmp.step.dependOn(&write_src.step);
892 }892 }