| ... | @@ -488,11 +488,12 @@ pub fn forceUndefinedSymbol(self: *Compile, symbol_name: []const u8) void { | ... | @@ -488,11 +488,12 @@ pub fn forceUndefinedSymbol(self: *Compile, symbol_name: []const u8) void { |
| 488 | } | 488 | } |
| 489 | | 489 | |
| 490 | /// Returns whether the library, executable, or object depends on a particular system library. | 490 | /// Returns whether the library, executable, or object depends on a particular system library. |
| | 491 | /// Includes transitive dependencies. |
| 491 | pub fn dependsOnSystemLibrary(self: *const Compile, name: []const u8) bool { | 492 | pub fn dependsOnSystemLibrary(self: *const Compile, name: []const u8) bool { |
| 492 | var is_linking_libc = false; | 493 | var is_linking_libc = false; |
| 493 | var is_linking_libcpp = false; | 494 | var is_linking_libcpp = false; |
| 494 | | 495 | |
| 495 | var it = self.root_module.iterateDependencies(self); | 496 | var it = self.root_module.iterateDependencies(self, true); |
| 496 | while (it.next()) |module| { | 497 | while (it.next()) |module| { |
| 497 | for (module.link_objects.items) |link_object| { | 498 | for (module.link_objects.items) |link_object| { |
| 498 | switch (link_object) { | 499 | switch (link_object) { |
| ... | @@ -841,7 +842,7 @@ fn appendModuleArgs(cs: *Compile, zig_args: *ArrayList([]const u8)) !void { | ... | @@ -841,7 +842,7 @@ fn appendModuleArgs(cs: *Compile, zig_args: *ArrayList([]const u8)) !void { |
| 841 | var names = std.StringHashMap(void).init(b.allocator); | 842 | var names = std.StringHashMap(void).init(b.allocator); |
| 842 | | 843 | |
| 843 | { | 844 | { |
| 844 | var it = cs.root_module.iterateDependencies(null); | 845 | var it = cs.root_module.iterateDependencies(null, false); |
| 845 | _ = it.next(); // Skip over the root module. | 846 | _ = it.next(); // Skip over the root module. |
| 846 | while (it.next()) |item| { | 847 | while (it.next()) |item| { |
| 847 | // While we're traversing the root dependencies, let's make sure that no module names | 848 | // While we're traversing the root dependencies, let's make sure that no module names |
| ... | @@ -1000,33 +1001,51 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -1000,33 +1001,51 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 1000 | | 1001 | |
| 1001 | try self.root_module.appendZigProcessFlags(&zig_args, step); | 1002 | try self.root_module.appendZigProcessFlags(&zig_args, step); |
| 1002 | | 1003 | |
| 1003 | var it = self.root_module.iterateDependencies(self); | 1004 | { |
| | 1005 | // Fully recursive iteration including dynamic libraries to detect |
| | 1006 | // libc and libc++ linkage. |
| | 1007 | var it = self.root_module.iterateDependencies(self, true); |
| | 1008 | while (it.next()) |key| { |
| | 1009 | if (key.module.link_libc == true) self.is_linking_libc = true; |
| | 1010 | if (key.module.link_libcpp == true) self.is_linking_libcpp = true; |
| | 1011 | } |
| | 1012 | } |
| | 1013 | |
| | 1014 | // For this loop, don't chase dynamic libraries because their link |
| | 1015 | // objects are already linked. |
| | 1016 | var it = self.root_module.iterateDependencies(self, false); |
| | 1017 | |
| 1004 | while (it.next()) |key| { | 1018 | while (it.next()) |key| { |
| 1005 | const module = key.module; | 1019 | const module = key.module; |
| 1006 | const compile = key.compile.?; | 1020 | const compile = key.compile.?; |
| 1007 | const dyn = compile.isDynamicLibrary(); | | |
| 1008 | | 1021 | |
| 1009 | // Inherit dependency on libc and libc++. | 1022 | // While walking transitive dependencies, if a given link object is |
| 1010 | if (module.link_libc == true) self.is_linking_libc = true; | 1023 | // already included in a library, it should not redundantly be |
| 1011 | if (module.link_libcpp == true) self.is_linking_libcpp = true; | 1024 | // placed on the linker line of the dependee. |
| | 1025 | const my_responsibility = compile == self; |
| | 1026 | const already_linked = !my_responsibility and compile.isDynamicLibrary(); |
| 1012 | | 1027 | |
| 1013 | // Inherit dependencies on darwin frameworks. | 1028 | // Inherit dependencies on darwin frameworks. |
| 1014 | if (!dyn) { | 1029 | if (!already_linked) { |
| 1015 | for (module.frameworks.keys(), module.frameworks.values()) |name, info| { | 1030 | for (module.frameworks.keys(), module.frameworks.values()) |name, info| { |
| 1016 | try frameworks.put(b.allocator, name, info); | 1031 | try frameworks.put(b.allocator, name, info); |
| 1017 | } | 1032 | } |
| 1018 | } | 1033 | } |
| 1019 | | 1034 | |
| 1020 | // Inherit dependencies on system libraries and static libraries. | 1035 | // Inherit dependencies on system libraries and static libraries. |
| 1021 | total_linker_objects += module.link_objects.items.len; | | |
| 1022 | for (module.link_objects.items) |link_object| { | 1036 | for (module.link_objects.items) |link_object| { |
| 1023 | switch (link_object) { | 1037 | switch (link_object) { |
| 1024 | .static_path => |static_path| try zig_args.append(static_path.getPath(b)), | 1038 | .static_path => |static_path| { |
| | 1039 | if (my_responsibility) { |
| | 1040 | try zig_args.append(static_path.getPath(b)); |
| | 1041 | total_linker_objects += 1; |
| | 1042 | } |
| | 1043 | }, |
| 1025 | .system_lib => |system_lib| { | 1044 | .system_lib => |system_lib| { |
| 1026 | if ((try seen_system_libs.fetchPut(b.allocator, system_lib.name, {})) != null) | 1045 | if ((try seen_system_libs.fetchPut(b.allocator, system_lib.name, {})) != null) |
| 1027 | continue; | 1046 | continue; |
| 1028 | | 1047 | |
| 1029 | if (dyn) | 1048 | if (already_linked) |
| 1030 | continue; | 1049 | continue; |
| 1031 | | 1050 | |
| 1032 | if ((system_lib.search_strategy != prev_search_strategy or | 1051 | if ((system_lib.search_strategy != prev_search_strategy or |
| ... | @@ -1088,29 +1107,36 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -1088,29 +1107,36 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 1088 | } | 1107 | } |
| 1089 | }, | 1108 | }, |
| 1090 | .other_step => |other| { | 1109 | .other_step => |other| { |
| 1091 | const included_in_lib = (compile.kind == .lib and other.kind == .obj); | | |
| 1092 | if (dyn or included_in_lib) | | |
| 1093 | continue; | | |
| 1094 | | | |
| 1095 | switch (other.kind) { | 1110 | switch (other.kind) { |
| 1096 | .exe => return step.fail("cannot link with an executable build artifact", .{}), | 1111 | .exe => return step.fail("cannot link with an executable build artifact", .{}), |
| 1097 | .@"test" => return step.fail("cannot link with a test", .{}), | 1112 | .@"test" => return step.fail("cannot link with a test", .{}), |
| 1098 | .obj => { | 1113 | .obj => { |
| 1099 | try zig_args.append(other.getEmittedBin().getPath(b)); | 1114 | const included_in_lib = !my_responsibility and |
| | 1115 | compile.kind == .lib and other.kind == .obj; |
| | 1116 | if (!already_linked and !included_in_lib) { |
| | 1117 | try zig_args.append(other.getEmittedBin().getPath(b)); |
| | 1118 | total_linker_objects += 1; |
| | 1119 | } |
| 1100 | }, | 1120 | }, |
| 1101 | .lib => l: { | 1121 | .lib => l: { |
| 1102 | if (self.isStaticLibrary() and other.isStaticLibrary()) { | 1122 | const other_produces_implib = other.producesImplib(); |
| | 1123 | const other_is_static = other_produces_implib or other.isStaticLibrary(); |
| | 1124 | |
| | 1125 | if (self.isStaticLibrary() and other_is_static) { |
| 1103 | // Avoid putting a static library inside a static library. | 1126 | // Avoid putting a static library inside a static library. |
| 1104 | break :l; | 1127 | break :l; |
| 1105 | } | 1128 | } |
| 1106 | | 1129 | |
| 1107 | // For DLLs, we gotta link against the implib. For | 1130 | // For DLLs, we must link against the implib. |
| 1108 | // everything else, we directly link against the library file. | 1131 | // For everything else, we directly link |
| 1109 | const full_path_lib = if (other.producesImplib()) | 1132 | // against the library file. |
| | 1133 | const full_path_lib = if (other_produces_implib) |
| 1110 | other.getGeneratedFilePath("generated_implib", &self.step) | 1134 | other.getGeneratedFilePath("generated_implib", &self.step) |
| 1111 | else | 1135 | else |
| 1112 | other.getGeneratedFilePath("generated_bin", &self.step); | 1136 | other.getGeneratedFilePath("generated_bin", &self.step); |
| | 1137 | |
| 1113 | try zig_args.append(full_path_lib); | 1138 | try zig_args.append(full_path_lib); |
| | 1139 | total_linker_objects += 1; |
| 1114 | | 1140 | |
| 1115 | if (other.linkage == Linkage.dynamic and | 1141 | if (other.linkage == Linkage.dynamic and |
| 1116 | self.rootModuleTarget().os.tag != .windows) | 1142 | self.rootModuleTarget().os.tag != .windows) |
| ... | @@ -1123,16 +1149,21 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -1123,16 +1149,21 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 1123 | }, | 1149 | }, |
| 1124 | } | 1150 | } |
| 1125 | }, | 1151 | }, |
| 1126 | .assembly_file => |asm_file| { | 1152 | .assembly_file => |asm_file| l: { |
| | 1153 | if (!my_responsibility) break :l; |
| | 1154 | |
| 1127 | if (prev_has_cflags) { | 1155 | if (prev_has_cflags) { |
| 1128 | try zig_args.append("-cflags"); | 1156 | try zig_args.append("-cflags"); |
| 1129 | try zig_args.append("--"); | 1157 | try zig_args.append("--"); |
| 1130 | prev_has_cflags = false; | 1158 | prev_has_cflags = false; |
| 1131 | } | 1159 | } |
| 1132 | try zig_args.append(asm_file.getPath(b)); | 1160 | try zig_args.append(asm_file.getPath(b)); |
| | 1161 | total_linker_objects += 1; |
| 1133 | }, | 1162 | }, |
| 1134 | | 1163 | |
| 1135 | .c_source_file => |c_source_file| { | 1164 | .c_source_file => |c_source_file| l: { |
| | 1165 | if (!my_responsibility) break :l; |
| | 1166 | |
| 1136 | if (c_source_file.flags.len == 0) { | 1167 | if (c_source_file.flags.len == 0) { |
| 1137 | if (prev_has_cflags) { | 1168 | if (prev_has_cflags) { |
| 1138 | try zig_args.append("-cflags"); | 1169 | try zig_args.append("-cflags"); |
| ... | @@ -1148,9 +1179,12 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -1148,9 +1179,12 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 1148 | prev_has_cflags = true; | 1179 | prev_has_cflags = true; |
| 1149 | } | 1180 | } |
| 1150 | try zig_args.append(c_source_file.file.getPath(b)); | 1181 | try zig_args.append(c_source_file.file.getPath(b)); |
| | 1182 | total_linker_objects += 1; |
| 1151 | }, | 1183 | }, |
| 1152 | | 1184 | |
| 1153 | .c_source_files => |c_source_files| { | 1185 | .c_source_files => |c_source_files| l: { |
| | 1186 | if (!my_responsibility) break :l; |
| | 1187 | |
| 1154 | if (c_source_files.flags.len == 0) { | 1188 | if (c_source_files.flags.len == 0) { |
| 1155 | if (prev_has_cflags) { | 1189 | if (prev_has_cflags) { |
| 1156 | try zig_args.append("-cflags"); | 1190 | try zig_args.append("-cflags"); |
| ... | @@ -1165,6 +1199,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -1165,6 +1199,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 1165 | try zig_args.append("--"); | 1199 | try zig_args.append("--"); |
| 1166 | prev_has_cflags = true; | 1200 | prev_has_cflags = true; |
| 1167 | } | 1201 | } |
| | 1202 | |
| 1168 | if (c_source_files.dependency) |dep| { | 1203 | if (c_source_files.dependency) |dep| { |
| 1169 | for (c_source_files.files) |file| { | 1204 | for (c_source_files.files) |file| { |
| 1170 | try zig_args.append(dep.builder.pathFromRoot(file)); | 1205 | try zig_args.append(dep.builder.pathFromRoot(file)); |
| ... | @@ -1174,9 +1209,12 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -1174,9 +1209,12 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 1174 | try zig_args.append(b.pathFromRoot(file)); | 1209 | try zig_args.append(b.pathFromRoot(file)); |
| 1175 | } | 1210 | } |
| 1176 | } | 1211 | } |
| | 1212 | total_linker_objects += c_source_files.files.len; |
| 1177 | }, | 1213 | }, |
| 1178 | | 1214 | |
| 1179 | .win32_resource_file => |rc_source_file| { | 1215 | .win32_resource_file => |rc_source_file| l: { |
| | 1216 | if (!my_responsibility) break :l; |
| | 1217 | |
| 1180 | if (rc_source_file.flags.len == 0) { | 1218 | if (rc_source_file.flags.len == 0) { |
| 1181 | if (prev_has_rcflags) { | 1219 | if (prev_has_rcflags) { |
| 1182 | try zig_args.append("-rcflags"); | 1220 | try zig_args.append("-rcflags"); |
| ... | @@ -1192,6 +1230,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -1192,6 +1230,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 1192 | prev_has_rcflags = true; | 1230 | prev_has_rcflags = true; |
| 1193 | } | 1231 | } |
| 1194 | try zig_args.append(rc_source_file.file.getPath(b)); | 1232 | try zig_args.append(rc_source_file.file.getPath(b)); |
| | 1233 | total_linker_objects += 1; |
| 1195 | }, | 1234 | }, |
| 1196 | } | 1235 | } |
| 1197 | } | 1236 | } |