Commit 3cbd0065fa

Andrew Kelley <superjoe30@gmail.com>
2017-05-01 22:35:10
basic support for specifying packages at the command line
See #226
1 parent 17b9353
Changed files (7)
src/main.cpp
@@ -36,6 +36,8 @@ static int usage(const char *arg0) {
         "  --name [name]                override output name\n"
         "  --output [file]              override destination path\n"
         "  --output-h [file]            override generated header file path\n"
+        "  --pkg-begin [name] [path]    make package available to import and push current pkg\n"
+        "  --pkg-end                    pop current pkg\n"
         "  --release                    build with optimizations on and debug protection off\n"
         "  --static                     output will be statically linked\n"
         "  --strip                      exclude debug symbols\n"
@@ -121,6 +123,36 @@ enum Cmd {
 
 static const char *default_zig_cache_name = "zig-cache";
 
+struct CliPkg {
+    const char *name;
+    const char *path;
+    ZigList<CliPkg *> children;
+    CliPkg *parent;
+};
+
+static void add_package(CodeGen *g, CliPkg *cli_pkg, PackageTableEntry *pkg) {
+    for (size_t i = 0; i < cli_pkg->children.length; i += 1) {
+        CliPkg *child_cli_pkg = cli_pkg->children.at(i);
+
+        Buf *dirname = buf_alloc();
+        Buf *basename = buf_alloc();
+        os_path_split(buf_create_from_str(child_cli_pkg->path), dirname, basename);
+
+        PackageTableEntry *child_pkg = codegen_create_package(g, buf_ptr(dirname), buf_ptr(basename));
+        auto entry = pkg->package_table.put_unique(buf_create_from_str(child_cli_pkg->name), child_pkg);
+        if (entry) {
+            PackageTableEntry *existing_pkg = entry->value;
+            Buf *full_path = buf_alloc();
+            os_path_join(&existing_pkg->root_src_dir, &existing_pkg->root_src_path, full_path);
+            fprintf(stderr, "Unable to add package '%s'->'%s': already exists as '%s'\n",
+                    child_cli_pkg->name, child_cli_pkg->path, buf_ptr(full_path));
+            exit(EXIT_FAILURE);
+        }
+
+        add_package(g, child_cli_pkg, child_pkg);
+    }
+}
+
 int main(int argc, char **argv) {
     os_init();
 
@@ -168,6 +200,7 @@ int main(int argc, char **argv) {
     size_t ver_patch = 0;
     bool timing_info = false;
     const char *cache_dir = nullptr;
+    CliPkg *cur_pkg = allocate<CliPkg>(1);
 
     if (argc >= 2 && strcmp(argv[1], "build") == 0) {
         const char *zig_exe_path = arg0;
@@ -309,13 +342,31 @@ int main(int argc, char **argv) {
             } else if (arg[1] == 'L' && arg[2] != 0) {
                 // alias for --library-path
                 lib_dirs.append(&arg[2]);
+            } else if (strcmp(arg, "--pkg-begin") == 0) {
+                if (i + 2 >= argc) {
+                    fprintf(stderr, "Expected 2 arguments after --pkg-begin\n");
+                    return usage(arg0);
+                }
+                CliPkg *new_cur_pkg = allocate<CliPkg>(1);
+                i += 1;
+                new_cur_pkg->name = argv[i];
+                i += 1;
+                new_cur_pkg->path = argv[i];
+                new_cur_pkg->parent = cur_pkg;
+                cur_pkg->children.append(new_cur_pkg);
+                cur_pkg = new_cur_pkg;
+            } else if (strcmp(arg, "--pkg-end") == 0) {
+                if (cur_pkg->parent == nullptr) {
+                    fprintf(stderr, "Encountered --pkg-end with no matching --pkg-begin\n");
+                    return EXIT_FAILURE;
+                }
+                cur_pkg = cur_pkg->parent;
             } else if (i + 1 >= argc) {
+                fprintf(stderr, "Expected another argument after %s\n", arg);
                 return usage(arg0);
             } else {
                 i += 1;
-                if (i >= argc) {
-                    return usage(arg0);
-                } else if (strcmp(arg, "--output") == 0) {
+                if (strcmp(arg, "--output") == 0) {
                     out_file = argv[i];
                 } else if (strcmp(arg, "--output-h") == 0) {
                     out_file_h = argv[i];
@@ -327,6 +378,7 @@ int main(int argc, char **argv) {
                     } else if (strcmp(argv[i], "off") == 0) {
                         color = ErrColorOff;
                     } else {
+                        fprintf(stderr, "--color options are 'auto', 'on', or 'off'\n");
                         return usage(arg0);
                     }
                 } else if (strcmp(arg, "--name") == 0) {
@@ -421,11 +473,13 @@ int main(int argc, char **argv) {
                     if (!in_file) {
                         in_file = arg;
                     } else {
+                        fprintf(stderr, "Unexpected extra parameter: %s\n", arg);
                         return usage(arg0);
                     }
                     break;
                 case CmdVersion:
                 case CmdTargets:
+                    fprintf(stderr, "Unexpected extra parameter: %s\n", arg);
                     return usage(arg0);
                 case CmdInvalid:
                     zig_unreachable();
@@ -433,6 +487,11 @@ int main(int argc, char **argv) {
         }
     }
 
+    if (cur_pkg->parent != nullptr) {
+        fprintf(stderr, "Unmatched --pkg-begin\n");
+        return EXIT_FAILURE;
+    }
+
     switch (cmd) {
     case CmdBuild:
     case CmdParseH:
@@ -579,6 +638,9 @@ int main(int argc, char **argv) {
             if (out_file_h)
                 codegen_set_output_h_path(g, buf_create_from_str(out_file_h));
 
+
+            add_package(g, cur_pkg, g->root_package);
+
             if (cmd == CmdBuild) {
                 for (size_t i = 0; i < objects.length; i += 1) {
                     codegen_add_object(g, buf_create_from_str(objects.at(i)));
std/build.zig
@@ -679,6 +679,12 @@ pub const LibExeObjStep = struct {
     name_only_filename: []const u8,
     object_files: List([]const u8),
     assembly_files: List([]const u8),
+    packages: List(Pkg),
+
+    const Pkg = struct {
+        name: []const u8,
+        path: []const u8,
+    };
 
     const Kind = enum {
         Exe,
@@ -736,6 +742,7 @@ pub const LibExeObjStep = struct {
             .name_only_filename = undefined,
             .object_files = List([]const u8).init(builder.allocator),
             .assembly_files = List([]const u8).init(builder.allocator),
+            .packages = List(Pkg).init(builder.allocator),
         };
         self.computeOutFileNames();
         return self;
@@ -835,6 +842,13 @@ pub const LibExeObjStep = struct {
         %%self.object_files.append(obj.getOutputPath());
     }
 
+    pub fn addPackagePath(self: &LibExeObjStep, name: []const u8, pkg_index_path: []const u8) {
+        %%self.packages.append(Pkg {
+            .name = name,
+            .path = pkg_index_path,
+        });
+    }
+
     fn make(step: &Step) -> %void {
         const self = @fieldParentPtr(LibExeObjStep, "step", step);
         const builder = self.builder;
@@ -883,9 +897,11 @@ pub const LibExeObjStep = struct {
         %%zig_args.append("--output");
         %%zig_args.append(output_path);
 
-        const output_h_path = self.getOutputHPath();
-        %%zig_args.append("--output-h");
-        %%zig_args.append(builder.pathFromRoot(output_h_path));
+        if (self.kind != Kind.Exe) {
+            const output_h_path = self.getOutputHPath();
+            %%zig_args.append("--output-h");
+            %%zig_args.append(builder.pathFromRoot(output_h_path));
+        }
 
         %%zig_args.append("--name");
         %%zig_args.append(self.name);
@@ -929,6 +945,13 @@ pub const LibExeObjStep = struct {
             }
         }
 
+        for (self.packages.toSliceConst()) |pkg| {
+            %%zig_args.append("--pkg-begin");
+            %%zig_args.append(pkg.name);
+            %%zig_args.append(builder.pathFromRoot(pkg.path));
+            %%zig_args.append("--pkg-end");
+        }
+
         for (builder.include_paths.toSliceConst()) |include_path| {
             %%zig_args.append("-isystem");
             %%zig_args.append(include_path);
test/standalone/pkg_import/build.zig
@@ -0,0 +1,12 @@
+const Builder = @import("std").build.Builder;
+
+pub fn build(b: &Builder) {
+    const exe = b.addExecutable("test", "test.zig");
+    exe.addPackagePath("my_pkg", "pkg.zig");
+
+    const run = b.addCommand(".", b.env_map, exe.getOutputPath(), [][]const u8{});
+    run.step.dependOn(&exe.step);
+
+    const test_step = b.step("test", "Test it");
+    test_step.dependOn(&run.step);
+}
test/standalone/pkg_import/pkg.zig
@@ -0,0 +1,1 @@
+pub fn add(a: i32, b: i32) -> i32 { a + b }
test/standalone/pkg_import/test.zig
@@ -0,0 +1,6 @@
+const my_pkg = @import("my_pkg");
+const assert = @import("std").debug.assert;
+
+pub fn main() -> %void {
+    assert(my_pkg.add(10, 20) == 30);
+}
test/build_examples.zig
@@ -8,4 +8,5 @@ pub fn addCases(cases: &tests.BuildExamplesContext) {
     cases.addBuildFile("example/shared_library/build.zig");
     cases.addBuildFile("example/mix_o_files/build.zig");
     cases.addBuildFile("test/standalone/issue_339/build.zig");
+    cases.addBuildFile("test/standalone/pkg_import/build.zig");
 }
test/tests.zig
@@ -657,7 +657,7 @@ pub const BuildExamplesContext = struct {
     pub fn addBuildFile(self: &BuildExamplesContext, build_file: []const u8) {
         const b = self.b;
 
-        const annotated_case_name = b.fmt("build {}", build_file);
+        const annotated_case_name = b.fmt("build {} (debug)", build_file);
         test (self.test_filter) |filter| {
             if (mem.indexOf(u8, annotated_case_name, filter) == null)
                 return;