Skip to content

Commit 6f5751a

Browse files
committed
[Dependency Scanning] Collect and report each module dependency's Link Libraries
1 parent 7e6862b commit 6f5751a

30 files changed

+632
-290
lines changed

include/swift-c/DependencyScan/DependencyScan.h

+22-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
/// SWIFTSCAN_VERSION_MINOR should increase when there are API additions.
2626
/// SWIFTSCAN_VERSION_MAJOR is intended for "major" source/ABI breaking changes.
2727
#define SWIFTSCAN_VERSION_MAJOR 0
28-
#define SWIFTSCAN_VERSION_MINOR 9
28+
#define SWIFTSCAN_VERSION_MINOR 10
2929

3030
SWIFTSCAN_BEGIN_DECLS
3131

@@ -46,6 +46,9 @@ typedef struct swiftscan_module_details_s *swiftscan_module_details_t;
4646
/// Opaque container to a dependency info of a given module.
4747
typedef struct swiftscan_dependency_info_s *swiftscan_dependency_info_t;
4848

49+
/// Opaque container to a link library info.
50+
typedef struct swiftscan_link_library_info_s *swiftscan_link_library_info_t;
51+
4952
/// Opaque container to an overall result of a dependency scan.
5053
typedef struct swiftscan_dependency_graph_s *swiftscan_dependency_graph_t;
5154

@@ -64,6 +67,12 @@ typedef struct {
6467
size_t count;
6568
} swiftscan_dependency_set_t;
6669

70+
/// Set of linked libraries
71+
typedef struct {
72+
swiftscan_link_library_info_t *link_libraries;
73+
size_t count;
74+
} swiftscan_link_library_set_t;
75+
6776
typedef enum {
6877
SWIFTSCAN_DIAGNOSTIC_SEVERITY_ERROR = 0,
6978
SWIFTSCAN_DIAGNOSTIC_SEVERITY_WARNING = 1,
@@ -127,9 +136,21 @@ swiftscan_module_info_get_source_files(swiftscan_dependency_info_t info);
127136
SWIFTSCAN_PUBLIC swiftscan_string_set_t *
128137
swiftscan_module_info_get_direct_dependencies(swiftscan_dependency_info_t info);
129138

139+
SWIFTSCAN_PUBLIC swiftscan_link_library_set_t *
140+
swiftscan_module_info_get_link_libraries(swiftscan_dependency_info_t info);
141+
130142
SWIFTSCAN_PUBLIC swiftscan_module_details_t
131143
swiftscan_module_info_get_details(swiftscan_dependency_info_t info);
132144

145+
//=== Link Library Info Functions ------------------------------------===//
146+
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
147+
swiftscan_link_library_info_get_link_name(
148+
swiftscan_link_library_info_t info);
149+
SWIFTSCAN_PUBLIC bool swiftscan_link_library_info_get_is_framework(
150+
swiftscan_link_library_info_t info);
151+
SWIFTSCAN_PUBLIC bool swiftscan_link_library_info_get_should_force_load(
152+
swiftscan_link_library_info_t info);
153+
133154
//=== Dependency Module Info Details Functions ----------------------------===//
134155

135156
SWIFTSCAN_PUBLIC swiftscan_dependency_info_kind_t

include/swift/AST/Import.h

+3
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
namespace swift {
3737
class ASTContext;
3838
class ModuleDecl;
39+
class ImportDecl;
3940

4041
// MARK: - Fundamental import enums
4142

@@ -102,6 +103,8 @@ using ImportOptions = OptionSet<ImportFlags>;
102103

103104
void simple_display(llvm::raw_ostream &out, ImportOptions options);
104105

106+
ImportOptions getImportOptions(ImportDecl *ID);
107+
105108
// MARK: - Import Paths
106109

107110
namespace detail {

include/swift/AST/ModuleDependencies.h

+196-171
Large diffs are not rendered by default.

include/swift/DependencyScan/DependencyScanImpl.h

+15
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,19 @@ struct swiftscan_dependency_info_s {
6060
*/
6161
swiftscan_string_set_t *direct_dependencies;
6262

63+
/// The list of link libraries for this module.
64+
swiftscan_link_library_set_t *link_libraries;
65+
6366
/// Specific details of a particular kind of module.
6467
swiftscan_module_details_t details;
6568
};
6669

70+
struct swiftscan_link_library_info_s {
71+
swiftscan_string_ref_t name;
72+
bool isFramework;
73+
bool forceLoad;
74+
};
75+
6776
/// Swift modules to be built from a module interface, may have a bridging
6877
/// header.
6978
typedef struct {
@@ -103,6 +112,9 @@ typedef struct {
103112
/// A flag to indicate whether or not this module is a framework.
104113
bool is_framework;
105114

115+
/// A flag that indicates this dependency is associated with a static archive
116+
bool is_static;
117+
106118
/// The CASID for CASFileSystemRoot
107119
swiftscan_string_ref_t cas_fs_root_id;
108120

@@ -140,6 +152,9 @@ typedef struct {
140152
/// A flag to indicate whether or not this module is a framework.
141153
bool is_framework;
142154

155+
/// A flag that indicates this dependency is associated with a static archive
156+
bool is_static;
157+
143158
/// ModuleCacheKey
144159
swiftscan_string_ref_t module_cache_key;
145160
} swiftscan_swift_binary_details_t;

include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ using ContextHashIDField = IdentifierIDField;
5555
using IsFrameworkField = BCFixed<1>;
5656
/// A bit that indicates whether or not a module is a system module
5757
using IsSystemField = BCFixed<1>;
58+
/// A bit that indicates whether or not a module is that of a static archive
59+
using IsStaticField = BCFixed<1>;
5860

5961
/// Arrays of various identifiers, distinguished for readability
6062
using IdentifierIDArryField = llvm::BCArray<IdentifierIDField>;
@@ -140,10 +142,11 @@ using SwiftInterfaceModuleDetailsLayout =
140142
FlagIDArrayIDField, // extraPCMArgs
141143
ContextHashIDField, // contextHash
142144
IsFrameworkField, // isFramework
145+
IsStaticField, // isStatic
143146
FileIDField, // bridgingHeaderFile
144147
FileIDArrayIDField, // sourceFiles
145148
FileIDArrayIDField, // bridgingSourceFiles
146-
IdentifierIDField, // bridgingModuleDependencies
149+
IdentifierIDField, // bridgingModuleDependencies
147150
DependencyIDArrayIDField, // swiftOverlayDependencies
148151
IdentifierIDField, // CASFileSystemRootID
149152
IdentifierIDField, // bridgingHeaderIncludeTree
@@ -174,6 +177,7 @@ using SwiftBinaryModuleDetailsLayout =
174177
IdentifierIDField, // headerModuleDependencies
175178
FileIDArrayIDField, // headerSourceFiles
176179
IsFrameworkField, // isFramework
180+
IsStaticField, // isStatic
177181
IdentifierIDField // moduleCacheKey
178182
>;
179183

include/swift/Option/Options.td

+4
Original file line numberDiff line numberDiff line change
@@ -1370,6 +1370,10 @@ def explain_module_dependency : Separate<["-"], "explain-module-dependency">,
13701370
Flags<[NewDriverOnlyOption]>,
13711371
HelpText<"Emit remark/notes describing why compilation may depend on a module with a given name.">;
13721372

1373+
def explicit_auto_linking : Flag<["-"], "explicit-auto-linking">,
1374+
Flags<[NewDriverOnlyOption]>,
1375+
HelpText<"Instead of linker-load directives, have the driver specify all link dependencies on the linker invocation. Requires '-explicit-module-build'.">;
1376+
13731377
def min_inlining_target_version : Separate<["-"], "target-min-inlining-version">,
13741378
Flags<[FrontendOption, ModuleInterfaceOption]>,
13751379
HelpText<"Require inlinable code with no '@available' attribute to back-deploy "

lib/AST/ConformanceLookupTable.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -306,9 +306,9 @@ void ConformanceLookupTable::updateLookupTable(NominalTypeDecl *nominal,
306306
if (!proto)
307307
continue;
308308
auto kp = proto->getKnownProtocolKind();
309-
assert(!found.isSuppressed ||
310-
kp.has_value() &&
311-
"suppressed conformance for non-known protocol!?");
309+
assert(!found.isSuppressed ||
310+
kp.has_value() &&
311+
"suppressed conformance for non-known protocol!?");
312312
if (!found.isSuppressed) {
313313
addProtocol(proto, found.Loc,
314314
source.withUncheckedLoc(found.uncheckedLoc)

lib/AST/ModuleDependencies.cpp

+80-1
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ SwiftDependencyScanningService::SwiftDependencyScanningService() {
483483
}
484484

485485
bool
486-
swift::dependencies::checkImportNotTautological(const ImportPath::Module modulePath,
486+
swift::dependencies::checkImportNotTautological(const ImportPath::Module modulePath,
487487
const SourceLoc importLoc,
488488
const SourceFile &SF,
489489
bool isExported) {
@@ -509,6 +509,85 @@ swift::dependencies::checkImportNotTautological(const ImportPath::Module moduleP
509509
return false;
510510
}
511511

512+
void
513+
swift::dependencies::registerCxxInteropLibraries(
514+
const llvm::Triple &Target,
515+
StringRef mainModuleName,
516+
bool hasStaticCxx, bool hasStaticCxxStdlib,
517+
std::function<void(const LinkLibrary&)> RegistrationCallback) {
518+
if (Target.isOSDarwin())
519+
RegistrationCallback(LinkLibrary("c++", LibraryKind::Library));
520+
else if (Target.isOSLinux())
521+
RegistrationCallback(LinkLibrary("stdc++", LibraryKind::Library));
522+
523+
// Do not try to link Cxx with itself.
524+
if (mainModuleName != "Cxx") {
525+
RegistrationCallback(LinkLibrary(Target.isOSWindows() && hasStaticCxx
526+
? "libswiftCxx"
527+
: "swiftCxx",
528+
LibraryKind::Library));
529+
}
530+
531+
// Do not try to link CxxStdlib with the C++ standard library, Cxx or
532+
// itself.
533+
if (llvm::none_of(llvm::ArrayRef{"Cxx", "CxxStdlib", "std"},
534+
[mainModuleName](StringRef Name) {
535+
return mainModuleName == Name;
536+
})) {
537+
// Only link with CxxStdlib on platforms where the overlay is available.
538+
switch (Target.getOS()) {
539+
case llvm::Triple::Linux:
540+
if (!Target.isAndroid())
541+
RegistrationCallback(LinkLibrary("swiftCxxStdlib",
542+
LibraryKind::Library));
543+
break;
544+
case llvm::Triple::Win32: {
545+
RegistrationCallback(
546+
LinkLibrary(hasStaticCxxStdlib ? "libswiftCxxStdlib" : "swiftCxxStdlib",
547+
LibraryKind::Library));
548+
break;
549+
}
550+
default:
551+
if (Target.isOSDarwin())
552+
RegistrationCallback(LinkLibrary("swiftCxxStdlib",
553+
LibraryKind::Library));
554+
break;
555+
}
556+
}
557+
}
558+
559+
void
560+
swift::dependencies::registerBackDeployLibraries(
561+
const IRGenOptions &IRGenOpts,
562+
std::function<void(const LinkLibrary&)> RegistrationCallback) {
563+
auto addBackDeployLib = [&](llvm::VersionTuple version,
564+
StringRef libraryName, bool forceLoad) {
565+
std::optional<llvm::VersionTuple> compatibilityVersion;
566+
if (libraryName == "swiftCompatibilityDynamicReplacements") {
567+
compatibilityVersion = IRGenOpts.
568+
AutolinkRuntimeCompatibilityDynamicReplacementLibraryVersion;
569+
} else if (libraryName == "swiftCompatibilityConcurrency") {
570+
compatibilityVersion =
571+
IRGenOpts.AutolinkRuntimeCompatibilityConcurrencyLibraryVersion;
572+
} else {
573+
compatibilityVersion = IRGenOpts.
574+
AutolinkRuntimeCompatibilityLibraryVersion;
575+
}
576+
577+
if (!compatibilityVersion)
578+
return;
579+
580+
if (*compatibilityVersion > version)
581+
return;
582+
583+
RegistrationCallback({libraryName, LibraryKind::Library, forceLoad});
584+
};
585+
586+
#define BACK_DEPLOYMENT_LIB(Version, Filter, LibraryName, ForceLoad) \
587+
addBackDeployLib(llvm::VersionTuple Version, LibraryName, ForceLoad);
588+
#include "swift/Frontend/BackDeploymentLibs.def"
589+
}
590+
512591
void SwiftDependencyTracker::addCommonSearchPathDeps(
513592
const SearchPathOptions &Opts) {
514593
// Add SDKSetting file.

lib/ClangImporter/ClangModuleDependencyScanner.cpp

+9-1
Original file line numberDiff line numberDiff line change
@@ -285,12 +285,20 @@ ModuleDependencyVector ClangImporter::bridgeClangModuleDependencies(
285285
if (Mapper)
286286
Mapper->mapInPlace(mappedPCMPath);
287287

288+
std::vector<LinkLibrary> LinkLibraries;
289+
if (!clangModuleDep.UseExportAsModuleLinkName)
290+
for (const auto &ll : clangModuleDep.LinkLibraries)
291+
LinkLibraries.push_back(
292+
{ll.Library,
293+
ll.IsFramework ? LibraryKind::Framework : LibraryKind::Library});
294+
288295
// Module-level dependencies.
289296
llvm::StringSet<> alreadyAddedModules;
290297
auto dependencies = ModuleDependencyInfo::forClangModule(
291298
pcmPath, mappedPCMPath, clangModuleDep.ClangModuleMapFile,
292299
clangModuleDep.ID.ContextHash, swiftArgs, fileDeps, capturedPCMArgs,
293-
RootID, IncludeTree, /*module-cache-key*/ "", clangModuleDep.IsSystem);
300+
LinkLibraries, RootID, IncludeTree, /*module-cache-key*/ "",
301+
clangModuleDep.IsSystem);
294302
for (const auto &moduleName : clangModuleDep.ClangModuleDeps) {
295303
dependencies.addModuleImport(moduleName.ModuleName, &alreadyAddedModules);
296304
// It is safe to assume that all dependencies of a Clang module are Clang modules.

lib/DependencyScan/DependencyScanJSON.cpp

+44-1
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,46 @@ static void writeDependencies(llvm::raw_ostream &out,
202202
out << "\n";
203203
}
204204

205+
void writeLinkLibraries(llvm::raw_ostream &out,
206+
const swiftscan_link_library_set_t *link_libraries,
207+
unsigned indentLevel, bool trailingComma) {
208+
out.indent(indentLevel * 2);
209+
out << "\"linkLibraries\": ";
210+
out << "[\n";
211+
212+
for (size_t i = 0; i < link_libraries->count; ++i) {
213+
const auto &llInfo = *link_libraries->link_libraries[i];
214+
out.indent((indentLevel + 1) * 2);
215+
out << "{\n";
216+
auto entryIndentLevel = ((indentLevel + 2) * 2);
217+
out.indent(entryIndentLevel);
218+
out << "\"linkName\": ";
219+
writeJSONValue(out, llInfo.name, indentLevel);
220+
out << ",\n";
221+
out.indent(entryIndentLevel);
222+
out << "\"isFramework\": ";
223+
writeJSONValue(out, llInfo.isFramework, entryIndentLevel);
224+
out << ",\n";
225+
out.indent(entryIndentLevel);
226+
out << "\"shouldForceLoad\": ";
227+
writeJSONValue(out, llInfo.forceLoad, entryIndentLevel);
228+
out << "\n";
229+
out.indent((indentLevel + 1) * 2);
230+
out << "}";
231+
if (i != link_libraries->count - 1) {
232+
out << ",";
233+
}
234+
out << "\n";
235+
}
236+
237+
out.indent(indentLevel * 2);
238+
out << "]";
239+
240+
if (trailingComma)
241+
out << ",";
242+
out << "\n";
243+
}
244+
205245
static const swiftscan_swift_textual_details_t *
206246
getAsTextualDependencyModule(swiftscan_module_details_t details) {
207247
if (details->kind == SWIFTSCAN_DEPENDENCY_INFO_SWIFT_TEXTUAL)
@@ -295,10 +335,13 @@ void writeJSON(llvm::raw_ostream &out,
295335
}
296336

297337
// Direct dependencies.
298-
if (swiftTextualDeps || swiftBinaryDeps || clangDeps)
338+
if (swiftTextualDeps || swiftBinaryDeps || clangDeps) {
299339
writeDependencies(out, directDependencies,
300340
"directDependencies", 3,
301341
/*trailingComma=*/true);
342+
writeLinkLibraries(out, moduleInfo.link_libraries,
343+
3, /*trailingComma=*/true);
344+
}
302345
// Swift and Clang-specific details.
303346
out.indent(3 * 2);
304347
out << "\"details\": {\n";

0 commit comments

Comments
 (0)