Skip to content

Commit fa17ed7

Browse files
committed
[libclang] Add C interface for querying against ModuleDeps
Previously the callback used for getting the output path of pcm's took in the ModuleID, which represents the name & context hash. Now that there are more attributes to determine the output path, like the attribute `isInStableDirectories`. To support this case, allow clients to override the signature of the callback to pass along a reference to the whole `ModuleDep` object instead. Additionally, this patch: * Makes calls that unwrap `CXDepGraphModule` const correct. * Provides an API to query whether a module comes from stable directories.
1 parent f8910af commit fa17ed7

File tree

5 files changed

+136
-22
lines changed

5 files changed

+136
-22
lines changed

clang/include/clang-c/Dependencies.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,27 @@ typedef struct CXOpaqueDepGraphTUCommand *CXDepGraphTUCommand;
250250
typedef struct CXOpaqueDependencyScannerWorkerScanSettings
251251
*CXDependencyScannerWorkerScanSettings;
252252

253+
/**
254+
* A callback that is called to determine the paths of output files for each
255+
* module dependency. The ModuleFile (pcm) path mapping is mandatory.
256+
*
257+
* \param Context the MLOContext that was passed to
258+
* \c clang_experimental_DependencyScannerWorker_getFileDependencies_vX.
259+
* \param CXDepMod the ModuleDep that represents the dependent module.
260+
* \param OutputKind the kind of module output to lookup.
261+
* \param[out] Output the output path(s) or name, whose total size must be <=
262+
* \p MaxLen. In the case of multiple outputs of the same
263+
* kind, this can be a null-separated list.
264+
* \param MaxLen the maximum size of Output.
265+
*
266+
* \returns the actual length of Output. If the return value is > \p MaxLen,
267+
* the callback will be repeated with a larger buffer.
268+
*/
269+
typedef size_t CXModuleLookupOutputCallback_v2(void *Context,
270+
CXDepGraphModule CXDepMod,
271+
CXOutputKind OutputKind,
272+
char *Output, size_t MaxLen);
273+
253274
/**
254275
* Creates a set of settings for
255276
* \c clang_experimental_DependencyScannerWorker_getDepGraph action.
@@ -280,6 +301,23 @@ clang_experimental_DependencyScannerWorkerScanSettings_create(
280301
const char *WorkingDirectory, void *MLOContext,
281302
CXModuleLookupOutputCallback *MLO);
282303

304+
/**
305+
* Override the ModuleLookupOutputCallback with \c
306+
* CXModuleLookupOutputCallback_v2 in the scanner settings for queries of module
307+
* dependencies. This is required for handling output paths of modules that
308+
* depend on attributes encoded in
309+
* \c CXDepGraphModule.
310+
*
311+
* \param Settings object created via
312+
* \c clang_experimental_DependencyScannerWorkerScanSettings_create.
313+
* \param MLO a callback that is called to determine the paths of output files
314+
* for each module dependency. This may receive the same module on
315+
* different workers.
316+
*/
317+
CINDEX_LINKAGE void
318+
clang_experimental_DependencyScannerWorkerScanSettings_setModuleLookupCallback(
319+
CXDependencyScannerWorkerScanSettings, CXModuleLookupOutputCallback_v2 *);
320+
283321
/**
284322
* Dispose of a \c CXDependencyScannerWorkerScanSettings object.
285323
*/
@@ -398,6 +436,13 @@ CINDEX_LINKAGE CXCStringArray
398436
CINDEX_LINKAGE CXCStringArray
399437
clang_experimental_DepGraphModule_getModuleDeps(CXDepGraphModule);
400438

439+
/**
440+
* \returns whether the provided module is comprised of
441+
* inputs that resolve into stable directories.
442+
*/
443+
CINDEX_LINKAGE bool
444+
clang_experimental_DepGraphModule_isInStableDirs(CXDepGraphModule);
445+
401446
/**
402447
* \returns the canonical command line to build this module.
403448
*
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// REQUIRES: shell
2+
// RUN: rm -rf %t
3+
// RUN: split-file %s %t
4+
5+
// RUN: c-index-test core -scan-deps -working-dir %S -- %clang \
6+
// RUN: -c %t/client.c -fmodules -fmodules-cache-path=%t/module-cache \
7+
// RUN: -isysroot %t/Sysroot -I %t/Sysroot/usr/include 2>&1 | FileCheck %s \
8+
// RUN: -implicit-check-not error: -implicit-check-not=warning:
9+
10+
//--- Sysroot/usr/include/A/module.modulemap
11+
module A {
12+
umbrella "."
13+
}
14+
15+
//--- Sysroot/usr/include/A/A.h
16+
typedef int A_t;
17+
18+
//--- client.c
19+
#include <A/A.h>
20+
21+
22+
// CHECK: module:
23+
// CHECK-NEXT: name: A
24+
// CHECK: is-in-stable-directories: 1
25+

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,8 @@ static int scanDeps(ArrayRef<const char *> Args, std::string WorkingDirectory,
822822
const char *ContextHash =
823823
clang_experimental_DepGraphModule_getContextHash(Mod);
824824
int CwdIgnored = clang_experimental_DepGraphModule_isCWDIgnored(Mod);
825+
bool IsInStableDir =
826+
clang_experimental_DepGraphModule_isInStableDirs(Mod);
825827
const char *ModuleMapPath =
826828
clang_experimental_DepGraphModule_getModuleMapPath(Mod);
827829
const char *ModuleFilesystemRootID =
@@ -844,6 +846,9 @@ static int scanDeps(ArrayRef<const char *> Args, std::string WorkingDirectory,
844846
<< " cwd-ignored: " << CwdIgnored << "\n"
845847
<< " module-map-path: "
846848
<< (ModuleMapPath ? ModuleMapPath : "<none>") << "\n";
849+
if (IsInStableDir)
850+
llvm::outs() << " is-in-stable-directories: " << IsInStableDir
851+
<< "\n";
847852
if (ModuleFilesystemRootID)
848853
llvm::outs() << " casfs-root-id: " << ModuleFilesystemRootID << "\n";
849854
if (ModuleIncludeTreeID)

clang/tools/libclang/CDependencies.cpp

Lines changed: 60 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "clang/Tooling/DependencyScanning/DependencyScanningService.h"
2424
#include "clang/Tooling/DependencyScanning/DependencyScanningTool.h"
2525
#include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h"
26+
#include "llvm/ADT/STLExtras.h"
2627
#include "llvm/CAS/CASProvidingFileSystem.h"
2728
#include "llvm/CAS/CachingOnDiskFileSystem.h"
2829
#include "llvm/Support/Process.h"
@@ -197,14 +198,18 @@ void clang_experimental_DependencyScannerWorker_dispose_v0(
197198
namespace {
198199
class OutputLookup {
199200
public:
200-
OutputLookup(void *MLOContext, CXModuleLookupOutputCallback *MLO)
201+
OutputLookup(void *MLOContext, std::variant<CXModuleLookupOutputCallback *,
202+
CXModuleLookupOutputCallback_v2 *>
203+
MLO)
201204
: MLOContext(MLOContext), MLO(MLO) {}
202205
std::string lookupModuleOutput(const ModuleDeps &MD, ModuleOutputKind MOK);
203206

204207
private:
205208
llvm::DenseMap<ModuleID, std::string> PCMPaths;
206209
void *MLOContext;
207-
CXModuleLookupOutputCallback *MLO;
210+
std::variant<CXModuleLookupOutputCallback *,
211+
CXModuleLookupOutputCallback_v2 *>
212+
MLO;
208213
};
209214

210215
struct DependencyScannerWorkerScanSettings {
@@ -213,7 +218,9 @@ struct DependencyScannerWorkerScanSettings {
213218
const char *ModuleName;
214219
const char *WorkingDirectory;
215220
void *MLOContext;
216-
CXModuleLookupOutputCallback *MLO;
221+
std::variant<CXModuleLookupOutputCallback *,
222+
CXModuleLookupOutputCallback_v2 *>
223+
MLO;
217224
};
218225

219226
struct CStringsManager {
@@ -273,7 +280,7 @@ struct DependencyGraph {
273280
};
274281

275282
struct DependencyGraphModule {
276-
ModuleDeps *ModDeps;
283+
const ModuleDeps *ModDeps;
277284
CStringsManager StrMgr{};
278285
};
279286

@@ -314,7 +321,9 @@ enum CXErrorCode clang_experimental_DependencyScannerWorker_getDepGraph(
314321
const char *ModuleName = Settings.ModuleName;
315322
const char *WorkingDirectory = Settings.WorkingDirectory;
316323
void *MLOContext = Settings.MLOContext;
317-
CXModuleLookupOutputCallback *MLO = Settings.MLO;
324+
std::variant<CXModuleLookupOutputCallback *,
325+
CXModuleLookupOutputCallback_v2 *>
326+
MLO = Settings.MLO;
318327

319328
OutputLookup OL(MLOContext, MLO);
320329
auto LookupOutputs = [&](const ModuleDeps &MD, ModuleOutputKind MOK) {
@@ -396,68 +405,73 @@ void clang_experimental_DepGraphModule_dispose(CXDepGraphModule CXDepMod) {
396405

397406
const char *
398407
clang_experimental_DepGraphModule_getName(CXDepGraphModule CXDepMod) {
399-
ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
408+
const ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
400409
return ModDeps.ID.ModuleName.c_str();
401410
}
402411

403412
const char *
404413
clang_experimental_DepGraphModule_getContextHash(CXDepGraphModule CXDepMod) {
405-
ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
414+
const ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
406415
return ModDeps.ID.ContextHash.c_str();
407416
}
408417

409418
const char *
410419
clang_experimental_DepGraphModule_getModuleMapPath(CXDepGraphModule CXDepMod) {
411-
ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
420+
const ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
412421
if (ModDeps.ClangModuleMapFile.empty())
413422
return nullptr;
414423
return ModDeps.ClangModuleMapFile.c_str();
415424
}
416425

417426
CXCStringArray
418427
clang_experimental_DepGraphModule_getFileDeps(CXDepGraphModule CXDepMod) {
419-
ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
428+
const ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
420429
std::vector<std::string> FileDeps;
421430
ModDeps.forEachFileDep([&](StringRef File) { FileDeps.emplace_back(File); });
422431
return unwrap(CXDepMod)->StrMgr.createCStringsOwned(std::move(FileDeps));
423432
}
424433

425434
CXCStringArray
426435
clang_experimental_DepGraphModule_getModuleDeps(CXDepGraphModule CXDepMod) {
427-
ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
436+
const ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
428437
std::vector<std::string> Modules;
429438
Modules.reserve(ModDeps.ClangModuleDeps.size());
430439
for (const ModuleID &MID : ModDeps.ClangModuleDeps)
431440
Modules.push_back(MID.ModuleName + ":" + MID.ContextHash);
432441
return unwrap(CXDepMod)->StrMgr.createCStringsOwned(std::move(Modules));
433442
}
434443

444+
bool clang_experimental_DepGraphModule_isInStableDirs(
445+
CXDepGraphModule CXDepMod) {
446+
return unwrap(CXDepMod)->ModDeps->IsInStableDirectories;
447+
}
448+
435449
CXCStringArray
436450
clang_experimental_DepGraphModule_getBuildArguments(CXDepGraphModule CXDepMod) {
437-
ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
451+
const ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
438452
return unwrap(CXDepMod)->StrMgr.createCStringsRef(
439453
ModDeps.getBuildArguments());
440454
}
441455

442456
const char *clang_experimental_DepGraphModule_getFileSystemRootID(
443457
CXDepGraphModule CXDepMod) {
444-
ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
458+
const ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
445459
if (ModDeps.CASFileSystemRootID)
446460
return ModDeps.CASFileSystemRootID->c_str();
447461
return nullptr;
448462
}
449463

450464
const char *
451465
clang_experimental_DepGraphModule_getIncludeTreeID(CXDepGraphModule CXDepMod) {
452-
ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
466+
const ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
453467
if (ModDeps.IncludeTreeID)
454468
return ModDeps.IncludeTreeID->c_str();
455469
return nullptr;
456470
}
457471

458472
const char *
459473
clang_experimental_DepGraphModule_getCacheKey(CXDepGraphModule CXDepMod) {
460-
ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
474+
const ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
461475
if (ModDeps.ModuleCacheKey)
462476
return ModDeps.ModuleCacheKey->c_str();
463477
return nullptr;
@@ -536,22 +550,46 @@ const char *clang_experimental_DepGraph_getTUContextHash(CXDepGraph Graph) {
536550
return TUDeps.ID.ContextHash.c_str();
537551
}
538552

553+
void clang_experimental_DependencyScannerWorkerScanSettings_setModuleLookupCallback(
554+
CXDependencyScannerWorkerScanSettings CXSettings,
555+
CXModuleLookupOutputCallback_v2 *MLO) {
556+
DependencyScannerWorkerScanSettings &Settings = *unwrap(CXSettings);
557+
Settings.MLO = MLO;
558+
}
559+
539560
CXDiagnosticSet clang_experimental_DepGraph_getDiagnostics(CXDepGraph Graph) {
540561
return unwrap(Graph)->getDiagnosticSet();
541562
}
542563

543-
static std::string lookupModuleOutput(const ModuleDeps &MD,
544-
ModuleOutputKind MOK, void *MLOContext,
545-
CXModuleLookupOutputCallback *MLO) {
564+
static std::string
565+
lookupModuleOutput(const ModuleDeps &MD, ModuleOutputKind MOK, void *MLOContext,
566+
std::variant<CXModuleLookupOutputCallback *,
567+
CXModuleLookupOutputCallback_v2 *>
568+
MLO) {
546569
SmallVector<char, 256> Buffer(256);
547-
size_t Len =
548-
MLO(MLOContext, MD.ID.ModuleName.c_str(), MD.ID.ContextHash.c_str(),
549-
wrap(MOK), Buffer.data(), Buffer.size());
570+
auto GetLengthFromOutputCallback = [&]() {
571+
return std::visit(llvm::makeVisitor(
572+
[&](CXModuleLookupOutputCallback *) -> size_t {
573+
return std::get<CXModuleLookupOutputCallback *>(
574+
MLO)(MLOContext, MD.ID.ModuleName.c_str(),
575+
MD.ID.ContextHash.c_str(), wrap(MOK),
576+
Buffer.data(), Buffer.size());
577+
},
578+
[&](CXModuleLookupOutputCallback_v2 *) -> size_t {
579+
return std::get<CXModuleLookupOutputCallback_v2 *>(
580+
MLO)(MLOContext,
581+
wrap(new DependencyGraphModule{&MD}),
582+
wrap(MOK), Buffer.data(), Buffer.size());
583+
}),
584+
MLO);
585+
};
586+
587+
size_t Len = GetLengthFromOutputCallback();
550588
if (Len > Buffer.size()) {
551589
Buffer.resize(Len);
552-
Len = MLO(MLOContext, MD.ID.ModuleName.c_str(), MD.ID.ContextHash.c_str(),
553-
wrap(MOK), Buffer.data(), Buffer.size());
590+
Len = GetLengthFromOutputCallback();
554591
}
592+
555593
return std::string(Buffer.begin(), Len);
556594
}
557595

clang/tools/libclang/libclang.map

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,7 @@ LLVM_21 {
575575
global:
576576
clang_experimental_DependencyScannerServiceOptions_setCWDOptimization;
577577
clang_experimental_DepGraphModule_isCWDIgnored;
578+
clang_experimental_DepGraphModule_isInStableDirs;
578579
};
579580

580581
# Example of how to add a new symbol version entry. If you do add a new symbol

0 commit comments

Comments
 (0)