Commit 72800f176e

Andrew Kelley <andrew@ziglang.org>
2019-07-04 23:43:56
zig build: search upwards for build.zig file
closes #2587
1 parent 47addd8
src/main.cpp
@@ -261,6 +261,15 @@ static bool get_cache_opt(CacheOpt opt, bool default_value) {
     zig_unreachable();
 }
 
+static int zig_error_no_build_file(void) {
+    fprintf(stderr,
+        "No 'build.zig' file found, in the current directory or any parent directories.\n"
+        "Initialize a 'build.zig' template file with `zig init-lib` or `zig init-exe`,\n"
+        "or see `zig --help` for more options.\n"
+    );
+    return EXIT_FAILURE;
+}
+
 extern "C" int ZigClang_main(int argc, char **argv);
 
 int main(int argc, char **argv) {
@@ -466,8 +475,7 @@ int main(int argc, char **argv) {
             return EXIT_FAILURE;
         }
         const char *zig_exe_path = buf_ptr(&zig_exe_path_buf);
-        const char *build_file = "build.zig";
-        bool asked_for_help = false;
+        const char *build_file = nullptr;
 
         init_all_targets();
 
@@ -478,7 +486,6 @@ int main(int argc, char **argv) {
         args.append(NULL); // placeholder
         for (int i = 2; i < argc; i += 1) {
             if (strcmp(argv[i], "--help") == 0) {
-                asked_for_help = true;
                 args.append(argv[i]);
             } else if (i + 1 < argc && strcmp(argv[i], "--build-file") == 0) {
                 build_file = argv[i + 1];
@@ -511,12 +518,36 @@ int main(int argc, char **argv) {
         ZigTarget target;
         get_native_target(&target);
 
-        Buf *build_file_buf = buf_create_from_str(build_file);
+        Buf *build_file_buf = buf_create_from_str((build_file != nullptr) ? build_file : "build.zig");
         Buf build_file_abs = os_path_resolve(&build_file_buf, 1);
         Buf build_file_basename = BUF_INIT;
         Buf build_file_dirname = BUF_INIT;
         os_path_split(&build_file_abs, &build_file_dirname, &build_file_basename);
 
+        for (;;) {
+            bool build_file_exists;
+            if ((err = os_file_exists(&build_file_abs, &build_file_exists))) {
+                fprintf(stderr, "unable to check existence of '%s': %s\n", buf_ptr(&build_file_abs), err_str(err));
+                return 1;
+            }
+            if (build_file_exists)
+                break;
+
+            if (build_file != nullptr) {
+                // they asked for a specific build file path. only look for that one
+                return zig_error_no_build_file();
+            }
+
+            Buf *next_dir = buf_alloc();
+            os_path_dirname(&build_file_dirname, next_dir);
+            if (buf_eql_buf(&build_file_dirname, next_dir)) {
+                // no more parent directories to search, give up
+                return zig_error_no_build_file();
+            }
+            os_path_join(next_dir, &build_file_basename, &build_file_abs);
+            buf_init_from_buf(&build_file_dirname, next_dir);
+        }
+
         Buf full_cache_dir = BUF_INIT;
         if (cache_dir == nullptr) {
             os_path_join(&build_file_dirname, buf_create_from_str(default_zig_cache_name), &full_cache_dir);
@@ -534,51 +565,6 @@ int main(int argc, char **argv) {
         args.items[2] = buf_ptr(&build_file_dirname);
         args.items[3] = buf_ptr(&full_cache_dir);
 
-        bool build_file_exists;
-        if ((err = os_file_exists(&build_file_abs, &build_file_exists))) {
-            fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(&build_file_abs), err_str(err));
-            return 1;
-        }
-        if (!build_file_exists) {
-            if (asked_for_help) {
-                // This usage text has to be synchronized with std/special/build_runner.zig
-                fprintf(stdout,
-                        "Usage: %s build [options]\n"
-                        "\n"
-                        "General Options:\n"
-                        "  --help                   Print this help and exit\n"
-                        "  --verbose                Print commands before executing them\n"
-                        "  --prefix [path]          Override default install prefix\n"
-                        "  --search-prefix [path]   Add a path to look for binaries, libraries, headers\n"
-                        "\n"
-                        "Project-specific options become available when the build file is found.\n"
-                        "\n"
-                        "Advanced Options:\n"
-                        "  --build-file [file]      Override path to build.zig\n"
-                        "  --cache-dir [path]       Override path to cache directory\n"
-                        "  --override-std-dir [arg] Override path to Zig standard library\n"
-                        "  --override-lib-dir [arg] Override path to Zig lib library\n"
-                        "  --verbose-tokenize       Enable compiler debug output for tokenization\n"
-                        "  --verbose-ast            Enable compiler debug output for parsing into an AST\n"
-                        "  --verbose-link           Enable compiler debug output for linking\n"
-                        "  --verbose-ir             Enable compiler debug output for Zig IR\n"
-                        "  --verbose-llvm-ir        Enable compiler debug output for LLVM IR\n"
-                        "  --verbose-cimport        Enable compiler debug output for C imports\n"
-                        "  --verbose-cc             Enable compiler debug output for C compilation\n"
-                        "\n"
-                , zig_exe_path);
-                return EXIT_SUCCESS;
-            }
-
-            fprintf(stderr,
-                    "No 'build.zig' file found.\n"
-                    "Initialize a 'build.zig' template file with `zig init-lib` or `zig init-exe`,\n"
-                    "or build an executable directly with `zig build-exe $FILENAME.zig`.\n"
-                    "See: `zig build --help` or `zig --help` for more options.\n"
-                   );
-            return EXIT_FAILURE;
-        }
-
         ZigPackage *build_pkg = codegen_create_package(g, buf_ptr(&build_file_dirname),
                 buf_ptr(&build_file_basename), "std.special");
         g->root_package->package_table.put(buf_create_from_str("@build"), build_pkg);
std/special/build_runner.zig
@@ -154,7 +154,6 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {
         try runBuild(builder);
     }
 
-    // This usage text has to be synchronized with src/main.cpp
     try out_stream.print(
         \\Usage: {} build [steps] [options]
         \\
std/build.zig
@@ -477,7 +477,7 @@ pub const Builder = struct {
         }
         const description = self.fmt("create a release build ({})", @tagName(mode));
         self.is_release = self.option(bool, "release", description) orelse false;
-        self.release_mode = if (is_release) mode else builtin.Mode.Debug;
+        self.release_mode = if (self.is_release) mode else builtin.Mode.Debug;
     }
 
     /// If you call this without first calling `setPreferredReleaseMode` then it gives the build user
build.zig
@@ -11,6 +11,7 @@ const io = std.io;
 const fs = std.fs;
 
 pub fn build(b: *Builder) !void {
+    b.setPreferredReleaseMode(.ReleaseFast);
     const mode = b.standardReleaseOptions();
 
     var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig");
README.md
@@ -71,7 +71,7 @@ Dependencies are the same as Stage 1, except now you can use stage 1 to compile
 Zig code.
 
 ```
-bin/zig build --build-file ../build.zig --prefix $(pwd)/stage2 install
+bin/zig build --prefix $(pwd)/stage2
 ```
 
 This produces `./stage2/bin/zig` which can be used for testing and development.
@@ -90,11 +90,11 @@ use stage 1.
 #### Debug / Development Build
 
 ```
-./stage2/bin/zig build --build-file ../build.zig --prefix $(pwd)/stage3 install
+./stage2/bin/zig build --prefix $(pwd)/stage3
 ```
 
 #### Release / Install Build
 
 ```
-./stage2/bin/zig build --build-file ../build.zig install -Drelease-fast
+./stage2/bin/zig build install -Drelease
 ```