authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-08-27 17:16:42-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-08-27 17:16:42-04:00
logebdc6b594ddc0762ed9e41b5f36e6da5e03c19e0
treefcc648080b4684e96d1016a912c647d0c8e313cd
parent5fd579a51c44c31b99cf34d9e8ada3b7692b4c43

all tests passing in MacOS

depends on LLD 5.0.0 with 3 patches See #273

8 files changed, 131 insertions(+), 17 deletions(-)

ci/travis_osx_script+1-1
...@@ -12,4 +12,4 @@ cd build...@@ -12,4 +12,4 @@ cd build
12cmake .. -DCMAKE_PREFIX_PATH=$PREFIX_DIR -DCMAKE_INSTALL_PREFIX=$(pwd) -DZIG_LIBC_LIB_DIR=$(dirname $($CC -print-file-name=crt1.o)) -DZIG_LIBC_INCLUDE_DIR=$(echo -n | $CC -E -x c - -v 2>&1 | grep -B1 "End of search list." | head -n1 | cut -c 2- | sed "s/ .*//") -DZIG_LIBC_STATIC_LIB_DIR=$(dirname $($CC -print-file-name=crtbegin.o))12cmake .. -DCMAKE_PREFIX_PATH=$PREFIX_DIR -DCMAKE_INSTALL_PREFIX=$(pwd) -DZIG_LIBC_LIB_DIR=$(dirname $($CC -print-file-name=crt1.o)) -DZIG_LIBC_INCLUDE_DIR=$(echo -n | $CC -E -x c - -v 2>&1 | grep -B1 "End of search list." | head -n1 | cut -c 2- | sed "s/ .*//") -DZIG_LIBC_STATIC_LIB_DIR=$(dirname $($CC -print-file-name=crtbegin.o))
13make VERBOSE=113make VERBOSE=1
14make install14make install
15./zig build --build-file ../build.zig test-behavior test-std test-compiler-rt test-compare-output test-compile-errors test-asm-link test-debug-safety test-parseh15./zig build --build-file ../build.zig test
example/mix_o_files/test.c+1-1
...@@ -8,7 +8,7 @@ int main(int argc, char **argv) {...@@ -8,7 +8,7 @@ int main(int argc, char **argv) {
8 const char *encoded = "YWxsIHlvdXIgYmFzZSBhcmUgYmVsb25nIHRvIHVz";8 const char *encoded = "YWxsIHlvdXIgYmFzZSBhcmUgYmVsb25nIHRvIHVz";
9 char buf[200];9 char buf[200];
1010
11 size_t len = decode_base_64(buf, 200, encoded, strlen(encoded));11 size_t len = decode_base_64((uint8_t *)buf, 200, (uint8_t *)encoded, strlen(encoded));
12 buf[len] = 0;12 buf[len] = 0;
13 assert(strcmp(buf, "all your base are belong to us") == 0);13 assert(strcmp(buf, "all your base are belong to us") == 0);
1414
src/link.cpp+30-2
...@@ -634,7 +634,29 @@ static void construct_linker_job_macho(LinkJob *lj) {...@@ -634,7 +634,29 @@ static void construct_linker_job_macho(LinkJob *lj) {
634 }634 }
635635
636 if (is_lib) {636 if (is_lib) {
637 zig_panic("TODO linker args on darwin for making a library");637 if (!g->is_static) {
638 lj->args.append("-dylib");
639
640 Buf *compat_vers = buf_sprintf("%" ZIG_PRI_usize ".0.0", g->version_major);
641 lj->args.append("-compatibility_version");
642 lj->args.append(buf_ptr(compat_vers));
643
644 Buf *cur_vers = buf_sprintf("%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize,
645 g->version_major, g->version_minor, g->version_patch);
646 lj->args.append("-current_version");
647 lj->args.append(buf_ptr(cur_vers));
648
649 // TODO getting an error when running an executable when doing this rpath thing
650 //Buf *dylib_install_name = buf_sprintf("@rpath/lib%s.%" ZIG_PRI_usize ".dylib",
651 // buf_ptr(g->root_out_name), g->version_major);
652 //lj->args.append("-install_name");
653 //lj->args.append(buf_ptr(dylib_install_name));
654
655 if (buf_len(&lj->out_file) == 0) {
656 buf_appendf(&lj->out_file, "lib%s.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib",
657 buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch);
658 }
659 }
638 }660 }
639661
640 lj->args.append("-arch");662 lj->args.append("-arch");
...@@ -667,8 +689,14 @@ static void construct_linker_job_macho(LinkJob *lj) {...@@ -667,8 +689,14 @@ static void construct_linker_job_macho(LinkJob *lj) {
667 lj->args.append("-o");689 lj->args.append("-o");
668 lj->args.append(buf_ptr(&lj->out_file));690 lj->args.append(buf_ptr(&lj->out_file));
669691
692 for (size_t i = 0; i < g->rpath_list.length; i += 1) {
693 Buf *rpath = g->rpath_list.at(i);
694 add_rpath(lj, rpath);
695 }
696 add_rpath(lj, &lj->out_file);
697
670 if (shared) {698 if (shared) {
671 zig_panic("TODO");699 lj->args.append("-headerpad_max_install_names");
672 } else if (g->is_static) {700 } else if (g->is_static) {
673 lj->args.append("-lcrt0.o");701 lj->args.append("-lcrt0.o");
674 } else {702 } else {
std/build.zig+38-4
...@@ -784,10 +784,27 @@ pub const LibExeObjStep = struct {...@@ -784,10 +784,27 @@ pub const LibExeObjStep = struct {
784 if (self.static) {784 if (self.static) {
785 self.out_filename = self.builder.fmt("lib{}.a", self.name);785 self.out_filename = self.builder.fmt("lib{}.a", self.name);
786 } else {786 } else {
787 self.out_filename = self.builder.fmt("lib{}.so.{d}.{d}.{d}",787 const target_os = switch (self.target) {
788 self.name, self.version.major, self.version.minor, self.version.patch);788 Target.Native => builtin.os,
789 self.major_only_filename = self.builder.fmt("lib{}.so.{d}", self.name, self.version.major);789 Target.Cross => |t| t.os,
790 self.name_only_filename = self.builder.fmt("lib{}.so", self.name);790 };
791 switch (target_os) {
792 builtin.Os.darwin, builtin.Os.ios, builtin.Os.macosx => {
793 self.out_filename = self.builder.fmt("lib{}.dylib.{d}.{d}.{d}",
794 self.name, self.version.major, self.version.minor, self.version.patch);
795 self.major_only_filename = self.builder.fmt("lib{}.dylib.{d}", self.name, self.version.major);
796 self.name_only_filename = self.builder.fmt("lib{}.dylib", self.name);
797 },
798 builtin.Os.windows => {
799 self.out_filename = self.builder.fmt("lib{}.dll", self.name);
800 },
801 else => {
802 self.out_filename = self.builder.fmt("lib{}.so.{d}.{d}.{d}",
803 self.name, self.version.major, self.version.minor, self.version.patch);
804 self.major_only_filename = self.builder.fmt("lib{}.so.{d}", self.name, self.version.major);
805 self.name_only_filename = self.builder.fmt("lib{}.so", self.name);
806 },
807 }
791 }808 }
792 },809 },
793 }810 }
...@@ -1124,6 +1141,7 @@ pub const CLibExeObjStep = struct {...@@ -1124,6 +1141,7 @@ pub const CLibExeObjStep = struct {
1124 kind: Kind,1141 kind: Kind,
1125 build_mode: builtin.Mode,1142 build_mode: builtin.Mode,
1126 strip: bool,1143 strip: bool,
1144 need_flat_namespace_hack: bool,
11271145
1128 const Kind = enum {1146 const Kind = enum {
1129 Exe,1147 Exe,
...@@ -1178,6 +1196,7 @@ pub const CLibExeObjStep = struct {...@@ -1178,6 +1196,7 @@ pub const CLibExeObjStep = struct {
1178 .object_src = undefined,1196 .object_src = undefined,
1179 .build_mode = builtin.Mode.Debug,1197 .build_mode = builtin.Mode.Debug,
1180 .strip = false,1198 .strip = false,
1199 .need_flat_namespace_hack = false,
1181 };1200 };
1182 clib.computeOutFileNames();1201 clib.computeOutFileNames();
1183 return clib;1202 return clib;
...@@ -1223,6 +1242,7 @@ pub const CLibExeObjStep = struct {...@@ -1223,6 +1242,7 @@ pub const CLibExeObjStep = struct {
1223 %%self.full_path_libs.append(lib.getOutputPath());1242 %%self.full_path_libs.append(lib.getOutputPath());
1224 // TODO should be some kind of isolated directory that only has this header in it1243 // TODO should be some kind of isolated directory that only has this header in it
1225 %%self.include_dirs.append(self.builder.cache_root);1244 %%self.include_dirs.append(self.builder.cache_root);
1245 self.need_flat_namespace_hack = true;
1226 }1246 }
12271247
1228 pub fn linkSystemLibrary(self: &CLibExeObjStep, name: []const u8) {1248 pub fn linkSystemLibrary(self: &CLibExeObjStep, name: []const u8) {
...@@ -1448,6 +1468,20 @@ pub const CLibExeObjStep = struct {...@@ -1448,6 +1468,20 @@ pub const CLibExeObjStep = struct {
14481468
1449 %%cc_args.append("-rdynamic");1469 %%cc_args.append("-rdynamic");
14501470
1471 const target_os = switch (self.target) {
1472 Target.Native => builtin.os,
1473 Target.Cross => |t| t.os,
1474 };
1475 switch (target_os) {
1476 builtin.Os.darwin, builtin.Os.ios, builtin.Os.macosx => {
1477 if (self.need_flat_namespace_hack) {
1478 %%cc_args.append("-Wl,-flat_namespace");
1479 }
1480 %%cc_args.append("-Wl,-search_paths_first");
1481 },
1482 else => {}
1483 }
1484
1451 for (self.full_path_libs.toSliceConst()) |full_path_lib| {1485 for (self.full_path_libs.toSliceConst()) |full_path_lib| {
1452 %%cc_args.append(builder.pathFromRoot(full_path_lib));1486 %%cc_args.append(builder.pathFromRoot(full_path_lib));
1453 }1487 }
std/c/index.zig+1
...@@ -37,3 +37,4 @@ pub extern "c" fn execve(path: &const u8, argv: &const ?&const u8,...@@ -37,3 +37,4 @@ pub extern "c" fn execve(path: &const u8, argv: &const ?&const u8,
37pub extern "c" fn dup(fd: c_int) -> c_int;37pub extern "c" fn dup(fd: c_int) -> c_int;
38pub extern "c" fn dup2(old_fd: c_int, new_fd: c_int) -> c_int;38pub extern "c" fn dup2(old_fd: c_int, new_fd: c_int) -> c_int;
39pub extern "c" fn readlink(noalias path: &const u8, noalias buf: &u8, bufsize: usize) -> isize;39pub extern "c" fn readlink(noalias path: &const u8, noalias buf: &u8, bufsize: usize) -> isize;
40pub extern "c" fn realpath(noalias file_name: &const u8, noalias resolved_name: &u8) -> ?&u8;
std/os/darwin.zig+6
...@@ -3,6 +3,8 @@ const assert = @import("../debug.zig").assert;...@@ -3,6 +3,8 @@ const assert = @import("../debug.zig").assert;
33
4pub use @import("darwin_errno.zig");4pub use @import("darwin_errno.zig");
55
6pub const PATH_MAX = 1024;
7
6pub const STDIN_FILENO = 0;8pub const STDIN_FILENO = 0;
7pub const STDOUT_FILENO = 1;9pub const STDOUT_FILENO = 1;
8pub const STDERR_FILENO = 2;10pub const STDERR_FILENO = 2;
...@@ -203,6 +205,10 @@ pub fn readlink(noalias path: &const u8, noalias buf_ptr: &u8, buf_len: usize) -...@@ -203,6 +205,10 @@ pub fn readlink(noalias path: &const u8, noalias buf_ptr: &u8, buf_len: usize) -
203 errnoWrap(c.readlink(path, buf_ptr, buf_len))205 errnoWrap(c.readlink(path, buf_ptr, buf_len))
204}206}
205207
208pub fn realpath(noalias filename: &const u8, noalias resolved_name: &u8) -> usize {
209 if (c.realpath(filename, resolved_name) == null) @bitCast(usize, -isize(*c._errno())) else 0
210}
211
206/// Takes the return value from a syscall and formats it back in the way212/// Takes the return value from a syscall and formats it back in the way
207/// that the kernel represents it to libc. Errno was a mistake, let's make213/// that the kernel represents it to libc. Errno was a mistake, let's make
208/// it go away forever.214/// it go away forever.
std/os/linux.zig+2
...@@ -6,6 +6,8 @@ const arch = switch (builtin.arch) {...@@ -6,6 +6,8 @@ const arch = switch (builtin.arch) {
6};6};
7pub use @import("linux_errno.zig");7pub use @import("linux_errno.zig");
88
9pub const PATH_MAX = 4096;
10
9pub const STDIN_FILENO = 0;11pub const STDIN_FILENO = 0;
10pub const STDOUT_FILENO = 1;12pub const STDOUT_FILENO = 1;
11pub const STDERR_FILENO = 2;13pub const STDERR_FILENO = 2;
std/os/path.zig+52-9
...@@ -8,6 +8,8 @@ const Allocator = mem.Allocator;...@@ -8,6 +8,8 @@ const Allocator = mem.Allocator;
8const os = @import("index.zig");8const os = @import("index.zig");
9const math = @import("../math.zig");9const math = @import("../math.zig");
10const posix = os.posix;10const posix = os.posix;
11const c = @import("../c/index.zig");
12const cstr = @import("../cstr.zig");
1113
12pub const sep = switch (builtin.os) {14pub const sep = switch (builtin.os) {
13 Os.windows => '\\',15 Os.windows => '\\',
...@@ -279,19 +281,60 @@ fn testRelative(from: []const u8, to: []const u8, expected_output: []const u8) {...@@ -279,19 +281,60 @@ fn testRelative(from: []const u8, to: []const u8, expected_output: []const u8) {
279 assert(mem.eql(u8, result, expected_output));281 assert(mem.eql(u8, result, expected_output));
280}282}
281283
284error AccessDenied;
285error FileNotFound;
286error NotSupported;
287error NotDir;
288error NameTooLong;
289error SymLinkLoop;
290error InputOutput;
291error Unexpected;
282/// Return the canonicalized absolute pathname.292/// Return the canonicalized absolute pathname.
283/// Expands all symbolic links and resolves references to `.`, `..`, and293/// Expands all symbolic links and resolves references to `.`, `..`, and
284/// extra `/` characters in ::pathname.294/// extra `/` characters in ::pathname.
285/// Caller must deallocate result.295/// Caller must deallocate result.
286pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 {296pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 {
287 if (builtin.os == builtin.Os.windows) {297 switch (builtin.os) {
288 @compileError("TODO implement os.path.real for windows");298 Os.windows => @compileError("TODO implement os.path.real for windows"),
299 Os.darwin, Os.macosx, Os.ios => {
300 // TODO instead of calling the libc function here, port the implementation
301 // to Zig, and then remove the NameTooLong error possibility.
302 const pathname_buf = %return allocator.alloc(u8, pathname.len + 1);
303 defer allocator.free(pathname_buf);
304
305 const result_buf = %return allocator.alloc(u8, posix.PATH_MAX);
306 %defer allocator.free(result_buf);
307
308 mem.copy(u8, pathname_buf, pathname);
309 pathname_buf[pathname.len] = 0;
310
311 const err = posix.getErrno(posix.realpath(pathname_buf.ptr, result_buf.ptr));
312 if (err > 0) {
313 return switch (err) {
314 posix.EINVAL => unreachable,
315 posix.EBADF => unreachable,
316 posix.EFAULT => unreachable,
317 posix.EACCES => error.AccessDenied,
318 posix.ENOENT => error.FileNotFound,
319 posix.ENOTSUP => error.NotSupported,
320 posix.ENOTDIR => error.NotDir,
321 posix.ENAMETOOLONG => error.NameTooLong,
322 posix.ELOOP => error.SymLinkLoop,
323 posix.EIO => error.InputOutput,
324 else => error.Unexpected,
325 };
326 }
327 return cstr.toSlice(result_buf.ptr);
328 },
329 Os.linux => {
330 const fd = %return os.posixOpen(pathname, posix.O_PATH|posix.O_NONBLOCK|posix.O_CLOEXEC, 0, allocator);
331 defer os.posixClose(fd);
332
333 var buf: ["/proc/self/fd/-2147483648".len]u8 = undefined;
334 const proc_path = fmt.bufPrint(buf[0..], "/proc/self/fd/{}", fd);
335
336 return os.readLink(allocator, proc_path);
337 },
338 else => @compileError("TODO implement os.path.real for " ++ @enumTagName(builtin.os)),
289 }339 }
290 const fd = %return os.posixOpen(pathname, posix.O_PATH|posix.O_NONBLOCK|posix.O_CLOEXEC, 0, allocator);
291 defer os.posixClose(fd);
292
293 var buf: ["/proc/self/fd/-2147483648".len]u8 = undefined;
294 const proc_path = fmt.bufPrint(buf[0..], "/proc/self/fd/{}", fd);
295
296 return os.readLink(allocator, proc_path);
297}340}