Skip to content

Commit 0a18baa

Browse files
Merge pull request #76732 from cachemeifyoucan/eng/PR-136682810
[Macro] Precise macro plugin dependency during scanning
2 parents c0a55e1 + 2d204f8 commit 0a18baa

File tree

13 files changed

+117
-64
lines changed

13 files changed

+117
-64
lines changed

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ ERROR(error_no_source_location_scope_map,none,
127127
ERROR(error_load_plugin_executable,none,
128128
"invalid value '%0' in '-load-plugin-executable'; "
129129
"make sure to use format '<plugin path>#<module names>'", (StringRef))
130+
ERROR(error_load_resolved_plugin,none,
131+
"invalid value '%0' in '-load-resolved-plugin'; "
132+
"make sure to use format '<library path>#<plugin path>#<module names>' where library and plugin path can't both be empty", (StringRef))
130133

131134
NOTE(note_valid_swift_versions, none,
132135
"valid arguments to '-swift-version' are %0", (StringRef))

include/swift/AST/SearchPathOptions.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,17 +214,24 @@ class PluginSearchOption {
214214
std::string SearchPath;
215215
std::string ServerPath;
216216
};
217+
struct ResolvedPluginConfig {
218+
std::string LibraryPath;
219+
std::string ExecutablePath;
220+
std::vector<std::string> ModuleNames;
221+
};
217222

218223
enum class Kind : uint8_t {
219224
LoadPluginLibrary,
220225
LoadPluginExecutable,
221226
PluginPath,
222227
ExternalPluginPath,
228+
ResolvedPluginConfig,
223229
};
224230

225231
private:
226-
using Members = ExternalUnionMembers<LoadPluginLibrary, LoadPluginExecutable,
227-
PluginPath, ExternalPluginPath>;
232+
using Members =
233+
ExternalUnionMembers<LoadPluginLibrary, LoadPluginExecutable, PluginPath,
234+
ExternalPluginPath, ResolvedPluginConfig>;
228235
static Members::Index getIndexForKind(Kind kind) {
229236
switch (kind) {
230237
case Kind::LoadPluginLibrary:
@@ -235,6 +242,8 @@ class PluginSearchOption {
235242
return Members::indexOf<PluginPath>();
236243
case Kind::ExternalPluginPath:
237244
return Members::indexOf<ExternalPluginPath>();
245+
case Kind::ResolvedPluginConfig:
246+
return Members::indexOf<ResolvedPluginConfig>();
238247
}
239248
};
240249
using Storage = ExternalUnion<Kind, Members, getIndexForKind>;
@@ -258,6 +267,10 @@ class PluginSearchOption {
258267
: kind(Kind::ExternalPluginPath) {
259268
storage.emplace<ExternalPluginPath>(kind, v);
260269
}
270+
PluginSearchOption(const ResolvedPluginConfig &v)
271+
: kind(Kind::ResolvedPluginConfig) {
272+
storage.emplace<ResolvedPluginConfig>(kind, v);
273+
}
261274
PluginSearchOption(const PluginSearchOption &o) : kind(o.kind) {
262275
storage.copyConstruct(o.kind, o.storage);
263276
}

include/swift/Option/Options.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2106,6 +2106,14 @@ def load_plugin_executable:
21062106
"of module names where the macro types are declared">,
21072107
MetaVarName<"<path>#<module-names>">;
21082108

2109+
def load_resolved_plugin:
2110+
Separate<["-"], "load-resolved-plugin">, Group<plugin_search_Group>,
2111+
Flags<[FrontendOption, DoesNotAffectIncrementalBuild, ArgumentIsPath]>,
2112+
HelpText<"Path to resolved plugin configuration and a comma-separated list "
2113+
"of module names where the macro types are declared. Library path "
2114+
"and exectuable path can be empty if not used">,
2115+
MetaVarName<"<library-path>#<executable-path>#<module-names>">;
2116+
21092117
def in_process_plugin_server_path : Separate<["-"], "in-process-plugin-server-path">,
21102118
Flags<[FrontendOption, ArgumentIsPath]>,
21112119
HelpText<"Path to dynamic library plugin server">;

lib/AST/PluginLoader.cpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,18 +83,17 @@ PluginLoader::getPluginMap() {
8383
// Helper function to try inserting an entry if there's no existing entry
8484
// associated with the module name.
8585
auto try_emplace = [&](StringRef moduleName, StringRef libPath,
86-
StringRef execPath) {
86+
StringRef execPath, bool overwrite = false) {
8787
auto moduleNameIdentifier = Ctx.getIdentifier(moduleName);
88-
if (map.find(moduleNameIdentifier) != map.end()) {
89-
// Specified module name is already in the map.
88+
if (map.find(moduleNameIdentifier) != map.end() && !overwrite) {
89+
// Specified module name is already in the map and no need to overwrite
90+
// the current value.
9091
return;
9192
}
9293

9394
libPath = libPath.empty() ? "" : Ctx.AllocateCopy(libPath);
9495
execPath = execPath.empty() ? "" : Ctx.AllocateCopy(execPath);
95-
auto result = map.insert({moduleNameIdentifier, {libPath, execPath}});
96-
assert(result.second);
97-
(void)result;
96+
map[moduleNameIdentifier] = {libPath, execPath};
9897
};
9998

10099
auto fs = getPluginLoadingFS(Ctx);
@@ -150,6 +149,18 @@ PluginLoader::getPluginMap() {
150149
}
151150
continue;
152151
}
152+
153+
// '-load-resolved-plugin <library path>#<server path>#<module name>,...'.
154+
case PluginSearchOption::Kind::ResolvedPluginConfig: {
155+
auto &val = entry.get<PluginSearchOption::ResolvedPluginConfig>();
156+
// Respect resolved plugin config above other search path, and it can
157+
// overwrite plugins found by other options or previous resolved
158+
// configuration.
159+
for (auto &moduleName : val.ModuleNames)
160+
try_emplace(moduleName, val.LibraryPath, val.ExecutablePath,
161+
/*overwrite*/ true);
162+
continue;
163+
}
153164
}
154165
llvm_unreachable("unhandled PluginSearchOption::Kind");
155166
}

lib/DependencyScan/ScanDependencies.cpp

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -160,25 +160,6 @@ parseBatchScanInputFile(ASTContext &ctx, StringRef batchInputPath,
160160
return result;
161161
}
162162

163-
static void removeMacroSearchPaths(std::vector<std::string> &cmd) {
164-
// Macro search path options.
165-
static const llvm::StringSet<> macroSearchOptions = {
166-
"-plugin-path",
167-
"-external-plugin-path",
168-
"-load-plugin-library",
169-
"-load-plugin-executable",
170-
"-in-process-plugin-server-path",
171-
};
172-
173-
// Remove macro search path option and its argument.
174-
for (auto it = cmd.begin(); it != cmd.end();) {
175-
if (macroSearchOptions.contains(*it) && it + 1 != cmd.end())
176-
it = cmd.erase(it, it + 2);
177-
else
178-
++it;
179-
}
180-
}
181-
182163
class ExplicitModuleDependencyResolver {
183164
public:
184165
ExplicitModuleDependencyResolver(
@@ -302,6 +283,13 @@ class ExplicitModuleDependencyResolver {
302283
depInfo.addMacroDependency(
303284
macro.first(), macro.second.LibraryPath, macro.second.ExecutablePath);
304285

286+
for (auto &macro : depInfo.getMacroDependencies()) {
287+
std::string arg = macro.second.LibraryPath + "#" +
288+
macro.second.ExecutablePath + "#" + macro.first;
289+
commandline.push_back("-load-resolved-plugin");
290+
commandline.push_back(arg);
291+
}
292+
305293
// Update CAS dependencies.
306294
if (auto err = collectCASDependencies(depInfo))
307295
return err;
@@ -529,11 +517,6 @@ class ExplicitModuleDependencyResolver {
529517
// Update build command line.
530518
if (resolvingDepInfo.isSwiftInterfaceModule() ||
531519
resolvingDepInfo.isSwiftSourceModule()) {
532-
// If there are no external macro dependencies, drop all plugin search
533-
// paths.
534-
if (resolvingDepInfo.getMacroDependencies().empty() && macros.empty())
535-
removeMacroSearchPaths(commandline);
536-
537520
// Update with casfs option.
538521
for (auto rootID : rootIDs) {
539522
commandline.push_back("-cas-fs");

lib/Frontend/CompilerInvocation.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2172,6 +2172,27 @@ static bool ParseSearchPathArgs(SearchPathOptions &Opts, ArgList &Args,
21722172
resolveSearchPath(dylibPath), resolveSearchPath(serverPath)});
21732173
break;
21742174
}
2175+
case OPT_load_resolved_plugin: {
2176+
StringRef libraryPath;
2177+
StringRef executablePath;
2178+
StringRef modulesStr;
2179+
std::tie(libraryPath, executablePath) =
2180+
StringRef(A->getValue()).split('#');
2181+
std::tie(executablePath, modulesStr) = executablePath.split('#');
2182+
if (modulesStr.empty() ||
2183+
(libraryPath.empty() && executablePath.empty())) {
2184+
Diags.diagnose(SourceLoc(), diag::error_load_resolved_plugin,
2185+
A->getValue());
2186+
}
2187+
std::vector<std::string> moduleNames;
2188+
for (auto name : llvm::split(modulesStr, ',')) {
2189+
moduleNames.emplace_back(name);
2190+
}
2191+
Opts.PluginSearchOpts.emplace_back(
2192+
PluginSearchOption::ResolvedPluginConfig{
2193+
libraryPath.str(), executablePath.str(), std::move(moduleNames)});
2194+
break;
2195+
}
21752196
default:
21762197
llvm_unreachable("unhandled plugin search option");
21772198
}

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1723,38 +1723,9 @@ void InterfaceSubContextDelegateImpl::inheritOptionsForBuildingInterface(
17231723
genericSubInvocation.setPlatformAvailabilityInheritanceMapPath(*SearchPathOpts.PlatformAvailabilityInheritanceMapPath);
17241724
}
17251725

1726-
for (auto &entry : SearchPathOpts.PluginSearchOpts) {
1727-
switch (entry.getKind()) {
1728-
case PluginSearchOption::Kind::LoadPluginLibrary: {
1729-
auto &val = entry.get<PluginSearchOption::LoadPluginLibrary>();
1730-
GenericArgs.push_back("-load-plugin-library");
1731-
GenericArgs.push_back(ArgSaver.save(val.LibraryPath));
1732-
break;
1733-
}
1734-
case PluginSearchOption::Kind::LoadPluginExecutable: {
1735-
auto &val = entry.get<PluginSearchOption::LoadPluginExecutable>();
1736-
for (auto &moduleName : val.ModuleNames) {
1737-
GenericArgs.push_back("-load-plugin-executable");
1738-
GenericArgs.push_back(
1739-
ArgSaver.save(val.ExecutablePath + "#" + moduleName));
1740-
}
1741-
break;
1742-
}
1743-
case PluginSearchOption::Kind::PluginPath: {
1744-
auto &val = entry.get<PluginSearchOption::PluginPath>();
1745-
GenericArgs.push_back("-plugin-path");
1746-
GenericArgs.push_back(ArgSaver.save(val.SearchPath));
1747-
break;
1748-
}
1749-
case PluginSearchOption::Kind::ExternalPluginPath: {
1750-
auto &val = entry.get<PluginSearchOption::ExternalPluginPath>();
1751-
GenericArgs.push_back("-external-plugin-path");
1752-
GenericArgs.push_back(
1753-
ArgSaver.save(val.SearchPath + "#" + val.ServerPath));
1754-
break;
1755-
}
1756-
}
1757-
}
1726+
// Inherit the plugin search opts but do not inherit the arguments.
1727+
genericSubInvocation.getSearchPathOptions().PluginSearchOpts =
1728+
SearchPathOpts.PluginSearchOpts;
17581729

17591730
genericSubInvocation.getFrontendOptions().InputMode
17601731
= FrontendOptions::ParseInputMode::SwiftModuleInterface;

lib/Serialization/ModuleFileSharedCore.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ static bool readOptionsBlock(llvm::BitstreamCursor &cursor,
148148
case PluginSearchOptionKind::LoadPluginExecutable:
149149
optKind = PluginSearchOption::Kind::LoadPluginExecutable;
150150
break;
151+
case PluginSearchOptionKind::ResolvedPluginConfig:
152+
optKind = PluginSearchOption::Kind::ResolvedPluginConfig;
153+
break;
151154
}
152155
extendedInfo.addPluginSearchOption({optKind, blobData});
153156
break;

lib/Serialization/ModuleFormat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,7 @@ enum class PluginSearchOptionKind : uint8_t {
694694
ExternalPluginPath,
695695
LoadPluginLibrary,
696696
LoadPluginExecutable,
697+
ResolvedPluginConfig,
697698
};
698699
using PluginSearchOptionKindField = BCFixed<3>;
699700

lib/Serialization/Serialization.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,6 +1245,18 @@ void Serializer::writeHeader() {
12451245
uint8_t(PluginSearchOptionKind::LoadPluginExecutable), optStr);
12461246
continue;
12471247
}
1248+
case PluginSearchOption::Kind::ResolvedPluginConfig: {
1249+
auto &opt = elem.get<PluginSearchOption::ResolvedPluginConfig>();
1250+
std::string optStr =
1251+
opt.LibraryPath + "#" + opt.ExecutablePath + "#";
1252+
llvm::interleave(
1253+
opt.ModuleNames, [&](auto &name) { optStr += name; },
1254+
[&]() { optStr += ","; });
1255+
PluginSearchOpt.emit(
1256+
ScratchRecord,
1257+
uint8_t(PluginSearchOptionKind::ResolvedPluginConfig), optStr);
1258+
continue;
1259+
}
12481260
}
12491261
}
12501262
}

test/CAS/macro_deps.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@
4444
// RUN: %{python} %S/Inputs/GenerateExplicitModuleMap.py %t/deps.json > %t/map.json
4545
// RUN: llvm-cas --cas %t/cas --make-blob --data %t/map.json > %t/map.casid
4646

47+
// RUN: %FileCheck %s --check-prefix=PLUGIN_SEARCH --check-prefix=RESOLVED --input-file=%t/MyApp.cmd
48+
// PLUGIN_SEARCH-NOT: -external-plugin-path
49+
// RESOLVED-COUNT-2: -load-resolved-plugin
50+
4751
// RUN: %target-swift-frontend -diagnostic-style=swift \
4852
// RUN: -emit-module -o %t/Test.swiftmodule -cache-compile-job -cas-path %t/cas \
4953
// RUN: -swift-version 5 -disable-implicit-swift-modules \

test/Macros/macro_plugin_server.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,26 @@
3232

3333
// RUN: %FileCheck -strict-whitespace %s < %t/macro-expansions.txt
3434

35+
/// Create file with matching name in alt directories and test
36+
/// `-load-resolved-plugin` takes the priority over other options.
37+
// RUN: %empty-directory(%t/alt)
38+
// RUN: touch %t/alt/%target-library-name(MacroDefinition)
39+
40+
// RUN: env SWIFT_DUMP_PLUGIN_MESSAGING=1 %target-swift-frontend \
41+
// RUN: -typecheck -verify \
42+
// RUN: -swift-version 5 -enable-experimental-feature Macros \
43+
// RUN: -external-plugin-path %t/alt#%swift-plugin-server \
44+
// RUN: -load-resolved-plugin lib-do-not-exist.dylib##MacroDefinition \
45+
// RUN: -load-resolved-plugin %t/plugins/%target-library-name(MacroDefinition)#%swift-plugin-server#MacroDefinition \
46+
// RUN: -load-resolved-plugin %t/plugins/%target-library-name(EvilMacros)#%swift-plugin-server#EvilMacros \
47+
// RUN: -external-plugin-path %t/alt#%swift-plugin-server \
48+
// RUN: -Rmacro-loading -verify-ignore-unknown \
49+
// RUN: -module-name MyApp \
50+
// RUN: %s \
51+
// RUN: 2>&1 | tee %t/macro-expansions-2.txt
52+
53+
// RUN: %FileCheck -strict-whitespace %s < %t/macro-expansions-2.txt
54+
3555
// RUN: not %target-swift-frontend \
3656
// RUN: -typecheck \
3757
// RUN: -swift-version 5 \

tools/lldb-moduleimport-test/lldb-moduleimport-test.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ static bool validateModule(
105105
case swift::PluginSearchOption::Kind::LoadPluginExecutable:
106106
optStr = "-load-plugin-executable";
107107
break;
108+
case swift::PluginSearchOption::Kind::ResolvedPluginConfig:
109+
optStr = "-load-resolved-plugin";
110+
break;
108111
}
109112
llvm::outs() << " " << optStr << " " << opt.second << "\n";
110113
}

0 commit comments

Comments
 (0)