From 67b4de33d2729fdb21337e5a0e05f6273bce23ba Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 2 Mar 2019 10:38:27 -0500 Subject: [PATCH] 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) --- CMakeLists.txt | 2 +- src/analyze.cpp | 3 ++ src/codegen.cpp | 37 ++++++++++++++----- src/codegen.hpp | 4 +- src/ir.cpp | 12 ++++++ src/link.cpp | 2 +- src/main.cpp | 21 ++++++----- std/build.zig | 11 ++++++ std/special/bootstrap.zig | 2 +- .../bootstrap_windows_tls.zig} | 4 +- std/special/builtin.zig | 2 +- test/build_examples.zig | 1 + test/compile_errors.zig | 9 +++++ test/standalone/main_pkg_path/a/test.zig | 5 +++ test/standalone/main_pkg_path/b.zig | 1 + test/standalone/main_pkg_path/build.zig | 9 +++++ 16 files changed, 99 insertions(+), 26 deletions(-) rename std/{os/windows/tls.zig => special/bootstrap_windows_tls.zig} (96%) create mode 100644 test/standalone/main_pkg_path/a/test.zig create mode 100644 test/standalone/main_pkg_path/b.zig create mode 100644 test/standalone/main_pkg_path/build.zig diff --git a/CMakeLists.txt b/CMakeLists.txt index 830a3456cf..f2d9f392ef 100644 --- a/CMakeLists.txt +++ b/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" diff --git a/src/analyze.cpp b/src/analyze.cpp index 089f72483f..30e147c62d 100644 --- a/src/analyze.cpp +++ b/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) { diff --git a/src/codegen.cpp b/src/codegen.cpp index 650cbee946..77832e215d 100644 --- a/src/codegen.cpp +++ b/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(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); + 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_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 { diff --git a/src/codegen.hpp b/src/codegen.hpp index eb30eeb9a7..91598fa7be 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -15,8 +15,8 @@ #include -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); diff --git a/src/ir.cpp b/src/ir.cpp index 7c45a9d588..2452011d79 100644 --- a/src/ir.cpp +++ b/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, diff --git a/src/link.cpp b/src/link.cpp index 7eb8cb111f..2e30dc6230 100644 --- a/src/link.cpp +++ b/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); diff --git a/src/main.cpp b/src/main.cpp index 966d7d59d7..9078059dc5 100644 --- a/src/main.cpp +++ b/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) { diff --git a/std/build.zig b/std/build.zig index e3fdfbccee..b7f76a53af 100644 --- a/std/build.zig +++ b/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()) { diff --git a/std/special/bootstrap.zig b/std/special/bootstrap.zig index 950fd5cbb9..04b29d6709 100644 --- a/std/special/bootstrap.zig +++ b/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()); } diff --git a/std/os/windows/tls.zig b/std/special/bootstrap_windows_tls.zig similarity index 96% rename from std/os/windows/tls.zig rename to std/special/bootstrap_windows_tls.zig index 9e62a7c5c6..71165d355b 100644 --- a/std/os/windows/tls.zig +++ b/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, diff --git a/std/special/builtin.zig b/std/special/builtin.zig index ad50eecc27..38c1493ba2 100644 --- a/std/special/builtin.zig +++ b/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); diff --git a/test/build_examples.zig b/test/build_examples.zig index c8a47bb093..3931648f19 100644 --- a/test/build_examples.zig +++ b/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) { diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 3f82f2d223..92df4d2d14 100644 --- a/test/compile_errors.zig +++ b/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; diff --git a/test/standalone/main_pkg_path/a/test.zig b/test/standalone/main_pkg_path/a/test.zig new file mode 100644 index 0000000000..286489912b --- /dev/null +++ b/test/standalone/main_pkg_path/a/test.zig @@ -0,0 +1,5 @@ +const b = @import("../b.zig"); + +test "main pkg path" { + b.foo(); +} diff --git a/test/standalone/main_pkg_path/b.zig b/test/standalone/main_pkg_path/b.zig new file mode 100644 index 0000000000..87d61fa63e --- /dev/null +++ b/test/standalone/main_pkg_path/b.zig @@ -0,0 +1 @@ +pub fn foo() void {} diff --git a/test/standalone/main_pkg_path/build.zig b/test/standalone/main_pkg_path/build.zig new file mode 100644 index 0000000000..c4ac18f967 --- /dev/null +++ b/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); +}