Skip to content

Commit e0dbba5

Browse files
committed
[Dependency Scanner] Add option to execute an import prescan
With this option enabled, the dependency scanner gathers all import statements in source files of the main module (non-transitive) and outputs a list of imported modules. This will be used by build systems and the swift-driver as a way to avoid redundant re-scanning in incremental contexts.
1 parent 8e6346e commit e0dbba5

File tree

6 files changed

+62
-1
lines changed

6 files changed

+62
-1
lines changed

include/swift/Frontend/FrontendOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,10 @@ class FrontendOptions {
269269
/// built and given to the compiler invocation.
270270
bool DisableImplicitModules = false;
271271

272+
/// When performing a dependency scanning action, only identify and output all imports
273+
/// of the main Swift module's source files.
274+
bool ImportPrescan = false;
275+
272276
/// The different modes for validating TBD against the LLVM IR.
273277
enum class TBDValidationMode {
274278
Default, ///< Do the default validation for the current platform.

include/swift/Option/FrontendOptions.td

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,11 @@ def placeholder_dependency_module_map
226226
def batch_scan_input_file
227227
: Separate<["-"], "batch-scan-input-file">, MetaVarName<"<path>">,
228228
HelpText<"Specify a JSON file containing modules to perform batch dependencies scanning">;
229-
}
230229

230+
def import_prescan : Flag<["-"], "import-prescan">,
231+
HelpText<"When performing a dependency scan, only dentify all imports of the main Swift module sources">;
232+
233+
}
231234

232235
// HIDDEN FLAGS
233236
let Flags = [FrontendOption, NoDriverOption, HelpHidden] in {

lib/Driver/Driver.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,10 +167,15 @@ static void validateDependencyScanningArgs(DiagnosticEngine &diags,
167167
const ArgList &args) {
168168
const Arg *ExternalDependencyMap = args.getLastArg(options::OPT_placeholder_dependency_module_map);
169169
const Arg *ScanDependencies = args.getLastArg(options::OPT_scan_dependencies);
170+
const Arg *Prescan = args.getLastArg(options::OPT_import_prescan);
170171
if (ExternalDependencyMap && !ScanDependencies) {
171172
diags.diagnose(SourceLoc(), diag::error_requirement_not_met,
172173
"-placeholder-dependency-module-map-file", "-scan-dependencies");
173174
}
175+
if (Prescan && !ScanDependencies) {
176+
diags.diagnose(SourceLoc(), diag::error_requirement_not_met,
177+
"-import-prescan", "-scan-dependencies");
178+
}
174179
}
175180

176181
static void validateDebugInfoArgs(DiagnosticEngine &diags,

lib/Frontend/ArgsToFrontendOptionsConverter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ bool ArgsToFrontendOptionsConverter::convert(
8888

8989
Opts.DisableImplicitModules |= Args.hasArg(OPT_disable_implicit_swift_modules);
9090

91+
Opts.ImportPrescan |= Args.hasArg(OPT_import_prescan);
92+
9193
// Always track system dependencies when scanning dependencies.
9294
if (const Arg *ModeArg = Args.getLastArg(OPT_modes_Group)) {
9395
if (ModeArg->getOption().matches(OPT_scan_dependencies)) {

lib/FrontendTool/ScanDependencies.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,17 @@ namespace {
387387
}
388388
}
389389

390+
static void writePrescanJSON(llvm::raw_ostream &out,
391+
const ModuleDependencies &mainModuleDependencies) {
392+
// Write out a JSON containing all main module imports.
393+
out << "{\n";
394+
SWIFT_DEFER {
395+
out << "}\n";
396+
};
397+
398+
writeJSONSingleField(out, "imports", mainModuleDependencies.getModuleDependencies(), 0, false);
399+
}
400+
390401
static void writeJSON(llvm::raw_ostream &out,
391402
CompilerInstance &instance,
392403
ModuleDependenciesCache &cache,
@@ -774,6 +785,8 @@ bool swift::scanDependencies(CompilerInstance &instance) {
774785
"-Xcc", "-target", "-Xcc", instance.getASTContext().LangOpts.Target.str(),
775786
"-Xcc", apinotesVer
776787
});
788+
789+
// Compute Implicit dependencies of the main module
777790
{
778791
llvm::StringSet<> alreadyAddedModules;
779792
for (auto fileUnit : mainModule->getFiles()) {
@@ -820,6 +833,17 @@ bool swift::scanDependencies(CompilerInstance &instance) {
820833
}
821834
}
822835

836+
// If import-prescan is specified, discover and serialize main module dependencies only and exit.
837+
if (opts.ImportPrescan) {
838+
writePrescanJSON(out, mainDependencies);
839+
// This process succeeds regardless of whether any errors occurred.
840+
// FIXME: We shouldn't need this, but it's masking bugs in our scanning
841+
// logic where we don't create a fresh context when scanning Swift interfaces
842+
// that includes their own command-line flags.
843+
Context.Diags.resetHadAnyError();
844+
return false;
845+
}
846+
823847
// Add the main module.
824848
StringRef mainModuleName = mainModule->getNameStr();
825849
llvm::SetVector<ModuleDependencyID, std::vector<ModuleDependencyID>,
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: mkdir -p %t/clang-module-cache
3+
// RUN: %target-swift-frontend -scan-dependencies -import-prescan -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4
4+
5+
// Check the contents of the JSON output
6+
// RUN: %FileCheck %s < %t/deps.json
7+
8+
// REQUIRES: executable_test
9+
// REQUIRES: objc_interop
10+
11+
import C
12+
import E
13+
import G
14+
import SubE
15+
16+
// CHECK: "imports": [
17+
// CHECK-NEXT: "C",
18+
// CHECK-NEXT: "E",
19+
// CHECK-NEXT: "G",
20+
// CHECK-NEXT: "SubE",
21+
// CHECK-NEXT: "Swift",
22+
// CHECK-NEXT: "SwiftOnoneSupport"
23+
// CHECK-NEXT: ]

0 commit comments

Comments
 (0)