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 {...@@ -585,41 +585,25 @@ pub fn linkLibrary(self: *LibExeObjStep, lib: *LibExeObjStep) void {
585}585}
586586
587pub fn isDynamicLibrary(self: *LibExeObjStep) bool {587pub 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;
589}593}
590594
591pub fn producesPdbFile(self: *LibExeObjStep) bool {595pub fn producesPdbFile(self: *LibExeObjStep) bool {
592 if (!self.target.isWindows() and !self.target.isUefi()) return false;596 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;
594 return self.isDynamicLibrary() or self.kind == .exe or self.kind == .test_exe;598 return self.isDynamicLibrary() or self.kind == .exe or self.kind == .test_exe;
595}599}
596600
597pub fn linkLibC(self: *LibExeObjStep) void {601pub fn linkLibC(self: *LibExeObjStep) void {
598 if (!self.is_linking_libc) {602 self.is_linking_libc = true;
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 }
609}603}
610604
611pub fn linkLibCpp(self: *LibExeObjStep) void {605pub fn linkLibCpp(self: *LibExeObjStep) void {
612 if (!self.is_linking_libcpp) {606 self.is_linking_libcpp = true;
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 }
623}607}
624608
625/// If the value is omitted, it is set to 1.609/// 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...@@ -762,7 +746,7 @@ pub fn runPkgConfig(self: *LibExeObjStep, lib_name: []const u8) ![]const []const
762 else => return err,746 else => return err,
763 };747 };
764748
765 var zig_args = std.ArrayList([]const u8).init(self.builder.allocator);749 var zig_args = ArrayList([]const u8).init(self.builder.allocator);
766 defer zig_args.deinit();750 defer zig_args.deinit();
767751
768 var it = mem.tokenize(u8, stdout, " \r\n\t");752 var it = mem.tokenize(u8, stdout, " \r\n\t");
...@@ -1105,21 +1089,8 @@ fn make(step: *Step) !void {...@@ -1105,21 +1089,8 @@ fn make(step: *Step) !void {
1105 try zig_args.append(try std.fmt.allocPrint(builder.allocator, "-freference-trace={d}", .{some}));1089 try zig_args.append(try std.fmt.allocPrint(builder.allocator, "-freference-trace={d}", .{some}));
1106 }1090 }
11071091
1108 if (self.use_llvm) |use_llvm| {1092 try addFlag(&zig_args, "LLVM", self.use_llvm);
1109 if (use_llvm) {1093 try addFlag(&zig_args, "LLD", self.use_lld);
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 }
11231094
1124 if (self.target.ofmt) |ofmt| {1095 if (self.target.ofmt) |ofmt| {
1125 try zig_args.append(try std.fmt.allocPrint(builder.allocator, "-ofmt={s}", .{@tagName(ofmt)}));1096 try zig_args.append(try std.fmt.allocPrint(builder.allocator, "-ofmt={s}", .{@tagName(ofmt)}));
...@@ -1137,40 +1108,24 @@ fn make(step: *Step) !void {...@@ -1137,40 +1108,24 @@ fn make(step: *Step) !void {
11371108
1138 if (self.root_src) |root_src| try zig_args.append(root_src.getPath(builder));1109 if (self.root_src) |root_src| try zig_args.append(root_src.getPath(builder));
11391110
1140 var prev_has_extra_flags = false;1111 // We will add link objects from transitive dependencies, but we want to keep
11411112 // all link objects in the same order provided.
1142 // Resolve transitive dependencies1113 // This array is used to keep self.link_objects immutable.
1143 {1114 var transitive_deps: TransitiveDeps = .{
1144 var transitive_dependencies = std.ArrayList(LinkObject).init(builder.allocator);1115 .link_objects = ArrayList(LinkObject).init(builder.allocator),
1145 defer transitive_dependencies.deinit();1116 .seen_system_libs = StringHashMap(void).init(builder.allocator),
11461117 .seen_steps = std.AutoHashMap(*const Step, void).init(builder.allocator),
1147 for (self.link_objects.items) |link_object| {1118 .is_linking_libcpp = self.is_linking_libcpp,
1148 switch (link_object) {1119 .is_linking_libc = self.is_linking_libc,
1149 .other_step => |other| {1120 .frameworks = &self.frameworks,
1150 // Inherit dependency on system libraries1121 };
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 }
11571122
1158 // Inherit dependencies on darwin frameworks1123 try transitive_deps.seen_steps.put(&self.step, {});
1159 if (!other.isDynamicLibrary()) {1124 try transitive_deps.add(self.link_objects.items);
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 }
11691125
1170 try self.link_objects.appendSlice(transitive_dependencies.items);1126 var prev_has_extra_flags = false;
1171 }
11721127
1173 for (self.link_objects.items) |link_object| {1128 for (transitive_deps.link_objects.items) |link_object| {
1174 switch (link_object) {1129 switch (link_object) {
1175 .static_path => |static_path| try zig_args.append(static_path.getPath(builder)),1130 .static_path => |static_path| try zig_args.append(static_path.getPath(builder)),
11761131
...@@ -1181,11 +1136,16 @@ fn make(step: *Step) !void {...@@ -1181,11 +1136,16 @@ fn make(step: *Step) !void {
1181 .obj => {1136 .obj => {
1182 try zig_args.append(other.getOutputSource().getPath(builder));1137 try zig_args.append(other.getOutputSource().getPath(builder));
1183 },1138 },
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
1185 const full_path_lib = other.getOutputLibSource().getPath(builder);1145 const full_path_lib = other.getOutputLibSource().getPath(builder);
1186 try zig_args.append(full_path_lib);1146 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()) {
1189 if (fs.path.dirname(full_path_lib)) |dirname| {1149 if (fs.path.dirname(full_path_lib)) |dirname| {
1190 try zig_args.append("-rpath");1150 try zig_args.append("-rpath");
1191 try zig_args.append(dirname);1151 try zig_args.append(dirname);
...@@ -1282,6 +1242,14 @@ fn make(step: *Step) !void {...@@ -1282,6 +1242,14 @@ fn make(step: *Step) !void {
1282 }1242 }
1283 }1243 }
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
1285 if (self.image_base) |image_base| {1253 if (self.image_base) |image_base| {
1286 try zig_args.append("--image-base");1254 try zig_args.append("--image-base");
1287 try zig_args.append(builder.fmt("0x{x}", .{image_base}));1255 try zig_args.append(builder.fmt("0x{x}", .{image_base}));
...@@ -1332,21 +1300,8 @@ fn make(step: *Step) !void {...@@ -1332,21 +1300,8 @@ fn make(step: *Step) !void {
13321300
1333 if (self.emit_h) try zig_args.append("-femit-h");1301 if (self.emit_h) try zig_args.append("-femit-h");
13341302
1335 if (self.strip) |strip| {1303 try addFlag(&zig_args, "strip", self.strip);
1336 if (strip) {1304 try addFlag(&zig_args, "unwind-tables", self.unwind_tables);
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 }
13501305
1351 switch (self.compress_debug_sections) {1306 switch (self.compress_debug_sections) {
1352 .none => {},1307 .none => {},
...@@ -1454,51 +1409,16 @@ fn make(step: *Step) !void {...@@ -1454,51 +1409,16 @@ fn make(step: *Step) !void {
1454 try zig_args.append("-dead_strip_dylibs");1409 try zig_args.append("-dead_strip_dylibs");
1455 }1410 }
14561411
1457 if (self.bundle_compiler_rt) |x| {1412 try addFlag(&zig_args, "compiler-rt", self.bundle_compiler_rt);
1458 if (x) {1413 try addFlag(&zig_args, "single-threaded", self.single_threaded);
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 }
1471 if (self.disable_stack_probing) {1414 if (self.disable_stack_probing) {
1472 try zig_args.append("-fno-stack-check");1415 try zig_args.append("-fno-stack-check");
1473 }1416 }
1474 if (self.stack_protector) |stack_protector| {1417 try addFlag(&zig_args, "stack-protector", self.stack_protector);
1475 if (stack_protector) {1418 try addFlag(&zig_args, "red-zone", self.red_zone);
1476 try zig_args.append("-fstack-protector");1419 try addFlag(&zig_args, "omit-frame-pointer", self.omit_frame_pointer);
1477 } else {1420 try addFlag(&zig_args, "dll-export-fns", self.dll_export_fns);
1478 try zig_args.append("-fno-stack-protector");1421
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 }
1502 if (self.disable_sanitize_c) {1422 if (self.disable_sanitize_c) {
1503 try zig_args.append("-fno-sanitize-c");1423 try zig_args.append("-fno-sanitize-c");
1504 }1424 }
...@@ -1559,7 +1479,7 @@ fn make(step: *Step) !void {...@@ -1559,7 +1479,7 @@ fn make(step: *Step) !void {
1559 try zig_args.append("-mcpu");1479 try zig_args.append("-mcpu");
1560 try zig_args.append(cross.cpu.model.name);1480 try zig_args.append(cross.cpu.model.name);
1561 } else {1481 } else {
1562 var mcpu_buffer = std.ArrayList(u8).init(builder.allocator);1482 var mcpu_buffer = ArrayList(u8).init(builder.allocator);
15631483
1564 try mcpu_buffer.writer().print("-mcpu={s}", .{cross.cpu.model.name});1484 try mcpu_buffer.writer().print("-mcpu={s}", .{cross.cpu.model.name});
15651485
...@@ -1604,11 +1524,11 @@ fn make(step: *Step) !void {...@@ -1604,11 +1524,11 @@ fn make(step: *Step) !void {
1604 }1524 }
1605 }1525 }
1606 } else {1526 } 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
1609 switch (builder.host.getExternalExecutor(self.target_info, .{1529 switch (builder.host.getExternalExecutor(self.target_info, .{
1610 .qemu_fixes_dl = need_cross_glibc and builder.glibc_runtimes_dir != null,1530 .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,
1612 })) {1532 })) {
1613 .native => {},1533 .native => {},
1614 .bad_dl, .bad_os_or_cpu => {1534 .bad_dl, .bad_os_or_cpu => {
...@@ -1803,29 +1723,9 @@ fn make(step: *Step) !void {...@@ -1803,29 +1723,9 @@ fn make(step: *Step) !void {
1803 }));1723 }));
1804 }1724 }
18051725
1806 if (self.valgrind_support) |valgrind_support| {1726 try addFlag(&zig_args, "valgrind", self.valgrind_support);
1807 if (valgrind_support) {1727 try addFlag(&zig_args, "each-lib-rpath", self.each_lib_rpath);
1808 try zig_args.append("-fvalgrind");1728 try addFlag(&zig_args, "build-id", self.build_id);
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 }
18291729
1830 if (self.override_lib_dir) |dir| {1730 if (self.override_lib_dir) |dir| {
1831 try zig_args.append("--zig-lib-dir");1731 try zig_args.append("--zig-lib-dir");
...@@ -1840,29 +1740,9 @@ fn make(step: *Step) !void {...@@ -1840,29 +1740,9 @@ fn make(step: *Step) !void {
1840 try zig_args.append(builder.pathFromRoot(dir));1740 try zig_args.append(builder.pathFromRoot(dir));
1841 }1741 }
18421742
1843 if (self.force_pic) |pic| {1743 try addFlag(&zig_args, "PIC", self.force_pic);
1844 if (pic) {1744 try addFlag(&zig_args, "PIE", self.pie);
1845 try zig_args.append("-fPIC");1745 try addFlag(&zig_args, "lto", self.want_lto);
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 }
18661746
1867 if (self.subsystem) |subsystem| {1747 if (self.subsystem) |subsystem| {
1868 try zig_args.append("--subsystem");1748 try zig_args.append("--subsystem");
...@@ -2129,3 +2009,73 @@ test "addPackage" {...@@ -2129,3 +2009,73 @@ test "addPackage" {
2129 const dupe = exe.packages.items[0];2009 const dupe = exe.packages.items[0];
2130 try std.testing.expectEqualStrings(pkg_top.name, dupe.name);2010 try std.testing.expectEqualStrings(pkg_top.name, dupe.name);
2131}2011}
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};