Skip to content

Commit f3045ff

Browse files
committed
DependenciesScanner: teach batch scanning mode to configure scanner using specified additional arguments
To help solving rdar://67079780, this change allows swift-driver to configure scanner using additional arguments passed down via the batch input JSON file for each module under scanning.
1 parent 5a1f38b commit f3045ff

File tree

8 files changed

+91
-10
lines changed

8 files changed

+91
-10
lines changed

include/swift/AST/DiagnosticsCommon.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,5 +185,8 @@ WARNING(cross_imported_by_both_modules, none,
185185
ERROR(scanner_find_cycle, none,
186186
"dependency scanner detected dependency cycle: '%0'", (StringRef))
187187

188+
ERROR(scanner_arguments_invalid, none,
189+
"dependencies scanner cannot be configured with arguments: '%0'", (StringRef))
190+
188191
#define UNDEFINE_DIAGNOSTIC_MACROS
189192
#include "DefineDiagnosticMacros.h"

lib/FrontendTool/FrontendTool.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1751,7 +1751,8 @@ static void performEndOfPipelineActions(CompilerInstance &Instance) {
17511751
/// \param Instance Will be reset after performIRGeneration when the verifier
17521752
/// mode is NoVerify and there were no errors.
17531753
/// \returns true on error
1754-
static bool performCompile(CompilerInstance &Instance,
1754+
static bool performCompile(CompilerInvocation &Invok,
1755+
CompilerInstance &Instance,
17551756
ArrayRef<const char *> Args,
17561757
int &ReturnValue,
17571758
FrontendObserver *observer) {
@@ -1839,7 +1840,8 @@ static bool performCompile(CompilerInstance &Instance,
18391840
if (batchScanInput.empty())
18401841
return finishPipeline(scanDependencies(Instance));
18411842
else
1842-
return finishPipeline(batchScanModuleDependencies(Instance,
1843+
return finishPipeline(batchScanModuleDependencies(Invok,
1844+
Instance,
18431845
batchScanInput));
18441846
}
18451847

@@ -2652,7 +2654,7 @@ int swift::performFrontend(ArrayRef<const char *> Args,
26522654
}
26532655

26542656
int ReturnValue = 0;
2655-
bool HadError = performCompile(*Instance, Args, ReturnValue, observer);
2657+
bool HadError = performCompile(Invocation, *Instance, Args, ReturnValue, observer);
26562658

26572659
if (verifierEnabled) {
26582660
DiagnosticEngine &diags = Instance->getDiags();

lib/FrontendTool/ScanDependencies.cpp

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "llvm/ADT/StringMap.h"
3232
#include "llvm/ADT/StringRef.h"
3333
#include "llvm/ADT/StringSet.h"
34+
#include "llvm/Support/CommandLine.h"
3435
#include "llvm/Support/FileSystem.h"
3536
#include "llvm/Support/StringSaver.h"
3637
#include "llvm/Support/YAMLTraits.h"
@@ -626,7 +627,6 @@ static bool diagnoseCycle(CompilerInstance &instance,
626627

627628
static bool scanModuleDependencies(CompilerInstance &instance,
628629
StringRef moduleName,
629-
StringRef arguments,
630630
bool isClang,
631631
StringRef outputPath) {
632632
ASTContext &ctx = instance.getASTContext();
@@ -685,25 +685,58 @@ static bool scanModuleDependencies(CompilerInstance &instance,
685685
bool swift::scanClangDependencies(CompilerInstance &instance) {
686686
return scanModuleDependencies(instance,
687687
instance.getMainModule()->getNameStr(),
688-
StringRef(),
689688
/*isClang*/true,
690689
instance.getInvocation().getFrontendOptions()
691690
.InputsAndOutputs.getSingleOutputFilename());
692691
}
693692

694-
bool swift::batchScanModuleDependencies(CompilerInstance &instance,
695-
llvm::StringRef batchInputFile) {
693+
bool swift::batchScanModuleDependencies(CompilerInvocation &invok,
694+
CompilerInstance &instance,
695+
llvm::StringRef batchInputFile) {
696696
(void)instance.getMainModule();
697697
llvm::BumpPtrAllocator alloc;
698698
llvm::StringSaver saver(alloc);
699699
auto results = parseBatchScanInputFile(instance.getASTContext(),
700700
batchInputFile, saver);
701701
if (!results.hasValue())
702702
return true;
703+
auto &diags = instance.getDiags();
704+
ForwardingDiagnosticConsumer FDC(diags);
705+
// Keep track of all compiler instances we have created.
706+
llvm::StringMap<std::unique_ptr<CompilerInstance>> subInstanceMap;
703707
for (auto &entry: *results) {
704-
if (scanModuleDependencies(instance, entry.moduleName, entry.arguments,
705-
!entry.isSwift, entry.outputPath))
708+
CompilerInstance *pInstance = nullptr;
709+
if (entry.arguments.empty()) {
710+
// Use the compiler's instance if no arguments are specified.
711+
pInstance = &instance;
712+
} else if (subInstanceMap.count(entry.arguments)) {
713+
// Use the previously created instance if we've seen the arguments before.
714+
pInstance = subInstanceMap[entry.arguments].get();
715+
} else {
716+
// Create a new instance by the arguments and save it in the map.
717+
pInstance = subInstanceMap.insert({entry.arguments,
718+
std::make_unique<CompilerInstance>()}).first->getValue().get();
719+
SmallVector<const char*, 4> args;
720+
llvm::cl::TokenizeGNUCommandLine(entry.arguments, saver, args);
721+
CompilerInvocation subInvok = invok;
722+
pInstance->addDiagnosticConsumer(&FDC);
723+
if (subInvok.parseArgs(args, diags)) {
724+
instance.getDiags().diagnose(SourceLoc(), diag::scanner_arguments_invalid,
725+
entry.arguments);
726+
return true;
727+
}
728+
if (pInstance->setup(subInvok)) {
729+
instance.getDiags().diagnose(SourceLoc(), diag::scanner_arguments_invalid,
730+
entry.arguments);
731+
return true;
732+
}
733+
}
734+
assert(pInstance);
735+
// Scan using the chosen compiler instance.
736+
if (scanModuleDependencies(*pInstance, entry.moduleName, !entry.isSwift,
737+
entry.outputPath)) {
706738
return true;
739+
}
707740
}
708741
return false;
709742
}

lib/FrontendTool/ScanDependencies.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@
1717

1818
namespace swift {
1919

20+
class CompilerInvocation;
2021
class CompilerInstance;
2122

2223
/// Batch scan the dependencies for modules specified in \c batchInputFile.
23-
bool batchScanModuleDependencies(CompilerInstance &instance, llvm::StringRef batchInputFile);
24+
bool batchScanModuleDependencies(CompilerInvocation &invok,
25+
CompilerInstance &instance,
26+
llvm::StringRef batchInputFile);
2427

2528
/// Scans the dependencies of the main module of \c instance.
2629
bool scanDependencies(CompilerInstance &instance);
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 110000
2+
#include "I.h"
3+
#endif
4+
5+
void funcH(void);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
void funcI(void);

test/ScanDependencies/Inputs/CHeaders/module.modulemap

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,13 @@ module G {
2727
header "G.h"
2828
export *
2929
}
30+
31+
module H {
32+
header "H.h"
33+
export *
34+
}
35+
36+
module I {
37+
header "I.h"
38+
export *
39+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %empty-directory(%t/inputs)
3+
// RUN: %empty-directory(%t/outputs)
4+
// RUN: mkdir -p %t/clang-module-cache
5+
6+
// RUN: echo "[{" > %/t/inputs/input.json
7+
// RUN: echo "\"clangModuleName\": \"H\"," >> %/t/inputs/input.json
8+
// RUN: echo "\"arguments\": \"-target x86_64-apple-macosx10.9\"," >> %/t/inputs/input.json
9+
// RUN: echo "\"output\": \"%/t/outputs/H.10.9.pcm.json\"" >> %/t/inputs/input.json
10+
// RUN: echo "}," >> %/t/inputs/input.json
11+
// RUN: echo "{" >> %/t/inputs/input.json
12+
// RUN: echo "\"clangModuleName\": \"H\"," >> %/t/inputs/input.json
13+
// RUN: echo "\"arguments\": \"-target x86_64-apple-macosx11.0\"," >> %/t/inputs/input.json
14+
// RUN: echo "\"output\": \"%/t/outputs/H.11.0.pcm.json\"" >> %/t/inputs/input.json
15+
// RUN: echo "}]" >> %/t/inputs/input.json
16+
17+
// RUN: %target-swift-frontend -scan-dependencies -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 -batch-scan-input-file %/t/inputs/input.json
18+
19+
// Check the contents of the JSON output
20+
// RUN: %FileCheck %s -check-prefix=CHECK-TEN < %t/outputs/H.10.9.pcm.json
21+
// RUN: %FileCheck %s -check-prefix=CHECK-ELEVEN < %t/outputs/H.11.0.pcm.json
22+
23+
// CHECK-TEN: "clang": "I"
24+
// CHECK-ELEVEN-NOT: "clang": "I"

0 commit comments

Comments
 (0)