Skip to content

Commit 2b24dae

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

19 files changed

+578
-282
lines changed

include/swift-c/DependencyScan/DependencyScan.h

Lines changed: 22 additions & 1 deletion
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

Lines changed: 3 additions & 0 deletions
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

Lines changed: 198 additions & 171 deletions
Large diffs are not rendered by default.

include/swift/DependencyScan/DependencyScanImpl.h

Lines changed: 15 additions & 0 deletions
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

Lines changed: 5 additions & 1 deletion
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

Lines changed: 4 additions & 0 deletions
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

Lines changed: 3 additions & 3 deletions
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

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ void ModuleDependencyInfo::addModuleImports(
184184
sourceFile.getTopLevelDecls(decls);
185185
for (auto decl : decls) {
186186
auto importDecl = dyn_cast<ImportDecl>(decl);
187+
//auto unboundImport = UnboundImport(importDecl);
187188
if (!importDecl)
188189
continue;
189190

@@ -483,7 +484,7 @@ SwiftDependencyScanningService::SwiftDependencyScanningService() {
483484
}
484485

485486
bool
486-
swift::dependencies::checkImportNotTautological(const ImportPath::Module modulePath,
487+
swift::dependencies::checkImportNotTautological(const ImportPath::Module modulePath,
487488
const SourceLoc importLoc,
488489
const SourceFile &SF,
489490
bool isExported) {
@@ -509,6 +510,86 @@ swift::dependencies::checkImportNotTautological(const ImportPath::Module moduleP
509510
return false;
510511
}
511512

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

lib/ClangImporter/ClangModuleDependencyScanner.cpp

Lines changed: 9 additions & 1 deletion
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

Lines changed: 44 additions & 1 deletion
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)