Skip to content

Commit 73856a5

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. (cherry picked from commit fa17ed7)
1 parent 5278f1b commit 73856a5

File tree

5 files changed

+135
-21
lines changed

5 files changed

+135
-21
lines changed

clang/include/clang-c/Dependencies.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,27 @@ typedef struct CXOpaqueDepGraphTUCommand *CXDepGraphTUCommand;
417417
typedef struct CXOpaqueDependencyScannerWorkerScanSettings
418418
*CXDependencyScannerWorkerScanSettings;
419419

420+
/**
421+
* A callback that is called to determine the paths of output files for each
422+
* module dependency. The ModuleFile (pcm) path mapping is mandatory.
423+
*
424+
* \param Context the MLOContext that was passed to
425+
* \c clang_experimental_DependencyScannerWorker_getFileDependencies_vX.
426+
* \param CXDepMod the ModuleDep that represents the dependent module.
427+
* \param OutputKind the kind of module output to lookup.
428+
* \param[out] Output the output path(s) or name, whose total size must be <=
429+
* \p MaxLen. In the case of multiple outputs of the same
430+
* kind, this can be a null-separated list.
431+
* \param MaxLen the maximum size of Output.
432+
*
433+
* \returns the actual length of Output. If the return value is > \p MaxLen,
434+
* the callback will be repeated with a larger buffer.
435+
*/
436+
typedef size_t CXModuleLookupOutputCallback_v2(void *Context,
437+
CXDepGraphModule CXDepMod,
438+
CXOutputKind OutputKind,
439+
char *Output, size_t MaxLen);
440+
420441
/**
421442
* Creates a set of settings for
422443
* \c clang_experimental_DependencyScannerWorker_getDepGraph action.
@@ -447,6 +468,23 @@ clang_experimental_DependencyScannerWorkerScanSettings_create(
447468
const char *WorkingDirectory, void *MLOContext,
448469
CXModuleLookupOutputCallback *MLO);
449470

471+
/**
472+
* Override the ModuleLookupOutputCallback with \c
473+
* CXModuleLookupOutputCallback_v2 in the scanner settings for queries of module
474+
* dependencies. This is required for handling output paths of modules that
475+
* depend on attributes encoded in
476+
* \c CXDepGraphModule.
477+
*
478+
* \param Settings object created via
479+
* \c clang_experimental_DependencyScannerWorkerScanSettings_create.
480+
* \param MLO a callback that is called to determine the paths of output files
481+
* for each module dependency. This may receive the same module on
482+
* different workers.
483+
*/
484+
CINDEX_LINKAGE void
485+
clang_experimental_DependencyScannerWorkerScanSettings_setModuleLookupCallback(
486+
CXDependencyScannerWorkerScanSettings, CXModuleLookupOutputCallback_v2 *);
487+
450488
/**
451489
* Dispose of a \c CXDependencyScannerWorkerScanSettings object.
452490
*/
@@ -565,6 +603,13 @@ CINDEX_LINKAGE CXCStringArray
565603
CINDEX_LINKAGE CXCStringArray
566604
clang_experimental_DepGraphModule_getModuleDeps(CXDepGraphModule);
567605

606+
/**
607+
* \returns whether the provided module is comprised of
608+
* inputs that resolve into stable directories.
609+
*/
610+
CINDEX_LINKAGE bool
611+
clang_experimental_DepGraphModule_isInStableDirs(CXDepGraphModule);
612+
568613
/**
569614
* \returns the canonical command line to build this module.
570615
*
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
@@ -815,6 +815,8 @@ static int scanDeps(ArrayRef<const char *> Args, std::string WorkingDirectory,
815815
const char *ContextHash =
816816
clang_experimental_DepGraphModule_getContextHash(Mod);
817817
int CwdIgnored = clang_experimental_DepGraphModule_isCWDIgnored(Mod);
818+
bool IsInStableDir =
819+
clang_experimental_DepGraphModule_isInStableDirs(Mod);
818820
const char *ModuleMapPath =
819821
clang_experimental_DepGraphModule_getModuleMapPath(Mod);
820822
const char *ModuleIncludeTreeID =
@@ -835,6 +837,9 @@ static int scanDeps(ArrayRef<const char *> Args, std::string WorkingDirectory,
835837
<< " cwd-ignored: " << CwdIgnored << "\n"
836838
<< " module-map-path: "
837839
<< (ModuleMapPath ? ModuleMapPath : "<none>") << "\n";
840+
if (IsInStableDir)
841+
llvm::outs() << " is-in-stable-directories: " << IsInStableDir
842+
<< "\n";
838843
if (ModuleIncludeTreeID)
839844
llvm::outs() << " include-tree-id: " << ModuleIncludeTreeID << "\n";
840845
if (ModuleCacheKey)

clang/tools/libclang/CDependencies.cpp

Lines changed: 59 additions & 21 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"
@@ -332,14 +333,18 @@ static CXErrorCode getFileDependencies(CXDependencyScannerWorker W, int argc,
332333
namespace {
333334
class OutputLookup {
334335
public:
335-
OutputLookup(void *MLOContext, CXModuleLookupOutputCallback *MLO)
336+
OutputLookup(void *MLOContext, std::variant<CXModuleLookupOutputCallback *,
337+
CXModuleLookupOutputCallback_v2 *>
338+
MLO)
336339
: MLOContext(MLOContext), MLO(MLO) {}
337340
std::string lookupModuleOutput(const ModuleDeps &MD, ModuleOutputKind MOK);
338341

339342
private:
340343
llvm::DenseMap<ModuleID, std::string> PCMPaths;
341344
void *MLOContext;
342-
CXModuleLookupOutputCallback *MLO;
345+
std::variant<CXModuleLookupOutputCallback *,
346+
CXModuleLookupOutputCallback_v2 *>
347+
MLO;
343348
};
344349
} // end anonymous namespace
345350

@@ -422,7 +427,9 @@ struct DependencyScannerWorkerScanSettings {
422427
const char *ModuleName;
423428
const char *WorkingDirectory;
424429
void *MLOContext;
425-
CXModuleLookupOutputCallback *MLO;
430+
std::variant<CXModuleLookupOutputCallback *,
431+
CXModuleLookupOutputCallback_v2 *>
432+
MLO;
426433
};
427434

428435
struct CStringsManager {
@@ -482,7 +489,7 @@ struct DependencyGraph {
482489
};
483490

484491
struct DependencyGraphModule {
485-
ModuleDeps *ModDeps;
492+
const ModuleDeps *ModDeps;
486493
CStringsManager StrMgr{};
487494
};
488495

@@ -523,7 +530,9 @@ enum CXErrorCode clang_experimental_DependencyScannerWorker_getDepGraph(
523530
const char *ModuleName = Settings.ModuleName;
524531
const char *WorkingDirectory = Settings.WorkingDirectory;
525532
void *MLOContext = Settings.MLOContext;
526-
CXModuleLookupOutputCallback *MLO = Settings.MLO;
533+
std::variant<CXModuleLookupOutputCallback *,
534+
CXModuleLookupOutputCallback_v2 *>
535+
MLO = Settings.MLO;
527536

528537
OutputLookup OL(MLOContext, MLO);
529538
auto LookupOutputs = [&](const ModuleDeps &MD, ModuleOutputKind MOK) {
@@ -582,60 +591,65 @@ void clang_experimental_DepGraphModule_dispose(CXDepGraphModule CXDepMod) {
582591

583592
const char *
584593
clang_experimental_DepGraphModule_getName(CXDepGraphModule CXDepMod) {
585-
ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
594+
const ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
586595
return ModDeps.ID.ModuleName.c_str();
587596
}
588597

589598
const char *
590599
clang_experimental_DepGraphModule_getContextHash(CXDepGraphModule CXDepMod) {
591-
ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
600+
const ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
592601
return ModDeps.ID.ContextHash.c_str();
593602
}
594603

595604
const char *
596605
clang_experimental_DepGraphModule_getModuleMapPath(CXDepGraphModule CXDepMod) {
597-
ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
606+
const ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
598607
if (ModDeps.ClangModuleMapFile.empty())
599608
return nullptr;
600609
return ModDeps.ClangModuleMapFile.c_str();
601610
}
602611

603612
CXCStringArray
604613
clang_experimental_DepGraphModule_getFileDeps(CXDepGraphModule CXDepMod) {
605-
ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
614+
const ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
606615
std::vector<std::string> FileDeps;
607616
ModDeps.forEachFileDep([&](StringRef File) { FileDeps.emplace_back(File); });
608617
return unwrap(CXDepMod)->StrMgr.createCStringsOwned(std::move(FileDeps));
609618
}
610619

611620
CXCStringArray
612621
clang_experimental_DepGraphModule_getModuleDeps(CXDepGraphModule CXDepMod) {
613-
ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
622+
const ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
614623
std::vector<std::string> Modules;
615624
Modules.reserve(ModDeps.ClangModuleDeps.size());
616625
for (const ModuleID &MID : ModDeps.ClangModuleDeps)
617626
Modules.push_back(MID.ModuleName + ":" + MID.ContextHash);
618627
return unwrap(CXDepMod)->StrMgr.createCStringsOwned(std::move(Modules));
619628
}
620629

630+
bool clang_experimental_DepGraphModule_isInStableDirs(
631+
CXDepGraphModule CXDepMod) {
632+
return unwrap(CXDepMod)->ModDeps->IsInStableDirectories;
633+
}
634+
621635
CXCStringArray
622636
clang_experimental_DepGraphModule_getBuildArguments(CXDepGraphModule CXDepMod) {
623-
ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
637+
const ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
624638
return unwrap(CXDepMod)->StrMgr.createCStringsRef(
625639
ModDeps.getBuildArguments());
626640
}
627641

628642
const char *
629643
clang_experimental_DepGraphModule_getIncludeTreeID(CXDepGraphModule CXDepMod) {
630-
ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
644+
const ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
631645
if (ModDeps.IncludeTreeID)
632646
return ModDeps.IncludeTreeID->c_str();
633647
return nullptr;
634648
}
635649

636650
const char *
637651
clang_experimental_DepGraphModule_getCacheKey(CXDepGraphModule CXDepMod) {
638-
ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
652+
const ModuleDeps &ModDeps = *unwrap(CXDepMod)->ModDeps;
639653
if (ModDeps.ModuleCacheKey)
640654
return ModDeps.ModuleCacheKey->c_str();
641655
return nullptr;
@@ -706,22 +720,46 @@ const char *clang_experimental_DepGraph_getTUContextHash(CXDepGraph Graph) {
706720
return TUDeps.ID.ContextHash.c_str();
707721
}
708722

723+
void clang_experimental_DependencyScannerWorkerScanSettings_setModuleLookupCallback(
724+
CXDependencyScannerWorkerScanSettings CXSettings,
725+
CXModuleLookupOutputCallback_v2 *MLO) {
726+
DependencyScannerWorkerScanSettings &Settings = *unwrap(CXSettings);
727+
Settings.MLO = MLO;
728+
}
729+
709730
CXDiagnosticSet clang_experimental_DepGraph_getDiagnostics(CXDepGraph Graph) {
710731
return unwrap(Graph)->getDiagnosticSet();
711732
}
712733

713-
static std::string lookupModuleOutput(const ModuleDeps &MD,
714-
ModuleOutputKind MOK, void *MLOContext,
715-
CXModuleLookupOutputCallback *MLO) {
734+
static std::string
735+
lookupModuleOutput(const ModuleDeps &MD, ModuleOutputKind MOK, void *MLOContext,
736+
std::variant<CXModuleLookupOutputCallback *,
737+
CXModuleLookupOutputCallback_v2 *>
738+
MLO) {
716739
SmallVector<char, 256> Buffer(256);
717-
size_t Len =
718-
MLO(MLOContext, MD.ID.ModuleName.c_str(), MD.ID.ContextHash.c_str(),
719-
wrap(MOK), Buffer.data(), Buffer.size());
740+
auto GetLengthFromOutputCallback = [&]() {
741+
return std::visit(llvm::makeVisitor(
742+
[&](CXModuleLookupOutputCallback *) -> size_t {
743+
return std::get<CXModuleLookupOutputCallback *>(
744+
MLO)(MLOContext, MD.ID.ModuleName.c_str(),
745+
MD.ID.ContextHash.c_str(), wrap(MOK),
746+
Buffer.data(), Buffer.size());
747+
},
748+
[&](CXModuleLookupOutputCallback_v2 *) -> size_t {
749+
return std::get<CXModuleLookupOutputCallback_v2 *>(
750+
MLO)(MLOContext,
751+
wrap(new DependencyGraphModule{&MD}),
752+
wrap(MOK), Buffer.data(), Buffer.size());
753+
}),
754+
MLO);
755+
};
756+
757+
size_t Len = GetLengthFromOutputCallback();
720758
if (Len > Buffer.size()) {
721759
Buffer.resize(Len);
722-
Len = MLO(MLOContext, MD.ID.ModuleName.c_str(), MD.ID.ContextHash.c_str(),
723-
wrap(MOK), Buffer.data(), Buffer.size());
760+
Len = GetLengthFromOutputCallback();
724761
}
762+
725763
return std::string(Buffer.begin(), Len);
726764
}
727765

clang/tools/libclang/libclang.map

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,7 @@ LLVM_21 {
574574
global:
575575
clang_experimental_DependencyScannerServiceOptions_setCWDOptimization;
576576
clang_experimental_DepGraphModule_isCWDIgnored;
577+
clang_experimental_DepGraphModule_isInStableDirs;
577578
};
578579

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

0 commit comments

Comments
 (0)