authorgravatar for ian@ianjohnson.devIan Johnson <ian@ianjohnson.dev> 2024-01-29 00:17:55-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-29 14:08:41-08:00
log27d2d8e81f03264e951ef3a7e4bb230d223f2ac2
treee14955c95633427aea6770d256ed32a344dc90cf
parenta479fd313248a55273a17de5f9af6b82abdb0be4

Apply cflags from pkg-config to all dependent modules

Closes #18628 This commit splits the arguments obtained from pkg-config into two groups, cflags and libs, and consistently applies the cflags to each individual module linking the library while applying the libs only once for each compilation.

1 files changed, 36 insertions(+), 16 deletions(-)

lib/std/Build/Step/Compile.zig+36-16
...@@ -567,9 +567,14 @@ pub fn defineCMacro(c: *Compile, name: []const u8, value: ?[]const u8) void {...@@ -567,9 +567,14 @@ pub fn defineCMacro(c: *Compile, name: []const u8, value: ?[]const u8) void {
567 c.root_module.addCMacro(name, value orelse "1");567 c.root_module.addCMacro(name, value orelse "1");
568}568}
569569
570const PkgConfigResult = struct {
571 cflags: []const []const u8,
572 libs: []const []const u8,
573};
574
570/// Run pkg-config for the given library name and parse the output, returning the arguments575/// Run pkg-config for the given library name and parse the output, returning the arguments
571/// that should be passed to zig to link the given library.576/// that should be passed to zig to link the given library.
572fn runPkgConfig(self: *Compile, lib_name: []const u8) ![]const []const u8 {577fn runPkgConfig(self: *Compile, lib_name: []const u8) !PkgConfigResult {
573 const b = self.step.owner;578 const b = self.step.owner;
574 const pkg_name = match: {579 const pkg_name = match: {
575 // First we have to map the library name to pkg config name. Unfortunately,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,37 +635,42 @@ fn runPkgConfig(self: *Compile, lib_name: []const u8) ![]const []const u8 {
630 else => return err,635 else => return err,
631 };636 };
632637
633 var zig_args = ArrayList([]const u8).init(b.allocator);638 var zig_cflags = ArrayList([]const u8).init(b.allocator);
634 defer zig_args.deinit();639 defer zig_cflags.deinit();
640 var zig_libs = ArrayList([]const u8).init(b.allocator);
641 defer zig_libs.deinit();
635642
636 var it = mem.tokenizeAny(u8, stdout, " \r\n\t");643 var it = mem.tokenizeAny(u8, stdout, " \r\n\t");
637 while (it.next()) |tok| {644 while (it.next()) |tok| {
638 if (mem.eql(u8, tok, "-I")) {645 if (mem.eql(u8, tok, "-I")) {
639 const dir = it.next() orelse return error.PkgConfigInvalidOutput;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 } else if (mem.startsWith(u8, tok, "-I")) {648 } else if (mem.startsWith(u8, tok, "-I")) {
642 try zig_args.append(tok);649 try zig_cflags.append(tok);
643 } else if (mem.eql(u8, tok, "-L")) {650 } else if (mem.eql(u8, tok, "-L")) {
644 const dir = it.next() orelse return error.PkgConfigInvalidOutput;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 } else if (mem.startsWith(u8, tok, "-L")) {653 } else if (mem.startsWith(u8, tok, "-L")) {
647 try zig_args.append(tok);654 try zig_libs.append(tok);
648 } else if (mem.eql(u8, tok, "-l")) {655 } else if (mem.eql(u8, tok, "-l")) {
649 const lib = it.next() orelse return error.PkgConfigInvalidOutput;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 } else if (mem.startsWith(u8, tok, "-l")) {658 } else if (mem.startsWith(u8, tok, "-l")) {
652 try zig_args.append(tok);659 try zig_libs.append(tok);
653 } else if (mem.eql(u8, tok, "-D")) {660 } else if (mem.eql(u8, tok, "-D")) {
654 const macro = it.next() orelse return error.PkgConfigInvalidOutput;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 } else if (mem.startsWith(u8, tok, "-D")) {663 } else if (mem.startsWith(u8, tok, "-D")) {
657 try zig_args.append(tok);664 try zig_cflags.append(tok);
658 } else if (b.debug_pkg_config) {665 } else if (b.debug_pkg_config) {
659 return self.step.fail("unknown pkg-config flag '{s}'", .{tok});666 return self.step.fail("unknown pkg-config flag '{s}'", .{tok});
660 }667 }
661 }668 }
662669
663 return zig_args.toOwnedSlice();670 return .{
671 .cflags = try zig_cflags.toOwnedSlice(),
672 .libs = try zig_libs.toOwnedSlice(),
673 };
664}674}
665675
666pub fn linkSystemLibrary(self: *Compile, name: []const u8) void {676pub fn linkSystemLibrary(self: *Compile, name: []const u8) void {
...@@ -954,7 +964,10 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -954,7 +964,10 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
954 }964 }
955965
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 var frameworks: std.StringArrayHashMapUnmanaged(Module.LinkFrameworkOptions) = .{};971 var frameworks: std.StringArrayHashMapUnmanaged(Module.LinkFrameworkOptions) = .{};
959972
960 var prev_has_cflags = false;973 var prev_has_cflags = false;
...@@ -1008,8 +1021,13 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -1008,8 +1021,13 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
1008 }1021 }
1009 },1022 },
1010 .system_lib => |system_lib| {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 continue;1027 continue;
1028 } else {
1029 system_lib_gop.value_ptr.* = &.{};
1030 }
10131031
1014 if (already_linked)1032 if (already_linked)
1015 continue;1033 continue;
...@@ -1044,8 +1062,10 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -1044,8 +1062,10 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
1044 switch (system_lib.use_pkg_config) {1062 switch (system_lib.use_pkg_config) {
1045 .no => try zig_args.append(b.fmt("{s}{s}", .{ prefix, system_lib.name })),1063 .no => try zig_args.append(b.fmt("{s}{s}", .{ prefix, system_lib.name })),
1046 .yes, .force => {1064 .yes, .force => {
1047 if (self.runPkgConfig(system_lib.name)) |args| {1065 if (self.runPkgConfig(system_lib.name)) |result| {
1048 try zig_args.appendSlice(args);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 } else |err| switch (err) {1069 } else |err| switch (err) {
1050 error.PkgConfigInvalidOutput,1070 error.PkgConfigInvalidOutput,
1051 error.PkgConfigCrashed,1071 error.PkgConfigCrashed,