Commit 67b4de33d2

Andrew Kelley <andrew@ziglang.org>
2019-03-02 16:38:27
compile error for import outside package path
closes #2024 there's a new cli option `--main-pkg-path` which you can use to choose a different root package directory besides the one inferred from the root source file and a corresponding build.zig API: foo.setMainPkgPath(path)
1 parent 764205a
src/analyze.cpp
@@ -4502,6 +4502,9 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu
 
     Buf *pkg_root_src_dir = &package->root_src_dir;
     Buf resolved_root_src_dir = os_path_resolve(&pkg_root_src_dir, 1);
+
+    assert(buf_starts_with_buf(resolved_path, &resolved_root_src_dir));
+
     Buf namespace_name = BUF_INIT;
     buf_init_from_buf(&namespace_name, &package->pkg_path);
     if (source_kind == SourceKindNonRoot) {
src/codegen.cpp
@@ -88,8 +88,8 @@ static const char *symbols_that_llvm_depends_on[] = {
     // TODO probably all of compiler-rt needs to go here
 };
 
-CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode,
-    Buf *zig_lib_dir, Buf *override_std_dir, ZigLibCInstallation *libc)
+CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target,
+    OutType out_type, BuildMode build_mode, Buf *zig_lib_dir, Buf *override_std_dir, ZigLibCInstallation *libc)
 {
     CodeGen *g = allocate<CodeGen>(1);
 
@@ -133,16 +133,35 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
     }
 
     if (root_src_path) {
-        Buf *src_basename = buf_alloc();
-        Buf *src_dir = buf_alloc();
-        os_path_split(root_src_path, src_dir, src_basename);
+        Buf *root_pkg_path;
+        Buf *rel_root_src_path;
+        if (main_pkg_path == nullptr) {
+            Buf *src_basename = buf_alloc();
+            Buf *src_dir = buf_alloc();
+            os_path_split(root_src_path, src_dir, src_basename);
+
+            if (buf_len(src_basename) == 0) {
+                fprintf(stderr, "Invalid root source path: %s\n", buf_ptr(root_src_path));
+                exit(1);
+            }
+            root_pkg_path = src_dir;
+            rel_root_src_path = src_basename;
+        } else {
+            Buf resolved_root_src_path = os_path_resolve(&root_src_path, 1);
+            Buf resolved_main_pkg_path = os_path_resolve(&main_pkg_path, 1);
 
-        if (buf_len(src_basename) == 0) {
-            fprintf(stderr, "Invalid root source path: %s\n", buf_ptr(root_src_path));
-            exit(1);
+            if (!buf_starts_with_buf(&resolved_root_src_path, &resolved_main_pkg_path)) {
+                fprintf(stderr, "Root source path '%s' outside main package path '%s'",
+                        buf_ptr(root_src_path), buf_ptr(main_pkg_path));
+                exit(1);
+            }
+            root_pkg_path = main_pkg_path;
+            rel_root_src_path = buf_create_from_mem(
+                    buf_ptr(&resolved_root_src_path) + buf_len(&resolved_main_pkg_path) + 1,
+                    buf_len(&resolved_root_src_path) - buf_len(&resolved_main_pkg_path) - 1);
         }
 
-        g->root_package = new_package(buf_ptr(src_dir), buf_ptr(src_basename), "");
+        g->root_package = new_package(buf_ptr(root_pkg_path), buf_ptr(rel_root_src_path), "");
         g->std_package = new_package(buf_ptr(g->zig_std_dir), "index.zig", "std");
         g->root_package->package_table.put(buf_create_from_str("std"), g->std_package);
     } else {
src/codegen.hpp
@@ -15,8 +15,8 @@
 
 #include <stdio.h>
 
-CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode,
-    Buf *zig_lib_dir, Buf *override_std_dir, ZigLibCInstallation *libc);
+CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target,
+    OutType out_type, BuildMode build_mode, Buf *zig_lib_dir, Buf *override_std_dir, ZigLibCInstallation *libc);
 
 void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
 void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len);
src/ir.cpp
@@ -17026,6 +17026,18 @@ static IrInstruction *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructio
         return ir_const_type(ira, &import_instruction->base, import_entry->value);
     }
 
+    if (source_kind == SourceKindNonRoot) {
+        ZigPackage *cur_scope_pkg = scope_package(import_instruction->base.scope);
+        Buf *pkg_root_src_dir = &cur_scope_pkg->root_src_dir;
+        Buf resolved_root_src_dir = os_path_resolve(&pkg_root_src_dir, 1);
+        if (!buf_starts_with_buf(resolved_path, &resolved_root_src_dir)) {
+            ir_add_error_node(ira, source_node,
+                    buf_sprintf("import of file outside package path: '%s'",
+                        buf_ptr(import_target_path)));
+            return ira->codegen->invalid_instruction;
+        }
+    }
+
     if ((err = file_fetch(ira->codegen, resolved_path, import_code))) {
         if (err == ErrorFileNotFound) {
             ir_add_error_node(ira, source_node,
src/link.cpp
@@ -41,7 +41,7 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path)
         child_out_type = OutTypeObj;
     }
 
-    CodeGen *child_gen = codegen_create(full_path, parent_gen->zig_target, child_out_type,
+    CodeGen *child_gen = codegen_create(nullptr, full_path, parent_gen->zig_target, child_out_type,
         parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir,
         parent_gen->libc);
 
src/main.cpp
@@ -63,6 +63,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
         "  --output-lib [file]          override import library path\n"
         "  --pkg-begin [name] [path]    make pkg available to import and push current pkg\n"
         "  --pkg-end                    pop current pkg\n"
+        "  --main-pkg-path              set the directory of the root package\n"
         "  --release-fast               build with optimizations on and safety off\n"
         "  --release-safe               build with optimizations on and safety on\n"
         "  --release-small              build with size optimizations on and safety off\n"
@@ -438,6 +439,7 @@ int main(int argc, char **argv) {
     TargetSubsystem subsystem = TargetSubsystemAuto;
     bool is_single_threaded = false;
     Buf *override_std_dir = nullptr;
+    Buf *main_pkg_path = nullptr;
     ValgrindSupport valgrind_support = ValgrindSupportAuto;
 
     if (argc >= 2 && strcmp(argv[1], "build") == 0) {
@@ -476,8 +478,8 @@ int main(int argc, char **argv) {
 
         ZigTarget target;
         get_native_target(&target);
-        CodeGen *g = codegen_create(build_runner_path, &target, OutTypeExe, BuildModeDebug, get_zig_lib_dir(),
-                override_std_dir, nullptr);
+        CodeGen *g = codegen_create(main_pkg_path, build_runner_path, &target, OutTypeExe,
+                BuildModeDebug, get_zig_lib_dir(), override_std_dir, nullptr);
         g->valgrind_support = valgrind_support;
         g->enable_time_report = timing_info;
         buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);
@@ -567,8 +569,8 @@ int main(int argc, char **argv) {
         get_native_target(&target);
         Buf *fmt_runner_path = buf_alloc();
         os_path_join(get_zig_special_dir(), buf_create_from_str("fmt_runner.zig"), fmt_runner_path);
-        CodeGen *g = codegen_create(fmt_runner_path, &target, OutTypeExe, BuildModeDebug, get_zig_lib_dir(),
-                nullptr, nullptr);
+        CodeGen *g = codegen_create(main_pkg_path, fmt_runner_path, &target, OutTypeExe,
+                BuildModeDebug, get_zig_lib_dir(), nullptr, nullptr);
         buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);
         g->valgrind_support = valgrind_support;
         g->is_single_threaded = true;
@@ -729,6 +731,8 @@ int main(int argc, char **argv) {
                     llvm_argv.append(argv[i]);
                 } else if (strcmp(arg, "--override-std-dir") == 0) {
                     override_std_dir = buf_create_from_str(argv[i]);
+                } else if (strcmp(arg, "--main-pkg-path") == 0) {
+                    main_pkg_path = buf_create_from_str(argv[i]);
                 } else if (strcmp(arg, "--library-path") == 0 || strcmp(arg, "-L") == 0) {
                     lib_dirs.append(argv[i]);
                 } else if (strcmp(arg, "--library") == 0) {
@@ -908,8 +912,8 @@ int main(int argc, char **argv) {
         return EXIT_SUCCESS;
     }
     case CmdBuiltin: {
-        CodeGen *g = codegen_create(nullptr, &target, out_type, build_mode, get_zig_lib_dir(), override_std_dir,
-                nullptr);
+        CodeGen *g = codegen_create(main_pkg_path, nullptr, &target,
+                out_type, build_mode, get_zig_lib_dir(), override_std_dir, nullptr);
         g->valgrind_support = valgrind_support;
         g->is_single_threaded = is_single_threaded;
         Buf *builtin_source = codegen_generate_builtin_source(g);
@@ -1012,8 +1016,8 @@ int main(int argc, char **argv) {
                     return EXIT_FAILURE;
                 }
             }
-            CodeGen *g = codegen_create(zig_root_source_file, &target, out_type, build_mode, get_zig_lib_dir(),
-                    override_std_dir, libc);
+            CodeGen *g = codegen_create(main_pkg_path, zig_root_source_file, &target, out_type, build_mode,
+                    get_zig_lib_dir(), override_std_dir, libc);
             g->valgrind_support = valgrind_support;
             g->subsystem = subsystem;
 
@@ -1096,7 +1100,6 @@ int main(int argc, char **argv) {
             if (out_file_lib != nullptr && out_type == OutTypeLib && !is_static)
                 codegen_set_output_lib_path(g, buf_create_from_str(out_file_lib));
 
-
             add_package(g, cur_pkg, g->root_package);
 
             if (cmd == CmdBuild || cmd == CmdRun || cmd == CmdTest) {
std/special/bootstrap.zig
@@ -46,7 +46,7 @@ nakedcc fn _start() noreturn {
 extern fn WinMainCRTStartup() noreturn {
     @setAlignStack(16);
     if (!builtin.single_threaded) {
-        _ = @import("../os/windows/tls.zig");
+        _ = @import("bootstrap_windows_tls.zig");
     }
     std.os.windows.ExitProcess(callMain());
 }
std/os/windows/tls.zig → std/special/bootstrap_windows_tls.zig
@@ -1,4 +1,4 @@
-const std = @import("../../index.zig");
+const std = @import("std");
 
 export var _tls_index: u32 = std.os.windows.TLS_OUT_OF_INDEXES;
 export var _tls_start: u8 linksection(".tls") = 0;
@@ -26,7 +26,7 @@ pub const IMAGE_TLS_DIRECTORY = extern struct {
     SizeOfZeroFill: u32,
     Characteristics: u32,
 };
-export const _tls_used linksection(".rdata$T") = IMAGE_TLS_DIRECTORY {
+export const _tls_used linksection(".rdata$T") = IMAGE_TLS_DIRECTORY{
     .StartAddressOfRawData = &_tls_start,
     .EndAddressOfRawData = &_tls_end,
     .AddressOfIndex = &_tls_index,
std/special/builtin.zig
@@ -134,7 +134,7 @@ nakedcc fn clone() void {
     }
 }
 
-const math = @import("../math/index.zig");
+const math = std.math;
 
 export fn fmodf(x: f32, y: f32) f32 {
     return generic_fmod(f32, x, y);
std/build.zig
@@ -859,6 +859,7 @@ pub const LibExeObjStep = struct {
     verbose_cc: bool,
     c_std: Builder.CStd,
     override_std_dir: ?[]const u8,
+    main_pkg_path: ?[]const u8,
     exec_cmd_args: ?[]const ?[]const u8,
     name_prefix: []const u8,
     filter: ?[]const u8,
@@ -950,6 +951,7 @@ pub const LibExeObjStep = struct {
             .c_std = Builder.CStd.C99,
             .system_linker_hack = false,
             .override_std_dir = null,
+            .main_pkg_path = null,
             .exec_cmd_args = null,
             .name_prefix = "",
             .filter = null,
@@ -1098,6 +1100,10 @@ pub const LibExeObjStep = struct {
         self.override_std_dir = dir_path;
     }
 
+    pub fn setMainPkgPath(self: *LibExeObjStep, dir_path: []const u8) void {
+        self.main_pkg_path = dir_path;
+    }
+
     pub fn setOutputPath(self: *LibExeObjStep, file_path: []const u8) void {
         self.output_path = file_path;
 
@@ -1424,6 +1430,11 @@ pub const LibExeObjStep = struct {
             try zig_args.append(builder.pathFromRoot(dir));
         }
 
+        if (self.main_pkg_path) |dir| {
+            try zig_args.append("--main-pkg-path");
+            try zig_args.append(builder.pathFromRoot(dir));
+        }
+
         try builder.spawnChild(zig_args.toSliceConst());
 
         if (self.kind == Kind.Lib and !self.static and self.target.wantSharedLibSymLinks()) {
test/standalone/main_pkg_path/a/test.zig
@@ -0,0 +1,5 @@
+const b = @import("../b.zig");
+
+test "main pkg path" {
+    b.foo();
+}
test/standalone/main_pkg_path/b.zig
@@ -0,0 +1,1 @@
+pub fn foo() void {}
test/standalone/main_pkg_path/build.zig
@@ -0,0 +1,9 @@
+const Builder = @import("std").build.Builder;
+
+pub fn build(b: *Builder) void {
+    const test_exe = b.addTest("a/test.zig");
+    test_exe.setMainPkgPath(".");
+
+    const test_step = b.step("test", "Test the program");
+    test_step.dependOn(&test_exe.step);
+}
test/build_examples.zig
@@ -7,6 +7,7 @@ pub fn addCases(cases: *tests.BuildExamplesContext) void {
     cases.addC("example/hello_world/hello_libc.zig");
     cases.add("example/cat/main.zig");
     cases.add("example/guess_number/main.zig");
+    cases.addBuildFile("test/standalone/main_pkg_path/build.zig");
     cases.addBuildFile("example/shared_library/build.zig");
     cases.addBuildFile("example/mix_o_files/build.zig");
     if (builtin.os != builtin.Os.macosx) {
test/compile_errors.zig
@@ -2,6 +2,15 @@ const tests = @import("tests.zig");
 const builtin = @import("builtin");
 
 pub fn addCases(cases: *tests.CompileErrorContext) void {
+    cases.add(
+        "import outside package path",
+        \\comptime{
+        \\    _ = @import("../a.zig");
+        \\}
+    ,
+        "tmp.zig:2:9: error: import of file outside package path: '../a.zig'",
+    );
+
     cases.add(
         "bogus compile var",
         \\const x = @import("builtin").bogus;
CMakeLists.txt
@@ -606,7 +606,6 @@ set(ZIG_STD_FILES
     "os/windows/ntdll.zig"
     "os/windows/ole32.zig"
     "os/windows/shell32.zig"
-    "os/windows/tls.zig"
     "os/windows/util.zig"
     "os/zen.zig"
     "pdb.zig"
@@ -617,6 +616,7 @@ set(ZIG_STD_FILES
     "sort.zig"
     "special/bootstrap.zig"
     "special/bootstrap_lib.zig"
+    "special/bootstrap_windows_tls.zig"
     "special/build_runner.zig"
     "special/builtin.zig"
     "special/compiler_rt/addXf3.zig"