Skip to content

Commit e6a1db7

Browse files
Merge pull request #75181 from cachemeifyoucan/eng/PR-macro-deps-swift-6
[6.0][Macro] Get accurate dependency information for macro in explicit module build
2 parents 5e8e659 + a845dac commit e6a1db7

File tree

11 files changed

+352
-86
lines changed

11 files changed

+352
-86
lines changed

include/swift-c/DependencyScan/DependencyScan.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ 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+
50+
/// Opaque container to a macro dependency.
51+
typedef struct swiftscan_macro_dependency_s *swiftscan_macro_dependency_t;
52+
4953
/// Opaque container to an overall result of a dependency scan.
5054
typedef struct swiftscan_dependency_graph_s *swiftscan_dependency_graph_t;
5155

@@ -64,6 +68,12 @@ typedef struct {
6468
size_t count;
6569
} swiftscan_dependency_set_t;
6670

71+
/// Set of macro dependency
72+
typedef struct {
73+
swiftscan_macro_dependency_t *macro_dependencies;
74+
size_t count;
75+
} swiftscan_macro_dependency_set_t;
76+
6777
typedef enum {
6878
SWIFTSCAN_DIAGNOSTIC_SEVERITY_ERROR = 0,
6979
SWIFTSCAN_DIAGNOSTIC_SEVERITY_WARNING = 1,

include/swift/AST/ModuleDependencies.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,12 @@ enum class ModuleDependencyKind : int8_t {
8888
LastKind = SwiftPlaceholder + 1
8989
};
9090

91+
/// This is used to idenfity a specific macro plugin dependency.
92+
struct MacroPluginDependency {
93+
std::string LibraryPath;
94+
std::string ExecutablePath;
95+
};
96+
9197
/// This is used to identify a specific module.
9298
struct ModuleDependencyID {
9399
std::string ModuleName;
@@ -240,6 +246,9 @@ struct CommonSwiftTextualModuleDependencyDetails {
240246
/// (Clang) modules on which the bridging header depends.
241247
std::vector<std::string> bridgingModuleDependencies;
242248

249+
/// The macro dependencies.
250+
std::map<std::string, MacroPluginDependency> macroDependencies;
251+
243252
/// The Swift frontend invocation arguments to build the Swift module from the
244253
/// interface.
245254
std::vector<std::string> buildCommandLine;
@@ -302,6 +311,12 @@ class SwiftInterfaceModuleDependenciesStorage :
302311
void updateCommandLine(const std::vector<std::string> &newCommandLine) {
303312
textualModuleDetails.buildCommandLine = newCommandLine;
304313
}
314+
315+
void addMacroDependency(StringRef macroModuleName, StringRef libraryPath,
316+
StringRef executablePath) {
317+
textualModuleDetails.macroDependencies.insert(
318+
{macroModuleName.str(), {libraryPath.str(), executablePath.str()}});
319+
}
305320
};
306321

307322
/// Describes the dependencies of a Swift module
@@ -353,6 +368,12 @@ class SwiftSourceModuleDependenciesStorage :
353368
void addTestableImport(ImportPath::Module module) {
354369
testableImports.insert(module.front().Item.str());
355370
}
371+
372+
void addMacroDependency(StringRef macroModuleName, StringRef libraryPath,
373+
StringRef executablePath) {
374+
textualModuleDetails.macroDependencies.insert(
375+
{macroModuleName.str(), {libraryPath.str(), executablePath.str()}});
376+
}
356377
};
357378

358379
/// Describes the dependencies of a pre-built Swift module (with no
@@ -758,6 +779,10 @@ class ModuleDependencyInfo {
758779
/// For a Source dependency, register a `Testable` import
759780
void addTestableImport(ImportPath::Module module);
760781

782+
/// For a Source/Textual dependency, register a macro dependency.
783+
void addMacroDependency(StringRef macroModuleName, StringRef libraryPath,
784+
StringRef executablePath);
785+
761786
/// Whether or not a queried module name is a `@Testable` import dependency
762787
/// of this module. Can only return `true` for Swift source modules.
763788
bool isTestableImport(StringRef moduleName) const;

include/swift/DependencyScan/DependencyScanImpl.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ struct swiftscan_dependency_info_s {
6464
swiftscan_module_details_t details;
6565
};
6666

67+
struct swiftscan_macro_dependency_s {
68+
swiftscan_string_ref_t moduleName;
69+
swiftscan_string_ref_t libraryPath;
70+
swiftscan_string_ref_t executablePath;
71+
};
72+
6773
/// Swift modules to be built from a module interface, may have a bridging
6874
/// header.
6975
typedef struct {
@@ -111,6 +117,9 @@ typedef struct {
111117

112118
/// ModuleCacheKey
113119
swiftscan_string_ref_t module_cache_key;
120+
121+
/// Macro dependecies.
122+
swiftscan_macro_dependency_set_t *macro_dependencies;
114123
} swiftscan_swift_textual_details_t;
115124

116125
/// Swift modules with only a binary module file.

lib/AST/ModuleDependencies.cpp

Lines changed: 54 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include "swift/AST/Decl.h"
1818
#include "swift/AST/DiagnosticsFrontend.h"
1919
#include "swift/AST/DiagnosticsSema.h"
20+
#include "swift/AST/MacroDefinition.h"
21+
#include "swift/AST/PluginLoader.h"
2022
#include "swift/AST/SourceFile.h"
2123
#include "swift/Frontend/Frontend.h"
2224
#include "llvm/CAS/CASProvidingFileSystem.h"
@@ -103,6 +105,21 @@ void ModuleDependencyInfo::addTestableImport(ImportPath::Module module) {
103105
dyn_cast<SwiftSourceModuleDependenciesStorage>(storage.get())->addTestableImport(module);
104106
}
105107

108+
void ModuleDependencyInfo::addMacroDependency(StringRef macroModuleName,
109+
StringRef libraryPath,
110+
StringRef executablePath) {
111+
if (auto swiftSourceStorage =
112+
dyn_cast<SwiftSourceModuleDependenciesStorage>(storage.get()))
113+
swiftSourceStorage->addMacroDependency(macroModuleName, libraryPath,
114+
executablePath);
115+
else if (auto swiftInterfaceStorage =
116+
dyn_cast<SwiftInterfaceModuleDependenciesStorage>(storage.get()))
117+
swiftInterfaceStorage->addMacroDependency(macroModuleName, libraryPath,
118+
executablePath);
119+
else
120+
llvm_unreachable("Unexpected dependency kind");
121+
}
122+
106123
bool ModuleDependencyInfo::isTestableImport(StringRef moduleName) const {
107124
if (auto swiftSourceDepStorage = getAsSwiftSourceModule())
108125
return swiftSourceDepStorage->testableImports.contains(moduleName);
@@ -183,35 +200,45 @@ void ModuleDependencyInfo::addModuleImports(
183200
SmallVector<Decl *, 32> decls;
184201
sourceFile.getTopLevelDecls(decls);
185202
for (auto decl : decls) {
186-
auto importDecl = dyn_cast<ImportDecl>(decl);
187-
if (!importDecl)
188-
continue;
189-
190-
ImportPath::Builder scratch;
191-
auto realPath = importDecl->getRealModulePath(scratch);
192-
193-
// Explicit 'Builtin' import is not a part of the module's
194-
// dependency set, does not exist on the filesystem,
195-
// and is resolved within the compiler during compilation.
196-
SmallString<64> importedModuleName;
197-
realPath.getString(importedModuleName);
198-
if (importedModuleName == BUILTIN_NAME)
199-
continue;
200-
201-
// Ignore/diagnose tautological imports akin to import resolution
202-
if (!swift::dependencies::checkImportNotTautological(
203-
realPath, importDecl->getLoc(), sourceFile,
204-
importDecl->isExported()))
205-
continue;
203+
if (auto importDecl = dyn_cast<ImportDecl>(decl)) {
204+
ImportPath::Builder scratch;
205+
auto realPath = importDecl->getRealModulePath(scratch);
206+
207+
// Explicit 'Builtin' import is not a part of the module's
208+
// dependency set, does not exist on the filesystem,
209+
// and is resolved within the compiler during compilation.
210+
SmallString<64> importedModuleName;
211+
realPath.getString(importedModuleName);
212+
if (importedModuleName == BUILTIN_NAME)
213+
continue;
206214

207-
addModuleImport(realPath, &alreadyAddedModules,
208-
sourceManager, importDecl->getLoc());
215+
// Ignore/diagnose tautological imports akin to import resolution
216+
if (!swift::dependencies::checkImportNotTautological(
217+
realPath, importDecl->getLoc(), sourceFile,
218+
importDecl->isExported()))
219+
continue;
209220

210-
// Additionally, keep track of which dependencies of a Source
211-
// module are `@Testable`.
212-
if (getKind() == swift::ModuleDependencyKind::SwiftSource &&
213-
importDecl->isTestable())
214-
addTestableImport(realPath);
221+
addModuleImport(realPath, &alreadyAddedModules, sourceManager,
222+
importDecl->getLoc());
223+
224+
// Additionally, keep track of which dependencies of a Source
225+
// module are `@Testable`.
226+
if (getKind() == swift::ModuleDependencyKind::SwiftSource &&
227+
importDecl->isTestable())
228+
addTestableImport(realPath);
229+
} else if (auto macroDecl = dyn_cast<MacroDecl>(decl)) {
230+
auto macroDef = macroDecl->getDefinition();
231+
auto &ctx = macroDecl->getASTContext();
232+
if (macroDef.kind != MacroDefinition::Kind::External)
233+
continue;
234+
auto external = macroDef.getExternalMacro();
235+
PluginLoader &loader = ctx.getPluginLoader();
236+
auto &entry = loader.lookupPluginByModuleName(external.moduleName);
237+
if (entry.libraryPath.empty() && entry.executablePath.empty())
238+
continue;
239+
addMacroDependency(external.moduleName.str(), entry.libraryPath,
240+
entry.executablePath);
241+
}
215242
}
216243

217244
auto fileName = sourceFile.getFilename();
@@ -535,58 +562,6 @@ void SwiftDependencyTracker::addCommonSearchPathDeps(
535562
// Add VFSOverlay file.
536563
for (auto &Overlay: Opts.VFSOverlayFiles)
537564
FS->status(Overlay);
538-
539-
// Add plugin dylibs from the toolchain only by look through the plugin search
540-
// directory.
541-
auto recordFiles = [&](StringRef Path) {
542-
std::error_code EC;
543-
for (auto I = FS->dir_begin(Path, EC);
544-
!EC && I != llvm::vfs::directory_iterator(); I = I.increment(EC)) {
545-
if (I->type() != llvm::sys::fs::file_type::regular_file)
546-
continue;
547-
#if defined(_WIN32)
548-
constexpr StringRef libPrefix{};
549-
constexpr StringRef libSuffix = ".dll";
550-
#else
551-
constexpr StringRef libPrefix = "lib";
552-
constexpr StringRef libSuffix = LTDL_SHLIB_EXT;
553-
#endif
554-
StringRef filename = llvm::sys::path::filename(I->path());
555-
if (filename.starts_with(libPrefix) && filename.ends_with(libSuffix))
556-
FS->status(I->path());
557-
}
558-
};
559-
for (auto &entry : Opts.PluginSearchOpts) {
560-
switch (entry.getKind()) {
561-
562-
// '-load-plugin-library <library path>'.
563-
case PluginSearchOption::Kind::LoadPluginLibrary: {
564-
auto &val = entry.get<PluginSearchOption::LoadPluginLibrary>();
565-
FS->status(val.LibraryPath);
566-
break;
567-
}
568-
569-
// '-load-plugin-executable <executable path>#<module name>, ...'.
570-
case PluginSearchOption::Kind::LoadPluginExecutable: {
571-
// We don't have executable plugin in toolchain.
572-
break;
573-
}
574-
575-
// '-plugin-path <library search path>'.
576-
case PluginSearchOption::Kind::PluginPath: {
577-
auto &val = entry.get<PluginSearchOption::PluginPath>();
578-
recordFiles(val.SearchPath);
579-
break;
580-
}
581-
582-
// '-external-plugin-path <library search path>#<server path>'.
583-
case PluginSearchOption::Kind::ExternalPluginPath: {
584-
auto &val = entry.get<PluginSearchOption::ExternalPluginPath>();
585-
recordFiles(val.SearchPath);
586-
break;
587-
}
588-
}
589-
}
590565
}
591566

592567
void SwiftDependencyTracker::startTracking() {

lib/DependencyScan/DependencyScanJSON.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,49 @@ static void writeDependencies(llvm::raw_ostream &out,
202202
out << "\n";
203203
}
204204

205+
static void
206+
writeMacroDependencies(llvm::raw_ostream &out,
207+
const swiftscan_macro_dependency_set_t *macro_deps,
208+
unsigned indentLevel, bool trailingComma) {
209+
if (!macro_deps)
210+
return;
211+
212+
out.indent(indentLevel * 2);
213+
out << "\"macroDependencies\": ";
214+
out << "[\n";
215+
for (size_t i = 0; i < macro_deps->count; ++i) {
216+
const auto &macroInfo = *macro_deps->macro_dependencies[i];
217+
out.indent((indentLevel + 1) * 2);
218+
out << "{\n";
219+
auto entryIndentLevel = ((indentLevel + 2) * 2);
220+
out.indent(entryIndentLevel);
221+
out << "\"moduleName\": ";
222+
writeJSONValue(out, macroInfo.moduleName, indentLevel);
223+
out << ",\n";
224+
out.indent(entryIndentLevel);
225+
out << "\"libraryPath\": ";
226+
writeJSONValue(out, macroInfo.libraryPath, entryIndentLevel);
227+
out << ",\n";
228+
out.indent(entryIndentLevel);
229+
out << "\"executablePath\": ";
230+
writeJSONValue(out, macroInfo.executablePath, entryIndentLevel);
231+
out << "\n";
232+
out.indent((indentLevel + 1) * 2);
233+
out << "}";
234+
if (i != macro_deps->count - 1) {
235+
out << ",";
236+
}
237+
out << "\n";
238+
}
239+
240+
out.indent(indentLevel * 2);
241+
out << "]";
242+
243+
if (trailingComma)
244+
out << ",";
245+
out << "\n";
246+
}
247+
205248
static const swiftscan_swift_textual_details_t *
206249
getAsTextualDependencyModule(swiftscan_module_details_t details) {
207250
if (details->kind == SWIFTSCAN_DEPENDENCY_INFO_SWIFT_TEXTUAL)
@@ -369,6 +412,8 @@ void writeJSON(llvm::raw_ostream &out,
369412
swiftTextualDeps->module_cache_key, 5,
370413
/*trailingComma=*/true);
371414
}
415+
writeMacroDependencies(out, swiftTextualDeps->macro_dependencies, 5,
416+
/*trailingComma=*/true);
372417
writeJSONSingleField(out, "isFramework", swiftTextualDeps->is_framework,
373418
5, commaAfterFramework);
374419
if (swiftTextualDeps->extra_pcm_args->count != 0) {

lib/DependencyScan/DependencyScanningTool.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,8 @@ static swiftscan_dependency_graph_t generateHollowDiagnosticOutput(
227227
false,
228228
c_string_utils::create_null(),
229229
c_string_utils::create_null(),
230-
c_string_utils::create_null()};
230+
c_string_utils::create_null(),
231+
nullptr};
231232
hollowMainModuleInfo->details = hollowDetails;
232233

233234
// Populate the diagnostic info

0 commit comments

Comments
 (0)