authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-08-02 11:05:35-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-08-03 09:52:15-07:00
logaef8bcf7763cd098201d6b4b4c3e9e447188ae43
tree9277bd3a722ca352cfad04704793e85bdb120247
parenta0e94ec576428e3b9f003c95e6538cb57f029263

std.Build.Step.Compile: fine-grained system lib search control

For each library you can specify the preferred mode and search strategy. The old way of setting global state is eliminated.

2 files changed, 70 insertions(+), 81 deletions(-)

lib/std/Build/Step/Compile.zig+63-76
......@@ -149,13 +149,6 @@ entitlements: ?[]const u8 = null,
149149/// (Darwin) Size of the pagezero segment.
150150pagezero_size: ?u64 = null,
151151
152/// (Darwin) Search strategy for searching system libraries. Either `paths_first` or `dylibs_first`.
153/// The former lowers to `-search_paths_first` linker option, while the latter to `-search_dylibs_first`
154/// option.
155/// By default, if no option is specified, the linker assumes `paths_first` as the default
156/// search strategy.
157search_strategy: ?enum { paths_first, dylibs_first } = null,
158
159152/// (Darwin) Set size of the padding between the end of load commands
160153/// and start of `__TEXT,__text` section.
161154headerpad_size: ?u32 = null,
......@@ -242,7 +235,11 @@ pub const SystemLib = struct {
242235 name: []const u8,
243236 needed: bool,
244237 weak: bool,
245 use_pkg_config: enum {
238 use_pkg_config: UsePkgConfig,
239 preferred_link_mode: std.builtin.LinkMode,
240 search_strategy: SystemLib.SearchStrategy,
241
242 pub const UsePkgConfig = enum {
246243 /// Don't use pkg-config, just pass -lfoo where foo is name.
247244 no,
248245 /// Try to get information on how to link the library from pkg-config.
......@@ -251,7 +248,9 @@ pub const SystemLib = struct {
251248 /// Try to get information on how to link the library from pkg-config.
252249 /// If that fails, error out.
253250 force,
254 },
251 };
252
253 pub const SearchStrategy = enum { paths_first, mode_first, no_fallback };
255254};
256255
257256const FrameworkLinkInfo = struct {
......@@ -718,74 +717,29 @@ pub fn defineCMacroRaw(self: *Compile, name_and_value: []const u8) void {
718717 self.c_macros.append(b.dupe(name_and_value)) catch @panic("OOM");
719718}
720719
721/// This one has no integration with anything, it just puts -lname on the command line.
722/// Prefer to use `linkSystemLibrary` instead.
720/// deprecated: use linkSystemLibrary2
723721pub fn linkSystemLibraryName(self: *Compile, name: []const u8) void {
724 const b = self.step.owner;
725 self.link_objects.append(.{
726 .system_lib = .{
727 .name = b.dupe(name),
728 .needed = false,
729 .weak = false,
730 .use_pkg_config = .no,
731 },
732 }) catch @panic("OOM");
722 return linkSystemLibrary2(self, name, .{ .use_pkg_config = .no });
733723}
734724
735/// This one has no integration with anything, it just puts -needed-lname on the command line.
736/// Prefer to use `linkSystemLibraryNeeded` instead.
725/// deprecated: use linkSystemLibrary2
737726pub fn linkSystemLibraryNeededName(self: *Compile, name: []const u8) void {
738 const b = self.step.owner;
739 self.link_objects.append(.{
740 .system_lib = .{
741 .name = b.dupe(name),
742 .needed = true,
743 .weak = false,
744 .use_pkg_config = .no,
745 },
746 }) catch @panic("OOM");
727 return linkSystemLibrary2(self, name, .{ .needed = true, .use_pkg_config = .no });
747728}
748729
749/// Darwin-only. This one has no integration with anything, it just puts -weak-lname on the
750/// command line. Prefer to use `linkSystemLibraryWeak` instead.
730/// deprecated: use linkSystemLibrary2
751731pub fn linkSystemLibraryWeakName(self: *Compile, name: []const u8) void {
752 const b = self.step.owner;
753 self.link_objects.append(.{
754 .system_lib = .{
755 .name = b.dupe(name),
756 .needed = false,
757 .weak = true,
758 .use_pkg_config = .no,
759 },
760 }) catch @panic("OOM");
732 return linkSystemLibrary2(self, name, .{ .weak = true, .use_pkg_config = .no });
761733}
762734
763/// This links against a system library, exclusively using pkg-config to find the library.
764/// Prefer to use `linkSystemLibrary` instead.
735/// deprecated: use linkSystemLibrary2
765736pub fn linkSystemLibraryPkgConfigOnly(self: *Compile, lib_name: []const u8) void {
766 const b = self.step.owner;
767 self.link_objects.append(.{
768 .system_lib = .{
769 .name = b.dupe(lib_name),
770 .needed = false,
771 .weak = false,
772 .use_pkg_config = .force,
773 },
774 }) catch @panic("OOM");
737 return linkSystemLibrary2(self, lib_name, .{ .use_pkg_config = .force });
775738}
776739
777/// This links against a system library, exclusively using pkg-config to find the library.
778/// Prefer to use `linkSystemLibraryNeeded` instead.
740/// deprecated: use linkSystemLibrary2
779741pub fn linkSystemLibraryNeededPkgConfigOnly(self: *Compile, lib_name: []const u8) void {
780 const b = self.step.owner;
781 self.link_objects.append(.{
782 .system_lib = .{
783 .name = b.dupe(lib_name),
784 .needed = true,
785 .weak = false,
786 .use_pkg_config = .force,
787 },
788 }) catch @panic("OOM");
742 return linkSystemLibrary2(self, lib_name, .{ .needed = true, .use_pkg_config = .force });
789743}
790744
791745/// Run pkg-config for the given library name and parse the output, returning the arguments
......@@ -885,21 +839,32 @@ fn runPkgConfig(self: *Compile, lib_name: []const u8) ![]const []const u8 {
885839}
886840
887841pub fn linkSystemLibrary(self: *Compile, name: []const u8) void {
888 self.linkSystemLibraryInner(name, .{});
842 self.linkSystemLibrary2(name, .{});
889843}
890844
845/// deprecated: use linkSystemLibrary2
891846pub fn linkSystemLibraryNeeded(self: *Compile, name: []const u8) void {
892 self.linkSystemLibraryInner(name, .{ .needed = true });
847 return linkSystemLibrary2(self, name, .{ .needed = true });
893848}
894849
850/// deprecated: use linkSystemLibrary2
895851pub fn linkSystemLibraryWeak(self: *Compile, name: []const u8) void {
896 self.linkSystemLibraryInner(name, .{ .weak = true });
852 return linkSystemLibrary2(self, name, .{ .weak = true });
897853}
898854
899fn linkSystemLibraryInner(self: *Compile, name: []const u8, opts: struct {
855pub const LinkSystemLibraryOptions = struct {
900856 needed: bool = false,
901857 weak: bool = false,
902}) void {
858 use_pkg_config: SystemLib.UsePkgConfig = .yes,
859 preferred_link_mode: std.builtin.LinkMode = .Dynamic,
860 search_strategy: SystemLib.SearchStrategy = .paths_first,
861};
862
863pub fn linkSystemLibrary2(
864 self: *Compile,
865 name: []const u8,
866 options: LinkSystemLibraryOptions,
867) void {
903868 const b = self.step.owner;
904869 if (isLibCLibrary(name)) {
905870 self.linkLibC();
......@@ -913,9 +878,11 @@ fn linkSystemLibraryInner(self: *Compile, name: []const u8, opts: struct {
913878 self.link_objects.append(.{
914879 .system_lib = .{
915880 .name = b.dupe(name),
916 .needed = opts.needed,
917 .weak = opts.weak,
918 .use_pkg_config = .yes,
881 .needed = options.needed,
882 .weak = options.weak,
883 .use_pkg_config = options.use_pkg_config,
884 .preferred_link_mode = options.preferred_link_mode,
885 .search_strategy = options.search_strategy,
919886 },
920887 }) catch @panic("OOM");
921888}
......@@ -1385,6 +1352,8 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
13851352 try transitive_deps.add(self.link_objects.items);
13861353
13871354 var prev_has_cflags = false;
1355 var prev_search_strategy: SystemLib.SearchStrategy = .paths_first;
1356 var prev_preferred_link_mode: std.builtin.LinkMode = .Dynamic;
13881357
13891358 for (transitive_deps.link_objects.items) |link_object| {
13901359 switch (link_object) {
......@@ -1420,6 +1389,28 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
14201389 },
14211390
14221391 .system_lib => |system_lib| {
1392 if ((system_lib.search_strategy != prev_search_strategy or
1393 system_lib.preferred_link_mode != prev_preferred_link_mode) and
1394 self.linkage != .static)
1395 {
1396 switch (system_lib.search_strategy) {
1397 .no_fallback => switch (system_lib.preferred_link_mode) {
1398 .Dynamic => try zig_args.append("-search_dylibs_only"),
1399 .Static => try zig_args.append("-search_static_only"),
1400 },
1401 .paths_first => switch (system_lib.preferred_link_mode) {
1402 .Dynamic => try zig_args.append("-search_paths_first"),
1403 .Static => try zig_args.append("-search_paths_first_static"),
1404 },
1405 .mode_first => switch (system_lib.preferred_link_mode) {
1406 .Dynamic => try zig_args.append("-search_dylibs_first"),
1407 .Static => try zig_args.append("-search_static_first"),
1408 },
1409 }
1410 prev_search_strategy = system_lib.search_strategy;
1411 prev_preferred_link_mode = system_lib.preferred_link_mode;
1412 }
1413
14231414 const prefix: []const u8 = prefix: {
14241415 if (system_lib.needed) break :prefix "-needed-l";
14251416 if (system_lib.weak) break :prefix "-weak-l";
......@@ -1662,10 +1653,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
16621653 const size = try std.fmt.allocPrint(b.allocator, "{x}", .{pagezero_size});
16631654 try zig_args.appendSlice(&[_][]const u8{ "-pagezero_size", size });
16641655 }
1665 if (self.search_strategy) |strat| switch (strat) {
1666 .paths_first => try zig_args.append("-search_paths_first"),
1667 .dylibs_first => try zig_args.append("-search_dylibs_first"),
1668 };
16691656 if (self.headerpad_size) |headerpad_size| {
16701657 const size = try std.fmt.allocPrint(b.allocator, "{x}", .{headerpad_size});
16711658 try zig_args.appendSlice(&[_][]const u8{ "-headerpad", size });
test/link/macho/search_strategy/build.zig+7-5
......@@ -17,8 +17,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize
1717
1818 {
1919 // -search_dylibs_first
20 const exe = createScenario(b, optimize, target, "search_dylibs_first");
21 exe.search_strategy = .dylibs_first;
20 const exe = createScenario(b, optimize, target, "search_dylibs_first", .mode_first);
2221
2322 const check = exe.checkObject();
2423 check.checkStart();
......@@ -34,8 +33,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize
3433
3534 {
3635 // -search_paths_first
37 const exe = createScenario(b, optimize, target, "search_paths_first");
38 exe.search_strategy = .paths_first;
36 const exe = createScenario(b, optimize, target, "search_paths_first", .paths_first);
3937
4038 const run = b.addRunArtifact(exe);
4139 run.skip_foreign_checks = true;
......@@ -49,6 +47,7 @@ fn createScenario(
4947 optimize: std.builtin.OptimizeMode,
5048 target: std.zig.CrossTarget,
5149 name: []const u8,
50 search_strategy: std.Build.Step.Compile.SystemLib.SearchStrategy,
5251) *std.Build.Step.Compile {
5352 const static = b.addStaticLibrary(.{
5453 .name = name,
......@@ -73,7 +72,10 @@ fn createScenario(
7372 .target = target,
7473 });
7574 exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &.{} });
76 exe.linkSystemLibraryName(name);
75 exe.linkSystemLibrary2(name, .{
76 .use_pkg_config = .no,
77 .search_strategy = search_strategy,
78 });
7779 exe.linkLibC();
7880 exe.addLibraryPath(static.getEmittedBinDirectory());
7981 exe.addLibraryPath(dylib.getEmittedBinDirectory());