Skip to content

Commit b9c8668

Browse files
authored
[clang dependency scanning] C APIs for Current Working Directory Optimization (#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
1 parent c321cd9 commit b9c8668

File tree

12 files changed

+106
-2
lines changed

12 files changed

+106
-2
lines changed

clang/include/clang-c/Dependencies.h

+21
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,20 @@ CINDEX_LINKAGE void
125125
clang_experimental_DependencyScannerServiceOptions_setCASOptions(
126126
CXDependencyScannerServiceOptions Opts, CXCASOptions);
127127

128+
/**
129+
* Set the working directory optimization option.
130+
* The dependency scanner service option Opts will indicate to the scanner that
131+
* the current working directory can or cannot be ignored when computing the
132+
* pcms' context hashes. The scanner will then determine if it is safe to
133+
* optimize each module and act accordingly.
134+
*
135+
* \param Value If it is non zero, the option is on. Otherwise the
136+
* option is off.
137+
*/
138+
CINDEX_LINKAGE void
139+
clang_experimental_DependencyScannerServiceOptions_setCWDOptimization(
140+
CXDependencyScannerServiceOptions Opts, int Value);
141+
128142
/**
129143
* Specify a \c CXCASObjectStore in the given options. If an object store and
130144
* action cache are available, the scanner will produce cached commands.
@@ -420,6 +434,13 @@ CINDEX_LINKAGE const char *
420434
CINDEX_LINKAGE
421435
const char *clang_experimental_DepGraphModule_getCacheKey(CXDepGraphModule);
422436

437+
/**
438+
* \returns 1 if the scanner ignores the current working directory when
439+
* computing the module's context hash. Otherwise returns 0.
440+
*/
441+
CINDEX_LINKAGE
442+
int clang_experimental_DepGraphModule_isCWDIgnored(CXDepGraphModule);
443+
423444
/**
424445
* \returns the number \c CXDepGraphTUCommand objects in the graph.
425446
*/

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

+3
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

+1
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,7 @@ ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
869869
MD.ModuleCacheKey = Key->toString();
870870
}
871871

872+
MD.IgnoreCWD = IgnoreCWD;
872873
MDC.associateWithContextHash(CI, IgnoreCWD, MD);
873874

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

clang/test/ClangScanDeps/cas-fs-multiple-commands.c

+1
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@
195195
// CHECK-LIBCLANG-NEXT: module:
196196
// CHECK-LIBCLANG-NEXT: name: Mod
197197
// CHECK-LIBCLANG-NEXT: context-hash: {{.*}}
198+
// CHECK-LIBCLANG-NEXT: cwd-ignored: 0
198199
// CHECK-LIBCLANG-NEXT: module-map-path: [[PREFIX]]/module.modulemap
199200
// CHECK-LIBCLANG-NEXT: casfs-root-id: [[M_ROOT_ID:llvmcas://[[:xdigit:]]+]]
200201
// CHECK-LIBCLANG-NEXT: cache-key: [[M_CACHE_KEY:llvmcas://[[:xdigit:]]+]]

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

+42
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/ClangScanDeps/include-tree-multiple-commands.c

+1
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@
195195
// CHECK-LIBCLANG-NEXT: module:
196196
// CHECK-LIBCLANG-NEXT: name: Mod
197197
// CHECK-LIBCLANG-NEXT: context-hash: {{.*}}
198+
// CHECK-LIBCLANG-NEXT: cwd-ignored: 0
198199
// CHECK-LIBCLANG-NEXT: module-map-path: [[PREFIX]]/include/module.modulemap
199200
// CHECK-LIBCLANG-NEXT: include-tree-id: [[M_INCLUDE_TREE:llvmcas://[[:xdigit:]]+]]
200201
// CHECK-LIBCLANG-NEXT: cache-key: [[M_CACHE_KEY:llvmcas://[[:xdigit:]]+]]

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

+1
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

+2
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: casfs-root-id: [[CASFS_MODA_ROOT_ID:llvmcas://[[:xdigit:]]+]]
3738
// CHECK-NEXT: cache-key: [[CASFS_MODA_CACHE_KEY:llvmcas://[[:xdigit:]]+]]
@@ -72,6 +73,7 @@
7273
// INCLUDE_TREE-NEXT: module:
7374
// INCLUDE_TREE-NEXT: name: ModA
7475
// INCLUDE_TREE-NEXT: context-hash: [[HASH_MOD_A:[A-Z0-9]+]]
76+
// INCLUDE_TREE-NEXT: cwd-ignored: 0
7577
// INCLUDE_TREE-NEXT: module-map-path: [[PREFIX]]/Inputs/module/module.modulemap
7678
// INCLUDE_TREE-NEXT: include-tree-id: [[ModA_INCLUDE_TREE_ID:llvmcas://[[:xdigit:]]+]]
7779
// INCLUDE_TREE-NEXT: cache-key: [[ModA_CACHE_KEY:llvmcas://[[:xdigit:]]+]]

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

+1
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

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

168172
static void printSymbolInfo(SymbolInfo SymInfo, raw_ostream &OS);
@@ -717,6 +721,10 @@ static int scanDeps(ArrayRef<const char *> Args, std::string WorkingDirectory,
717721
clang_experimental_DependencyScannerServiceOptions_setDependencyMode(
718722
Opts, CXDependencyMode_Full);
719723

724+
if (options::OptimizeCWD)
725+
clang_experimental_DependencyScannerServiceOptions_setCWDOptimization(Opts,
726+
1);
727+
720728
if (DBs)
721729
clang_experimental_DependencyScannerServiceOptions_setCASDatabases(Opts,
722730
DBs);
@@ -813,6 +821,7 @@ static int scanDeps(ArrayRef<const char *> Args, std::string WorkingDirectory,
813821
const char *Name = clang_experimental_DepGraphModule_getName(Mod);
814822
const char *ContextHash =
815823
clang_experimental_DepGraphModule_getContextHash(Mod);
824+
int CwdIgnored = clang_experimental_DepGraphModule_isCWDIgnored(Mod);
816825
const char *ModuleMapPath =
817826
clang_experimental_DepGraphModule_getModuleMapPath(Mod);
818827
const char *ModuleFilesystemRootID =
@@ -832,6 +841,7 @@ static int scanDeps(ArrayRef<const char *> Args, std::string WorkingDirectory,
832841
llvm::outs() << " module:\n"
833842
<< " name: " << Name << "\n"
834843
<< " context-hash: " << ContextHash << "\n"
844+
<< " cwd-ignored: " << CwdIgnored << "\n"
835845
<< " module-map-path: "
836846
<< (ModuleMapPath ? ModuleMapPath : "<none>") << "\n";
837847
if (ModuleFilesystemRootID)

clang/tools/libclang/CDependencies.cpp

+16-1
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

@@ -100,6 +101,15 @@ void clang_experimental_DependencyScannerServiceOptions_setCASOptions(
100101
unwrap(Opts)->CASOpts = *cas::unwrap(CASOpts);
101102
}
102103

104+
void clang_experimental_DependencyScannerServiceOptions_setCWDOptimization(
105+
CXDependencyScannerServiceOptions Opts, int Value) {
106+
auto Mask =
107+
Value != 0 ? ScanningOptimizations::All : ScanningOptimizations::None;
108+
auto OptArgs = unwrap(Opts)->OptimizeArgs;
109+
unwrap(Opts)->OptimizeArgs = (OptArgs & ~ScanningOptimizations::IgnoreCWD) |
110+
(ScanningOptimizations::IgnoreCWD & Mask);
111+
}
112+
103113
void clang_experimental_DependencyScannerServiceOptions_setObjectStore(
104114
CXDependencyScannerServiceOptions Opts, CXCASObjectStore CAS) {
105115
unwrap(Opts)->CAS = cas::unwrap(CAS)->CAS;
@@ -156,7 +166,8 @@ clang_experimental_DependencyScannerService_create_v1(
156166
}
157167
return wrap(new DependencyScanningService(
158168
ScanningMode::DependencyDirectivesScan, Format, unwrap(Opts)->CASOpts,
159-
std::move(CAS), std::move(Cache), std::move(FS)));
169+
std::move(CAS), std::move(Cache), std::move(FS),
170+
unwrap(Opts)->OptimizeArgs));
160171
}
161172

162173
void clang_experimental_DependencyScannerService_dispose_v0(
@@ -452,6 +463,10 @@ clang_experimental_DepGraphModule_getCacheKey(CXDepGraphModule CXDepMod) {
452463
return nullptr;
453464
}
454465

466+
int clang_experimental_DepGraphModule_isCWDIgnored(CXDepGraphModule CXDepMod) {
467+
return unwrap(CXDepMod)->ModDeps->IgnoreCWD;
468+
}
469+
455470
size_t clang_experimental_DepGraph_getNumTUCommands(CXDepGraph Graph) {
456471
TranslationUnitDeps &TUDeps = unwrap(Graph)->TUDeps;
457472
return TUDeps.Commands.size();

clang/tools/libclang/libclang.map

+6
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,12 @@ LLVM_20 {
570570
clang_visitCXXMethods;
571571
};
572572

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

0 commit comments

Comments
 (0)