| ... | @@ -1,10 +1,12 @@ | ... | @@ -1,10 +1,12 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| | 2 | const mem = std.mem; |
| 2 | const c = @import("c.zig"); | 3 | const c = @import("c.zig"); |
| 3 | const builtin = @import("builtin"); | 4 | const builtin = @import("builtin"); |
| 4 | const ObjectFormat = builtin.ObjectFormat; | 5 | const ObjectFormat = builtin.ObjectFormat; |
| 5 | const Compilation = @import("compilation.zig").Compilation; | 6 | const Compilation = @import("compilation.zig").Compilation; |
| 6 | const Target = @import("target.zig").Target; | 7 | const Target = @import("target.zig").Target; |
| 7 | const LibCInstallation = @import("libc_installation.zig").LibCInstallation; | 8 | const LibCInstallation = @import("libc_installation.zig").LibCInstallation; |
| | 9 | const assert = std.debug.assert; |
| 8 | | 10 | |
| 9 | const Context = struct { | 11 | const Context = struct { |
| 10 | comp: *Compilation, | 12 | comp: *Compilation, |
| ... | @@ -315,8 +317,163 @@ fn constructLinkerArgsCoff(ctx: *Context) void { | ... | @@ -315,8 +317,163 @@ fn constructLinkerArgsCoff(ctx: *Context) void { |
| 315 | @panic("TODO"); | 317 | @panic("TODO"); |
| 316 | } | 318 | } |
| 317 | | 319 | |
| 318 | fn constructLinkerArgsMachO(ctx: *Context) void { | 320 | fn constructLinkerArgsMachO(ctx: *Context) !void { |
| 319 | @panic("TODO"); | 321 | try ctx.args.append(c"-demangle"); |
| | 322 | |
| | 323 | if (ctx.comp.linker_rdynamic) { |
| | 324 | try ctx.args.append(c"-export_dynamic"); |
| | 325 | } |
| | 326 | |
| | 327 | const is_lib = ctx.comp.kind == Compilation.Kind.Lib; |
| | 328 | const shared = !ctx.comp.is_static and is_lib; |
| | 329 | if (ctx.comp.is_static) { |
| | 330 | try ctx.args.append(c"-static"); |
| | 331 | } else { |
| | 332 | try ctx.args.append(c"-dynamic"); |
| | 333 | } |
| | 334 | |
| | 335 | //if (is_lib) { |
| | 336 | // if (!g->is_static) { |
| | 337 | // lj->args.append("-dylib"); |
| | 338 | |
| | 339 | // Buf *compat_vers = buf_sprintf("%" ZIG_PRI_usize ".0.0", g->version_major); |
| | 340 | // lj->args.append("-compatibility_version"); |
| | 341 | // lj->args.append(buf_ptr(compat_vers)); |
| | 342 | |
| | 343 | // Buf *cur_vers = buf_sprintf("%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize, |
| | 344 | // g->version_major, g->version_minor, g->version_patch); |
| | 345 | // lj->args.append("-current_version"); |
| | 346 | // lj->args.append(buf_ptr(cur_vers)); |
| | 347 | |
| | 348 | // // TODO getting an error when running an executable when doing this rpath thing |
| | 349 | // //Buf *dylib_install_name = buf_sprintf("@rpath/lib%s.%" ZIG_PRI_usize ".dylib", |
| | 350 | // // buf_ptr(g->root_out_name), g->version_major); |
| | 351 | // //lj->args.append("-install_name"); |
| | 352 | // //lj->args.append(buf_ptr(dylib_install_name)); |
| | 353 | |
| | 354 | // if (buf_len(&lj->out_file) == 0) { |
| | 355 | // buf_appendf(&lj->out_file, "lib%s.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib", |
| | 356 | // buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch); |
| | 357 | // } |
| | 358 | // } |
| | 359 | //} |
| | 360 | |
| | 361 | try ctx.args.append(c"-arch"); |
| | 362 | const darwin_arch_str = try std.cstr.addNullByte( |
| | 363 | &ctx.arena.allocator, |
| | 364 | ctx.comp.target.getDarwinArchString(), |
| | 365 | ); |
| | 366 | try ctx.args.append(darwin_arch_str.ptr); |
| | 367 | |
| | 368 | const platform = try DarwinPlatform.get(ctx.comp); |
| | 369 | switch (platform.kind) { |
| | 370 | DarwinPlatform.Kind.MacOS => try ctx.args.append(c"-macosx_version_min"), |
| | 371 | DarwinPlatform.Kind.IPhoneOS => try ctx.args.append(c"-iphoneos_version_min"), |
| | 372 | DarwinPlatform.Kind.IPhoneOSSimulator => try ctx.args.append(c"-ios_simulator_version_min"), |
| | 373 | } |
| | 374 | const ver_str = try std.fmt.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", platform.major, platform.minor, platform.micro); |
| | 375 | try ctx.args.append(ver_str.ptr); |
| | 376 | |
| | 377 | if (ctx.comp.kind == Compilation.Kind.Exe) { |
| | 378 | if (ctx.comp.is_static) { |
| | 379 | try ctx.args.append(c"-no_pie"); |
| | 380 | } else { |
| | 381 | try ctx.args.append(c"-pie"); |
| | 382 | } |
| | 383 | } |
| | 384 | |
| | 385 | try ctx.args.append(c"-o"); |
| | 386 | try ctx.args.append(ctx.out_file_path.ptr()); |
| | 387 | |
| | 388 | //for (size_t i = 0; i < g->rpath_list.length; i += 1) { |
| | 389 | // Buf *rpath = g->rpath_list.at(i); |
| | 390 | // add_rpath(lj, rpath); |
| | 391 | //} |
| | 392 | //add_rpath(lj, &lj->out_file); |
| | 393 | |
| | 394 | if (shared) { |
| | 395 | try ctx.args.append(c"-headerpad_max_install_names"); |
| | 396 | } else if (ctx.comp.is_static) { |
| | 397 | try ctx.args.append(c"-lcrt0.o"); |
| | 398 | } else { |
| | 399 | switch (platform.kind) { |
| | 400 | DarwinPlatform.Kind.MacOS => { |
| | 401 | if (platform.versionLessThan(10, 5)) { |
| | 402 | try ctx.args.append(c"-lcrt1.o"); |
| | 403 | } else if (platform.versionLessThan(10, 6)) { |
| | 404 | try ctx.args.append(c"-lcrt1.10.5.o"); |
| | 405 | } else if (platform.versionLessThan(10, 8)) { |
| | 406 | try ctx.args.append(c"-lcrt1.10.6.o"); |
| | 407 | } |
| | 408 | }, |
| | 409 | DarwinPlatform.Kind.IPhoneOS => { |
| | 410 | if (ctx.comp.target.getArch() == builtin.Arch.aarch64) { |
| | 411 | // iOS does not need any crt1 files for arm64 |
| | 412 | } else if (platform.versionLessThan(3, 1)) { |
| | 413 | try ctx.args.append(c"-lcrt1.o"); |
| | 414 | } else if (platform.versionLessThan(6, 0)) { |
| | 415 | try ctx.args.append(c"-lcrt1.3.1.o"); |
| | 416 | } |
| | 417 | }, |
| | 418 | DarwinPlatform.Kind.IPhoneOSSimulator => {}, // no crt1.o needed |
| | 419 | } |
| | 420 | } |
| | 421 | |
| | 422 | //for (size_t i = 0; i < g->lib_dirs.length; i += 1) { |
| | 423 | // const char *lib_dir = g->lib_dirs.at(i); |
| | 424 | // lj->args.append("-L"); |
| | 425 | // lj->args.append(lib_dir); |
| | 426 | //} |
| | 427 | |
| | 428 | for (ctx.comp.link_objects) |link_object| { |
| | 429 | const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object); |
| | 430 | try ctx.args.append(link_obj_with_null.ptr); |
| | 431 | } |
| | 432 | try addFnObjects(ctx); |
| | 433 | |
| | 434 | //// compiler_rt on darwin is missing some stuff, so we still build it and rely on LinkOnce |
| | 435 | //if (g->out_type == OutTypeExe || g->out_type == OutTypeLib) { |
| | 436 | // Buf *compiler_rt_o_path = build_compiler_rt(g); |
| | 437 | // lj->args.append(buf_ptr(compiler_rt_o_path)); |
| | 438 | //} |
| | 439 | |
| | 440 | if (ctx.comp.target == Target.Native) { |
| | 441 | for (ctx.comp.link_libs_list.toSliceConst()) |lib| { |
| | 442 | if (mem.eql(u8, lib.name, "c")) { |
| | 443 | // on Darwin, libSystem has libc in it, but also you have to use it |
| | 444 | // to make syscalls because the syscall numbers are not documented |
| | 445 | // and change between versions. |
| | 446 | // so we always link against libSystem |
| | 447 | try ctx.args.append(c"-lSystem"); |
| | 448 | } else { |
| | 449 | if (mem.indexOfScalar(u8, lib.name, '/') == null) { |
| | 450 | const arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-l{}\x00", lib.name); |
| | 451 | try ctx.args.append(arg.ptr); |
| | 452 | } else { |
| | 453 | const arg = try std.cstr.addNullByte(&ctx.arena.allocator, lib.name); |
| | 454 | try ctx.args.append(arg.ptr); |
| | 455 | } |
| | 456 | } |
| | 457 | } |
| | 458 | } else { |
| | 459 | try ctx.args.append(c"-undefined"); |
| | 460 | try ctx.args.append(c"dynamic_lookup"); |
| | 461 | } |
| | 462 | |
| | 463 | if (platform.kind == DarwinPlatform.Kind.MacOS) { |
| | 464 | if (platform.versionLessThan(10, 5)) { |
| | 465 | try ctx.args.append(c"-lgcc_s.10.4"); |
| | 466 | } else if (platform.versionLessThan(10, 6)) { |
| | 467 | try ctx.args.append(c"-lgcc_s.10.5"); |
| | 468 | } |
| | 469 | } else { |
| | 470 | @panic("TODO"); |
| | 471 | } |
| | 472 | |
| | 473 | //for (size_t i = 0; i < g->darwin_frameworks.length; i += 1) { |
| | 474 | // lj->args.append("-framework"); |
| | 475 | // lj->args.append(buf_ptr(g->darwin_frameworks.at(i))); |
| | 476 | //} |
| 320 | } | 477 | } |
| 321 | | 478 | |
| 322 | fn constructLinkerArgsWasm(ctx: *Context) void { | 479 | fn constructLinkerArgsWasm(ctx: *Context) void { |
| ... | @@ -341,3 +498,85 @@ fn addFnObjects(ctx: *Context) !void { | ... | @@ -341,3 +498,85 @@ fn addFnObjects(ctx: *Context) !void { |
| 341 | it = node.next; | 498 | it = node.next; |
| 342 | } | 499 | } |
| 343 | } | 500 | } |
| | 501 | |
| | 502 | const DarwinPlatform = struct { |
| | 503 | kind: Kind, |
| | 504 | major: u32, |
| | 505 | minor: u32, |
| | 506 | micro: u32, |
| | 507 | |
| | 508 | const Kind = enum { |
| | 509 | MacOS, |
| | 510 | IPhoneOS, |
| | 511 | IPhoneOSSimulator, |
| | 512 | }; |
| | 513 | |
| | 514 | fn get(comp: *Compilation) !DarwinPlatform { |
| | 515 | var result: DarwinPlatform = undefined; |
| | 516 | const ver_str = switch (comp.darwin_version_min) { |
| | 517 | Compilation.DarwinVersionMin.MacOS => |ver| blk: { |
| | 518 | result.kind = Kind.MacOS; |
| | 519 | break :blk ver; |
| | 520 | }, |
| | 521 | Compilation.DarwinVersionMin.Ios => |ver| blk: { |
| | 522 | result.kind = Kind.IPhoneOS; |
| | 523 | break :blk ver; |
| | 524 | }, |
| | 525 | Compilation.DarwinVersionMin.None => blk: { |
| | 526 | assert(comp.target.getOs() == builtin.Os.macosx); |
| | 527 | result.kind = Kind.MacOS; |
| | 528 | break :blk "10.10"; |
| | 529 | }, |
| | 530 | }; |
| | 531 | |
| | 532 | var had_extra: bool = undefined; |
| | 533 | try darwinGetReleaseVersion(ver_str, &result.major, &result.minor, &result.micro, &had_extra,); |
| | 534 | if (had_extra or result.major != 10 or result.minor >= 100 or result.micro >= 100) { |
| | 535 | return error.InvalidDarwinVersionString; |
| | 536 | } |
| | 537 | |
| | 538 | if (result.kind == Kind.IPhoneOS) { |
| | 539 | switch (comp.target.getArch()) { |
| | 540 | builtin.Arch.i386, |
| | 541 | builtin.Arch.x86_64, |
| | 542 | => result.kind = Kind.IPhoneOSSimulator, |
| | 543 | else => {}, |
| | 544 | } |
| | 545 | } |
| | 546 | return result; |
| | 547 | } |
| | 548 | |
| | 549 | fn versionLessThan(self: DarwinPlatform, major: u32, minor: u32) bool { |
| | 550 | if (self.major < major) |
| | 551 | return true; |
| | 552 | if (self.major > major) |
| | 553 | return false; |
| | 554 | if (self.minor < minor) |
| | 555 | return true; |
| | 556 | return false; |
| | 557 | } |
| | 558 | }; |
| | 559 | |
| | 560 | /// Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and return the |
| | 561 | /// grouped values as integers. Numbers which are not provided are set to 0. |
| | 562 | /// return true if the entire string was parsed (9.2), or all groups were |
| | 563 | /// parsed (10.3.5extrastuff). |
| | 564 | fn darwinGetReleaseVersion(str: []const u8, major: *u32, minor: *u32, micro: *u32, had_extra: *bool) !void { |
| | 565 | major.* = 0; |
| | 566 | minor.* = 0; |
| | 567 | micro.* = 0; |
| | 568 | had_extra.* = false; |
| | 569 | |
| | 570 | if (str.len == 0) |
| | 571 | return error.InvalidDarwinVersionString; |
| | 572 | |
| | 573 | var start_pos: usize = 0; |
| | 574 | for ([]*u32{major, minor, micro}) |v| { |
| | 575 | const dot_pos = mem.indexOfScalarPos(u8, str, start_pos, '.'); |
| | 576 | const end_pos = dot_pos orelse str.len; |
| | 577 | v.* = std.fmt.parseUnsigned(u32, str[start_pos..end_pos], 10) catch return error.InvalidDarwinVersionString; |
| | 578 | start_pos = (dot_pos orelse return) + 1; |
| | 579 | if (start_pos == str.len) return; |
| | 580 | } |
| | 581 | had_extra.* = true; |
| | 582 | } |