authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-01-21 02:54:25-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-01-21 02:54:25-05:00
log38eebf3c4d68239e1d29118234a3165355a3a5fc
tree2852950958833f6d416d3930921c4f68c46fb7db
parent74b72a766de96c7c70fc8a02d3e2ee3cd353f225
parent6d38dba72e9f3d32ddc73975305d7fc95ed7531a
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #14392 from ziglang/zig-build-transitive-deps

std.build.LibExeObjStep: better handle transitive deps

1 files changed, 129 insertions(+), 179 deletions(-)

lib/std/build/LibExeObjStep.zig+129-179
......@@ -585,41 +585,25 @@ pub fn linkLibrary(self: *LibExeObjStep, lib: *LibExeObjStep) void {
585585}
586586
587587pub fn isDynamicLibrary(self: *LibExeObjStep) bool {
588 return self.kind == .lib and self.linkage != null and self.linkage.? == .dynamic;
588 return self.kind == .lib and self.linkage == Linkage.dynamic;
589}
590
591pub fn isStaticLibrary(self: *LibExeObjStep) bool {
592 return self.kind == .lib and self.linkage != Linkage.dynamic;
589593}
590594
591595pub fn producesPdbFile(self: *LibExeObjStep) bool {
592596 if (!self.target.isWindows() and !self.target.isUefi()) return false;
593 if (self.strip != null and self.strip.?) return false;
597 if (self.strip == true) return false;
594598 return self.isDynamicLibrary() or self.kind == .exe or self.kind == .test_exe;
595599}
596600
597601pub fn linkLibC(self: *LibExeObjStep) void {
598 if (!self.is_linking_libc) {
599 self.is_linking_libc = true;
600 self.link_objects.append(.{
601 .system_lib = .{
602 .name = "c",
603 .needed = false,
604 .weak = false,
605 .use_pkg_config = .no,
606 },
607 }) catch unreachable;
608 }
602 self.is_linking_libc = true;
609603}
610604
611605pub fn linkLibCpp(self: *LibExeObjStep) void {
612 if (!self.is_linking_libcpp) {
613 self.is_linking_libcpp = true;
614 self.link_objects.append(.{
615 .system_lib = .{
616 .name = "c++",
617 .needed = false,
618 .weak = false,
619 .use_pkg_config = .no,
620 },
621 }) catch unreachable;
622 }
606 self.is_linking_libcpp = true;
623607}
624608
625609/// If the value is omitted, it is set to 1.
......@@ -762,7 +746,7 @@ pub fn runPkgConfig(self: *LibExeObjStep, lib_name: []const u8) ![]const []const
762746 else => return err,
763747 };
764748
765 var zig_args = std.ArrayList([]const u8).init(self.builder.allocator);
749 var zig_args = ArrayList([]const u8).init(self.builder.allocator);
766750 defer zig_args.deinit();
767751
768752 var it = mem.tokenize(u8, stdout, " \r\n\t");
......@@ -1105,21 +1089,8 @@ fn make(step: *Step) !void {
11051089 try zig_args.append(try std.fmt.allocPrint(builder.allocator, "-freference-trace={d}", .{some}));
11061090 }
11071091
1108 if (self.use_llvm) |use_llvm| {
1109 if (use_llvm) {
1110 try zig_args.append("-fLLVM");
1111 } else {
1112 try zig_args.append("-fno-LLVM");
1113 }
1114 }
1115
1116 if (self.use_lld) |use_lld| {
1117 if (use_lld) {
1118 try zig_args.append("-fLLD");
1119 } else {
1120 try zig_args.append("-fno-LLD");
1121 }
1122 }
1092 try addFlag(&zig_args, "LLVM", self.use_llvm);
1093 try addFlag(&zig_args, "LLD", self.use_lld);
11231094
11241095 if (self.target.ofmt) |ofmt| {
11251096 try zig_args.append(try std.fmt.allocPrint(builder.allocator, "-ofmt={s}", .{@tagName(ofmt)}));
......@@ -1137,40 +1108,24 @@ fn make(step: *Step) !void {
11371108
11381109 if (self.root_src) |root_src| try zig_args.append(root_src.getPath(builder));
11391110
1140 var prev_has_extra_flags = false;
1141
1142 // Resolve transitive dependencies
1143 {
1144 var transitive_dependencies = std.ArrayList(LinkObject).init(builder.allocator);
1145 defer transitive_dependencies.deinit();
1146
1147 for (self.link_objects.items) |link_object| {
1148 switch (link_object) {
1149 .other_step => |other| {
1150 // Inherit dependency on system libraries
1151 for (other.link_objects.items) |other_link_object| {
1152 switch (other_link_object) {
1153 .system_lib => try transitive_dependencies.append(other_link_object),
1154 else => continue,
1155 }
1156 }
1111 // We will add link objects from transitive dependencies, but we want to keep
1112 // all link objects in the same order provided.
1113 // This array is used to keep self.link_objects immutable.
1114 var transitive_deps: TransitiveDeps = .{
1115 .link_objects = ArrayList(LinkObject).init(builder.allocator),
1116 .seen_system_libs = StringHashMap(void).init(builder.allocator),
1117 .seen_steps = std.AutoHashMap(*const Step, void).init(builder.allocator),
1118 .is_linking_libcpp = self.is_linking_libcpp,
1119 .is_linking_libc = self.is_linking_libc,
1120 .frameworks = &self.frameworks,
1121 };
11571122
1158 // Inherit dependencies on darwin frameworks
1159 if (!other.isDynamicLibrary()) {
1160 var it = other.frameworks.iterator();
1161 while (it.next()) |framework| {
1162 self.frameworks.put(framework.key_ptr.*, framework.value_ptr.*) catch unreachable;
1163 }
1164 }
1165 },
1166 else => continue,
1167 }
1168 }
1123 try transitive_deps.seen_steps.put(&self.step, {});
1124 try transitive_deps.add(self.link_objects.items);
11691125
1170 try self.link_objects.appendSlice(transitive_dependencies.items);
1171 }
1126 var prev_has_extra_flags = false;
11721127
1173 for (self.link_objects.items) |link_object| {
1128 for (transitive_deps.link_objects.items) |link_object| {
11741129 switch (link_object) {
11751130 .static_path => |static_path| try zig_args.append(static_path.getPath(builder)),
11761131
......@@ -1181,11 +1136,16 @@ fn make(step: *Step) !void {
11811136 .obj => {
11821137 try zig_args.append(other.getOutputSource().getPath(builder));
11831138 },
1184 .lib => {
1139 .lib => l: {
1140 if (self.isStaticLibrary() and other.isStaticLibrary()) {
1141 // Avoid putting a static library inside a static library.
1142 break :l;
1143 }
1144
11851145 const full_path_lib = other.getOutputLibSource().getPath(builder);
11861146 try zig_args.append(full_path_lib);
11871147
1188 if (other.linkage != null and other.linkage.? == .dynamic and !self.target.isWindows()) {
1148 if (other.linkage == Linkage.dynamic and !self.target.isWindows()) {
11891149 if (fs.path.dirname(full_path_lib)) |dirname| {
11901150 try zig_args.append("-rpath");
11911151 try zig_args.append(dirname);
......@@ -1282,6 +1242,14 @@ fn make(step: *Step) !void {
12821242 }
12831243 }
12841244
1245 if (transitive_deps.is_linking_libcpp) {
1246 try zig_args.append("-lc++");
1247 }
1248
1249 if (transitive_deps.is_linking_libc) {
1250 try zig_args.append("-lc");
1251 }
1252
12851253 if (self.image_base) |image_base| {
12861254 try zig_args.append("--image-base");
12871255 try zig_args.append(builder.fmt("0x{x}", .{image_base}));
......@@ -1332,21 +1300,8 @@ fn make(step: *Step) !void {
13321300
13331301 if (self.emit_h) try zig_args.append("-femit-h");
13341302
1335 if (self.strip) |strip| {
1336 if (strip) {
1337 try zig_args.append("-fstrip");
1338 } else {
1339 try zig_args.append("-fno-strip");
1340 }
1341 }
1342
1343 if (self.unwind_tables) |unwind_tables| {
1344 if (unwind_tables) {
1345 try zig_args.append("-funwind-tables");
1346 } else {
1347 try zig_args.append("-fno-unwind-tables");
1348 }
1349 }
1303 try addFlag(&zig_args, "strip", self.strip);
1304 try addFlag(&zig_args, "unwind-tables", self.unwind_tables);
13501305
13511306 switch (self.compress_debug_sections) {
13521307 .none => {},
......@@ -1454,51 +1409,16 @@ fn make(step: *Step) !void {
14541409 try zig_args.append("-dead_strip_dylibs");
14551410 }
14561411
1457 if (self.bundle_compiler_rt) |x| {
1458 if (x) {
1459 try zig_args.append("-fcompiler-rt");
1460 } else {
1461 try zig_args.append("-fno-compiler-rt");
1462 }
1463 }
1464 if (self.single_threaded) |single_threaded| {
1465 if (single_threaded) {
1466 try zig_args.append("-fsingle-threaded");
1467 } else {
1468 try zig_args.append("-fno-single-threaded");
1469 }
1470 }
1412 try addFlag(&zig_args, "compiler-rt", self.bundle_compiler_rt);
1413 try addFlag(&zig_args, "single-threaded", self.single_threaded);
14711414 if (self.disable_stack_probing) {
14721415 try zig_args.append("-fno-stack-check");
14731416 }
1474 if (self.stack_protector) |stack_protector| {
1475 if (stack_protector) {
1476 try zig_args.append("-fstack-protector");
1477 } else {
1478 try zig_args.append("-fno-stack-protector");
1479 }
1480 }
1481 if (self.red_zone) |red_zone| {
1482 if (red_zone) {
1483 try zig_args.append("-mred-zone");
1484 } else {
1485 try zig_args.append("-mno-red-zone");
1486 }
1487 }
1488 if (self.omit_frame_pointer) |omit_frame_pointer| {
1489 if (omit_frame_pointer) {
1490 try zig_args.append("-fomit-frame-pointer");
1491 } else {
1492 try zig_args.append("-fno-omit-frame-pointer");
1493 }
1494 }
1495 if (self.dll_export_fns) |dll_export_fns| {
1496 if (dll_export_fns) {
1497 try zig_args.append("-fdll-export-fns");
1498 } else {
1499 try zig_args.append("-fno-dll-export-fns");
1500 }
1501 }
1417 try addFlag(&zig_args, "stack-protector", self.stack_protector);
1418 try addFlag(&zig_args, "red-zone", self.red_zone);
1419 try addFlag(&zig_args, "omit-frame-pointer", self.omit_frame_pointer);
1420 try addFlag(&zig_args, "dll-export-fns", self.dll_export_fns);
1421
15021422 if (self.disable_sanitize_c) {
15031423 try zig_args.append("-fno-sanitize-c");
15041424 }
......@@ -1559,7 +1479,7 @@ fn make(step: *Step) !void {
15591479 try zig_args.append("-mcpu");
15601480 try zig_args.append(cross.cpu.model.name);
15611481 } else {
1562 var mcpu_buffer = std.ArrayList(u8).init(builder.allocator);
1482 var mcpu_buffer = ArrayList(u8).init(builder.allocator);
15631483
15641484 try mcpu_buffer.writer().print("-mcpu={s}", .{cross.cpu.model.name});
15651485
......@@ -1604,11 +1524,11 @@ fn make(step: *Step) !void {
16041524 }
16051525 }
16061526 } else {
1607 const need_cross_glibc = self.target.isGnuLibC() and self.is_linking_libc;
1527 const need_cross_glibc = self.target.isGnuLibC() and transitive_deps.is_linking_libc;
16081528
16091529 switch (builder.host.getExternalExecutor(self.target_info, .{
16101530 .qemu_fixes_dl = need_cross_glibc and builder.glibc_runtimes_dir != null,
1611 .link_libc = self.is_linking_libc,
1531 .link_libc = transitive_deps.is_linking_libc,
16121532 })) {
16131533 .native => {},
16141534 .bad_dl, .bad_os_or_cpu => {
......@@ -1803,29 +1723,9 @@ fn make(step: *Step) !void {
18031723 }));
18041724 }
18051725
1806 if (self.valgrind_support) |valgrind_support| {
1807 if (valgrind_support) {
1808 try zig_args.append("-fvalgrind");
1809 } else {
1810 try zig_args.append("-fno-valgrind");
1811 }
1812 }
1813
1814 if (self.each_lib_rpath) |each_lib_rpath| {
1815 if (each_lib_rpath) {
1816 try zig_args.append("-feach-lib-rpath");
1817 } else {
1818 try zig_args.append("-fno-each-lib-rpath");
1819 }
1820 }
1821
1822 if (self.build_id) |build_id| {
1823 if (build_id) {
1824 try zig_args.append("-fbuild-id");
1825 } else {
1826 try zig_args.append("-fno-build-id");
1827 }
1828 }
1726 try addFlag(&zig_args, "valgrind", self.valgrind_support);
1727 try addFlag(&zig_args, "each-lib-rpath", self.each_lib_rpath);
1728 try addFlag(&zig_args, "build-id", self.build_id);
18291729
18301730 if (self.override_lib_dir) |dir| {
18311731 try zig_args.append("--zig-lib-dir");
......@@ -1840,29 +1740,9 @@ fn make(step: *Step) !void {
18401740 try zig_args.append(builder.pathFromRoot(dir));
18411741 }
18421742
1843 if (self.force_pic) |pic| {
1844 if (pic) {
1845 try zig_args.append("-fPIC");
1846 } else {
1847 try zig_args.append("-fno-PIC");
1848 }
1849 }
1850
1851 if (self.pie) |pie| {
1852 if (pie) {
1853 try zig_args.append("-fPIE");
1854 } else {
1855 try zig_args.append("-fno-PIE");
1856 }
1857 }
1858
1859 if (self.want_lto) |lto| {
1860 if (lto) {
1861 try zig_args.append("-flto");
1862 } else {
1863 try zig_args.append("-fno-lto");
1864 }
1865 }
1743 try addFlag(&zig_args, "PIC", self.force_pic);
1744 try addFlag(&zig_args, "PIE", self.pie);
1745 try addFlag(&zig_args, "lto", self.want_lto);
18661746
18671747 if (self.subsystem) |subsystem| {
18681748 try zig_args.append("--subsystem");
......@@ -2129,3 +2009,73 @@ test "addPackage" {
21292009 const dupe = exe.packages.items[0];
21302010 try std.testing.expectEqualStrings(pkg_top.name, dupe.name);
21312011}
2012
2013fn addFlag(args: *ArrayList([]const u8), comptime name: []const u8, opt: ?bool) !void {
2014 const cond = opt orelse return;
2015 try args.ensureUnusedCapacity(1);
2016 if (cond) {
2017 args.appendAssumeCapacity("-f" ++ name);
2018 } else {
2019 args.appendAssumeCapacity("-fno-" ++ name);
2020 }
2021}
2022
2023const TransitiveDeps = struct {
2024 link_objects: ArrayList(LinkObject),
2025 seen_system_libs: StringHashMap(void),
2026 seen_steps: std.AutoHashMap(*const Step, void),
2027 is_linking_libcpp: bool,
2028 is_linking_libc: bool,
2029 frameworks: *StringHashMap(FrameworkLinkInfo),
2030
2031 fn add(td: *TransitiveDeps, link_objects: []const LinkObject) !void {
2032 try td.link_objects.ensureUnusedCapacity(link_objects.len);
2033
2034 for (link_objects) |link_object| {
2035 try td.link_objects.append(link_object);
2036 switch (link_object) {
2037 .other_step => |other| try addInner(td, other, other.isDynamicLibrary()),
2038 else => {},
2039 }
2040 }
2041 }
2042
2043 fn addInner(td: *TransitiveDeps, other: *LibExeObjStep, dyn: bool) !void {
2044 // Inherit dependency on libc and libc++
2045 td.is_linking_libcpp = td.is_linking_libcpp or other.is_linking_libcpp;
2046 td.is_linking_libc = td.is_linking_libc or other.is_linking_libc;
2047
2048 // Inherit dependencies on darwin frameworks
2049 if (!dyn) {
2050 var it = other.frameworks.iterator();
2051 while (it.next()) |framework| {
2052 try td.frameworks.put(framework.key_ptr.*, framework.value_ptr.*);
2053 }
2054 }
2055
2056 // Inherit dependencies on system libraries and static libraries.
2057 for (other.link_objects.items) |other_link_object| {
2058 switch (other_link_object) {
2059 .system_lib => |system_lib| {
2060 if ((try td.seen_system_libs.fetchPut(system_lib.name, {})) != null)
2061 continue;
2062
2063 if (dyn)
2064 continue;
2065
2066 try td.link_objects.append(other_link_object);
2067 },
2068 .other_step => |inner_other| {
2069 if ((try td.seen_steps.fetchPut(&inner_other.step, {})) != null)
2070 continue;
2071
2072 if (!dyn)
2073 try td.link_objects.append(other_link_object);
2074
2075 try addInner(td, inner_other, dyn or inner_other.isDynamicLibrary());
2076 },
2077 else => continue,
2078 }
2079 }
2080 }
2081};