Skip to content

Commit 7135e91

Browse files
committed
[clang dependency scanning] C APIs for Current Working Directory Optimization (llvm#10146)
This PR implements two new C APIs so the build system can communicate with the dependency scanner about current working directory optimization. Two new functions are added: 1. `void clang_experimental_DependencyScannerServiceOptions_setCWDOptimization(CXDependencyScannerServiceOptions Opts, int)`: the caller can use this function to set `Opts` to indicate that it can support current working directory optimization. 2. `int clang_experimental_DepGraphModule_isCWDIgnored(CXDepGraphModule)`: this function can retrieve the module info from the scanner, indicating if the current working directory is ignored for this module's context hash. As an example usage, the user of the APIs (e.g. a build system) can use them to set reasonable debug working directories for each `pcm`s. rdar://145860213 (cherry picked from commit b9c8668) Conflicts: clang/test/ClangScanDeps/cas-fs-multiple-commands.c clang/test/ClangScanDeps/include-tree-multiple-commands.c clang/tools/libclang/libclang.map
1 parent 4cc6756 commit 7135e91

File tree

10 files changed

+104
-2
lines changed

10 files changed

+104
-2
lines changed

clang/include/clang-c/Dependencies.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,20 @@ CINDEX_LINKAGE void
218218
clang_experimental_DependencyScannerServiceOptions_setCASOptions(
219219
CXDependencyScannerServiceOptions Opts, CXCASOptions);
220220

221+
/**
222+
* Set the working directory optimization option.
223+
* The dependency scanner service option Opts will indicate to the scanner that
224+
* the current working directory can or cannot be ignored when computing the
225+
* pcms' context hashes. The scanner will then determine if it is safe to
226+
* optimize each module and act accordingly.
227+
*
228+
* \param Value If it is non zero, the option is on. Otherwise the
229+
* option is off.
230+
*/
231+
CINDEX_LINKAGE void
232+
clang_experimental_DependencyScannerServiceOptions_setCWDOptimization(
233+
CXDependencyScannerServiceOptions Opts, int Value);
234+
221235
/**
222236
* Specify a \c CXCASObjectStore in the given options. If an object store and
223237
* action cache are available, the scanner will produce cached commands.
@@ -578,6 +592,13 @@ CINDEX_LINKAGE const char *
578592
CINDEX_LINKAGE
579593
const char *clang_experimental_DepGraphModule_getCacheKey(CXDepGraphModule);
580594

595+
/**
596+
* \returns 1 if the scanner ignores the current working directory when
597+
* computing the module's context hash. Otherwise returns 0.
598+
*/
599+
CINDEX_LINKAGE
600+
int clang_experimental_DepGraphModule_isCWDIgnored(CXDepGraphModule);
601+
581602
/**
582603
* \returns the number \c CXDepGraphTUCommand objects in the graph.
583604
*/

clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ struct ModuleDeps {
117117
/// Whether this is a "system" module.
118118
bool IsSystem;
119119

120+
/// Whether current working directory is ignored.
121+
bool IgnoreCWD;
122+
120123
/// The path to the modulemap file which defines this module.
121124
///
122125
/// This can be used to explicitly build this module. This file will

clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,6 +877,7 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
877877
MD.ModuleCacheKey = Key->toString();
878878
}
879879

880+
MD.IgnoreCWD = IgnoreCWD;
880881
MDC.associateWithContextHash(CI, IgnoreCWD, MD);
881882

882883
// Finish the compiler invocation. Requires dependencies and the context hash.

clang/test/ClangScanDeps/cwd-c-api.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Test the current working directory C APIs.
2+
3+
// RUN: rm -rf %t
4+
// RUN: split-file %s %t
5+
6+
// RUN: c-index-test core -scan-deps -working-dir %S -- %clang \
7+
// RUN: -c %t/main.c -fmodules -fmodules-cache-path=%t/module-cache \
8+
// RUN: 2>&1 > %t/no_cwd_opt.txt
9+
// RUN: cat %t/no_cwd_opt.txt | FileCheck %s --check-prefix=NO-CWD-OPT
10+
11+
12+
// RUN: c-index-test core -scan-deps -working-dir %S -optimize-cwd -- \
13+
// RUN: %clang \
14+
// RUN: -c %t/main.c -fmodules -fmodules-cache-path=%t/module-cache \
15+
// RUN: 2>&1 > %t/cwd_opt.txt
16+
// RUN: cat %t/cwd_opt.txt | FileCheck %s --check-prefix=CWD-OPT
17+
18+
//--- module.modulemap
19+
module Mod { header "Mod.h" }
20+
21+
//--- Mod.h
22+
int foo();
23+
24+
//--- main.c
25+
#include "Mod.h"
26+
27+
int main() {
28+
return foo();
29+
}
30+
31+
// NO-CWD-OPT: modules:
32+
// NO-CWD-OPT-NEXT: module:
33+
// NO-CWD-OPT-NEXT: name: Mod
34+
// NO-CWD-OPT-NEXT: context-hash:{{.*}}
35+
// NO-CWD-OPT-NEXT: cwd-ignored: 0
36+
37+
38+
// CWD-OPT: modules:
39+
// CWD-OPT-NEXT: module:
40+
// CWD-OPT-NEXT: name: Mod
41+
// CWD-OPT-NEXT: context-hash:{{.*}}
42+
// CWD-OPT-NEXT: cwd-ignored: 1

clang/test/Index/Core/scan-deps-by-mod-name.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// CHECK-NEXT: module:
1414
// CHECK-NEXT: name: ModA
1515
// CHECK-NEXT: context-hash: [[HASH_MOD_A:[A-Z0-9]+]]
16+
// CHECK-NEXT: cwd-ignored: 0
1617
// CHECK-NEXT: module-map-path: [[PREFIX]]/Inputs/module/module.modulemap
1718
// CHECK-NEXT: module-deps:
1819
// CHECK-NEXT: file-deps:

clang/test/Index/Core/scan-deps-cas.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
// CHECK-NEXT: module:
3333
// CHECK-NEXT: name: ModA
3434
// CHECK-NEXT: context-hash: [[HASH_MOD_A:[A-Z0-9]+]]
35+
// CHECK-NEXT: cwd-ignored: 0
3536
// CHECK-NEXT: module-map-path: [[PREFIX]]/Inputs/module/module.modulemap
3637
// CHECK-NEXT: cache-key: [[CASFS_MODA_CACHE_KEY:llvmcas://[[:xdigit:]]+]]
3738
// CHECK-NEXT: module-deps:
@@ -70,6 +71,7 @@
7071
// INCLUDE_TREE-NEXT: module:
7172
// INCLUDE_TREE-NEXT: name: ModA
7273
// INCLUDE_TREE-NEXT: context-hash: [[HASH_MOD_A:[A-Z0-9]+]]
74+
// INCLUDE_TREE-NEXT: cwd-ignored: 0
7375
// INCLUDE_TREE-NEXT: module-map-path: [[PREFIX]]/Inputs/module/module.modulemap
7476
// INCLUDE_TREE-NEXT: include-tree-id: [[ModA_INCLUDE_TREE_ID:llvmcas://[[:xdigit:]]+]]
7577
// INCLUDE_TREE-NEXT: cache-key: [[ModA_CACHE_KEY:llvmcas://[[:xdigit:]]+]]

clang/test/Index/Core/scan-deps.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
// CHECK-NEXT: module:
2222
// CHECK-NEXT: name: ModA
2323
// CHECK-NEXT: context-hash: [[HASH_MOD_A:[A-Z0-9]+]]
24+
// CHECK-NEXT: cwd-ignored: 0
2425
// CHECK-NEXT: module-map-path: [[PREFIX]]/Inputs/module/module.modulemap
2526
// CHECK-NEXT: module-deps:
2627
// CHECK-NEXT: file-deps:

clang/tools/c-index-test/core_main.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,11 @@ static cl::opt<bool> TestCASCancellation(
161161
"test-cas-cancellation",
162162
cl::desc(
163163
"perform extra CAS API invocation and cancel it for testing purposes"));
164-
}
164+
static cl::opt<bool> OptimizeCWD(
165+
"optimize-cwd",
166+
cl::desc(
167+
"instruct the scanner to ignore current working directory if safe."));
168+
} // namespace options
165169
} // anonymous namespace
166170

167171
static void printSymbolInfo(SymbolInfo SymInfo, raw_ostream &OS);
@@ -714,6 +718,10 @@ static int scanDeps(ArrayRef<const char *> Args, std::string WorkingDirectory,
714718
clang_experimental_DependencyScannerServiceOptions_setDependencyMode(
715719
Opts, CXDependencyMode_Full);
716720

721+
if (options::OptimizeCWD)
722+
clang_experimental_DependencyScannerServiceOptions_setCWDOptimization(Opts,
723+
1);
724+
717725
if (DBs)
718726
clang_experimental_DependencyScannerServiceOptions_setCASDatabases(Opts,
719727
DBs);
@@ -806,6 +814,7 @@ static int scanDeps(ArrayRef<const char *> Args, std::string WorkingDirectory,
806814
const char *Name = clang_experimental_DepGraphModule_getName(Mod);
807815
const char *ContextHash =
808816
clang_experimental_DepGraphModule_getContextHash(Mod);
817+
int CwdIgnored = clang_experimental_DepGraphModule_isCWDIgnored(Mod);
809818
const char *ModuleMapPath =
810819
clang_experimental_DepGraphModule_getModuleMapPath(Mod);
811820
const char *ModuleIncludeTreeID =
@@ -823,6 +832,7 @@ static int scanDeps(ArrayRef<const char *> Args, std::string WorkingDirectory,
823832
llvm::outs() << " module:\n"
824833
<< " name: " << Name << "\n"
825834
<< " context-hash: " << ContextHash << "\n"
835+
<< " cwd-ignored: " << CwdIgnored << "\n"
826836
<< " module-map-path: "
827837
<< (ModuleMapPath ? ModuleMapPath : "<none>") << "\n";
828838
if (ModuleIncludeTreeID)

clang/tools/libclang/CDependencies.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ namespace {
3434
struct DependencyScannerServiceOptions {
3535
ScanningOutputFormat ConfiguredFormat = ScanningOutputFormat::Full;
3636
CASOptions CASOpts;
37+
ScanningOptimizations OptimizeArgs = ScanningOptimizations::Default;
3738
std::shared_ptr<cas::ObjectStore> CAS;
3839
std::shared_ptr<cas::ActionCache> Cache;
3940

@@ -115,6 +116,15 @@ void clang_experimental_DependencyScannerServiceOptions_setCASOptions(
115116
unwrap(Opts)->CASOpts = *cas::unwrap(CASOpts);
116117
}
117118

119+
void clang_experimental_DependencyScannerServiceOptions_setCWDOptimization(
120+
CXDependencyScannerServiceOptions Opts, int Value) {
121+
auto Mask =
122+
Value != 0 ? ScanningOptimizations::All : ScanningOptimizations::None;
123+
auto OptArgs = unwrap(Opts)->OptimizeArgs;
124+
unwrap(Opts)->OptimizeArgs = (OptArgs & ~ScanningOptimizations::IgnoreCWD) |
125+
(ScanningOptimizations::IgnoreCWD & Mask);
126+
}
127+
118128
void clang_experimental_DependencyScannerServiceOptions_setObjectStore(
119129
CXDependencyScannerServiceOptions Opts, CXCASObjectStore CAS) {
120130
unwrap(Opts)->CAS = cas::unwrap(CAS)->CAS;
@@ -171,7 +181,8 @@ clang_experimental_DependencyScannerService_create_v1(
171181
}
172182
return wrap(new DependencyScanningService(
173183
ScanningMode::DependencyDirectivesScan, Format, unwrap(Opts)->CASOpts,
174-
std::move(CAS), std::move(Cache), std::move(FS)));
184+
std::move(CAS), std::move(Cache), std::move(FS),
185+
unwrap(Opts)->OptimizeArgs));
175186
}
176187

177188
void clang_experimental_DependencyScannerService_dispose_v0(
@@ -630,6 +641,10 @@ clang_experimental_DepGraphModule_getCacheKey(CXDepGraphModule CXDepMod) {
630641
return nullptr;
631642
}
632643

644+
int clang_experimental_DepGraphModule_isCWDIgnored(CXDepGraphModule CXDepMod) {
645+
return unwrap(CXDepMod)->ModDeps->IgnoreCWD;
646+
}
647+
633648
size_t clang_experimental_DepGraph_getNumTUCommands(CXDepGraph Graph) {
634649
TranslationUnitDeps &TUDeps = unwrap(Graph)->TUDeps;
635650
return TUDeps.Commands.size();

clang/tools/libclang/libclang.map

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,12 @@ LLVM_19 {
569569
clang_Cursor_getBinaryOpcodeStr;
570570
};
571571

572+
LLVM_21 {
573+
global:
574+
clang_experimental_DependencyScannerServiceOptions_setCWDOptimization;
575+
clang_experimental_DepGraphModule_isCWDIgnored;
576+
};
577+
572578
# Example of how to add a new symbol version entry. If you do add a new symbol
573579
# version, please update the example to depend on the version you added.
574580
# LLVM_X {

0 commit comments

Comments
 (0)