| ... | ... | @@ -567,9 +567,14 @@ pub fn defineCMacro(c: *Compile, name: []const u8, value: ?[]const u8) void { |
| 567 | 567 | c.root_module.addCMacro(name, value orelse "1"); |
| 568 | 568 | } |
| 569 | 569 | |
| 570 | const PkgConfigResult = struct { |
| 571 | cflags: []const []const u8, |
| 572 | libs: []const []const u8, |
| 573 | }; |
| 574 | |
| 570 | 575 | /// Run pkg-config for the given library name and parse the output, returning the arguments |
| 571 | 576 | /// that should be passed to zig to link the given library. |
| 572 | | fn runPkgConfig(self: *Compile, lib_name: []const u8) ![]const []const u8 { |
| 577 | fn runPkgConfig(self: *Compile, lib_name: []const u8) !PkgConfigResult { |
| 573 | 578 | const b = self.step.owner; |
| 574 | 579 | const pkg_name = match: { |
| 575 | 580 | // First we have to map the library name to pkg config name. Unfortunately, |
| ... | ... | @@ -630,37 +635,42 @@ fn runPkgConfig(self: *Compile, lib_name: []const u8) ![]const []const u8 { |
| 630 | 635 | else => return err, |
| 631 | 636 | }; |
| 632 | 637 | |
| 633 | | var zig_args = ArrayList([]const u8).init(b.allocator); |
| 634 | | defer zig_args.deinit(); |
| 638 | var zig_cflags = ArrayList([]const u8).init(b.allocator); |
| 639 | defer zig_cflags.deinit(); |
| 640 | var zig_libs = ArrayList([]const u8).init(b.allocator); |
| 641 | defer zig_libs.deinit(); |
| 635 | 642 | |
| 636 | 643 | var it = mem.tokenizeAny(u8, stdout, " \r\n\t"); |
| 637 | 644 | while (it.next()) |tok| { |
| 638 | 645 | if (mem.eql(u8, tok, "-I")) { |
| 639 | 646 | const dir = it.next() orelse return error.PkgConfigInvalidOutput; |
| 640 | | try zig_args.appendSlice(&[_][]const u8{ "-I", dir }); |
| 647 | try zig_cflags.appendSlice(&[_][]const u8{ "-I", dir }); |
| 641 | 648 | } else if (mem.startsWith(u8, tok, "-I")) { |
| 642 | | try zig_args.append(tok); |
| 649 | try zig_cflags.append(tok); |
| 643 | 650 | } else if (mem.eql(u8, tok, "-L")) { |
| 644 | 651 | const dir = it.next() orelse return error.PkgConfigInvalidOutput; |
| 645 | | try zig_args.appendSlice(&[_][]const u8{ "-L", dir }); |
| 652 | try zig_libs.appendSlice(&[_][]const u8{ "-L", dir }); |
| 646 | 653 | } else if (mem.startsWith(u8, tok, "-L")) { |
| 647 | | try zig_args.append(tok); |
| 654 | try zig_libs.append(tok); |
| 648 | 655 | } else if (mem.eql(u8, tok, "-l")) { |
| 649 | 656 | const lib = it.next() orelse return error.PkgConfigInvalidOutput; |
| 650 | | try zig_args.appendSlice(&[_][]const u8{ "-l", lib }); |
| 657 | try zig_libs.appendSlice(&[_][]const u8{ "-l", lib }); |
| 651 | 658 | } else if (mem.startsWith(u8, tok, "-l")) { |
| 652 | | try zig_args.append(tok); |
| 659 | try zig_libs.append(tok); |
| 653 | 660 | } else if (mem.eql(u8, tok, "-D")) { |
| 654 | 661 | const macro = it.next() orelse return error.PkgConfigInvalidOutput; |
| 655 | | try zig_args.appendSlice(&[_][]const u8{ "-D", macro }); |
| 662 | try zig_cflags.appendSlice(&[_][]const u8{ "-D", macro }); |
| 656 | 663 | } else if (mem.startsWith(u8, tok, "-D")) { |
| 657 | | try zig_args.append(tok); |
| 664 | try zig_cflags.append(tok); |
| 658 | 665 | } else if (b.debug_pkg_config) { |
| 659 | 666 | return self.step.fail("unknown pkg-config flag '{s}'", .{tok}); |
| 660 | 667 | } |
| 661 | 668 | } |
| 662 | 669 | |
| 663 | | return zig_args.toOwnedSlice(); |
| 670 | return .{ |
| 671 | .cflags = try zig_cflags.toOwnedSlice(), |
| 672 | .libs = try zig_libs.toOwnedSlice(), |
| 673 | }; |
| 664 | 674 | } |
| 665 | 675 | |
| 666 | 676 | pub fn linkSystemLibrary(self: *Compile, name: []const u8) void { |
| ... | ... | @@ -954,7 +964,10 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 954 | 964 | } |
| 955 | 965 | |
| 956 | 966 | { |
| 957 | | var seen_system_libs: std.StringHashMapUnmanaged(void) = .{}; |
| 967 | // Stores system libraries that have already been seen for at least one |
| 968 | // module, along with any arguments that need to be passed to the |
| 969 | // compiler for each module individually. |
| 970 | var seen_system_libs: std.StringHashMapUnmanaged([]const []const u8) = .{}; |
| 958 | 971 | var frameworks: std.StringArrayHashMapUnmanaged(Module.LinkFrameworkOptions) = .{}; |
| 959 | 972 | |
| 960 | 973 | var prev_has_cflags = false; |
| ... | ... | @@ -1008,8 +1021,13 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 1008 | 1021 | } |
| 1009 | 1022 | }, |
| 1010 | 1023 | .system_lib => |system_lib| { |
| 1011 | | if ((try seen_system_libs.fetchPut(arena, system_lib.name, {})) != null) |
| 1024 | const system_lib_gop = try seen_system_libs.getOrPut(arena, system_lib.name); |
| 1025 | if (system_lib_gop.found_existing) { |
| 1026 | try zig_args.appendSlice(system_lib_gop.value_ptr.*); |
| 1012 | 1027 | continue; |
| 1028 | } else { |
| 1029 | system_lib_gop.value_ptr.* = &.{}; |
| 1030 | } |
| 1013 | 1031 | |
| 1014 | 1032 | if (already_linked) |
| 1015 | 1033 | continue; |
| ... | ... | @@ -1044,8 +1062,10 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 1044 | 1062 | switch (system_lib.use_pkg_config) { |
| 1045 | 1063 | .no => try zig_args.append(b.fmt("{s}{s}", .{ prefix, system_lib.name })), |
| 1046 | 1064 | .yes, .force => { |
| 1047 | | if (self.runPkgConfig(system_lib.name)) |args| { |
| 1048 | | try zig_args.appendSlice(args); |
| 1065 | if (self.runPkgConfig(system_lib.name)) |result| { |
| 1066 | try zig_args.appendSlice(result.cflags); |
| 1067 | try zig_args.appendSlice(result.libs); |
| 1068 | try seen_system_libs.put(arena, system_lib.name, result.cflags); |
| 1049 | 1069 | } else |err| switch (err) { |
| 1050 | 1070 | error.PkgConfigInvalidOutput, |
| 1051 | 1071 | error.PkgConfigCrashed, |