Skip to content

Commit 7a8a697

Browse files
authored
Merge pull request #699 from Bigcheese/scan-deps-apple-master
[Clang][ScanDeps] Add C API and implement enough to build Foundation.
2 parents 39207b5 + 21c4c10 commit 7a8a697

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1272
-37
lines changed

clang/include/clang-c/Dependencies.h

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
/*==-- clang-c/Dependencies.h - Dependency Discovery C Interface --*- C -*-===*\
2+
|* *|
3+
|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
4+
|* Exceptions. *|
5+
|* See https://llvm.org/LICENSE.txt for license information. *|
6+
|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
7+
|* *|
8+
|*===----------------------------------------------------------------------===*|
9+
|* *|
10+
|* This header provides a dependency discovery interface similar to *|
11+
|* clang-scan-deps. *|
12+
|* *|
13+
|* An example of its usage is available in c-index-test/core_main.cpp. *|
14+
|* *|
15+
|* EXPERIMENTAL: These interfaces are experimental and will change. If you *|
16+
|* use these be prepared for them to change without notice on any commit. *|
17+
|* *|
18+
\*===----------------------------------------------------------------------===*/
19+
20+
#ifndef LLVM_CLANG_C_DEPENDENCIES_H
21+
#define LLVM_CLANG_C_DEPENDENCIES_H
22+
23+
#include "clang-c/BuildSystem.h"
24+
#include "clang-c/CXErrorCode.h"
25+
#include "clang-c/CXString.h"
26+
#include "clang-c/Platform.h"
27+
28+
#ifdef __cplusplus
29+
extern "C" {
30+
#endif
31+
32+
/**
33+
* \defgroup SCAN_DEPS Dependency scanning service.
34+
* @{
35+
*/
36+
37+
typedef struct {
38+
CXString Name;
39+
/**
40+
* The context hash of a module represents the set of compiler options that
41+
* may make one version of a module incompatible from another. This includes
42+
* things like language mode, predefined macros, header search paths, etc...
43+
*
44+
* Modules with the same name but a different \c ContextHash should be treated
45+
* as separate modules for the purpose of a build.
46+
*/
47+
CXString ContextHash;
48+
49+
/**
50+
* The path to the modulemap file which defines this module.
51+
*
52+
* This can be used to explicitly build this module. This file will
53+
* additionally appear in \c FileDeps as a dependency.
54+
*/
55+
CXString ModuleMapPath;
56+
57+
/**
58+
* The list of files which this module directly depends on.
59+
*
60+
* If any of these change then the module needs to be rebuilt.
61+
*/
62+
CXStringSet *FileDeps;
63+
64+
/**
65+
* The list of modules which this module direct depends on.
66+
*
67+
* This does include the context hash. The format is
68+
* `<module-name>:<context-hash>`
69+
*/
70+
CXStringSet *ModuleDeps;
71+
72+
/**
73+
* The full command line needed to build this module.
74+
*
75+
* Not including `-fmodule-file=` or `-o`.
76+
*/
77+
CXStringSet *BuildArguments;
78+
} CXModuleDependency;
79+
80+
typedef struct {
81+
int Count;
82+
CXModuleDependency *Modules;
83+
} CXModuleDependencySet;
84+
85+
/**
86+
* See \c CXModuleDependency for the meaning of these fields, with the addition
87+
* that they represent only the direct dependencies for \c CXDependencyMode_Full
88+
* mode.
89+
*/
90+
typedef struct {
91+
CXString ContextHash;
92+
CXStringSet *FileDeps;
93+
CXStringSet *ModuleDeps;
94+
95+
/**
96+
* Additional arguments to append to the build of this file.
97+
*
98+
* This contains things like disabling implicit modules. This does not include
99+
* the `-fmodule-file=` arguments that are needed.
100+
*/
101+
CXStringSet *AdditionalArguments;
102+
} CXFileDependencies;
103+
104+
CINDEX_LINKAGE void
105+
clang_experimental_ModuleDependencySet_dispose(CXModuleDependencySet *MD);
106+
107+
CINDEX_LINKAGE void
108+
clang_experimental_FileDependencies_dispose(CXFileDependencies *ID);
109+
110+
/**
111+
* Object encapsulating instance of a dependency scanner service.
112+
*
113+
* The dependency scanner service is a global instance that owns the
114+
* global cache and other global state that's shared between the dependency
115+
* scanner workers. The service APIs are thread safe.
116+
*/
117+
typedef struct CXOpaqueDependencyScannerService *CXDependencyScannerService;
118+
119+
/**
120+
* The mode to report module dependencies in.
121+
*/
122+
typedef enum {
123+
/**
124+
* Flatten all module dependencies. This reports the full transitive set of
125+
* header and module map dependencies needed to do an implicit module build.
126+
*/
127+
CXDependencyMode_Flat,
128+
129+
/**
130+
* Report the full module graph. This reports only the direct dependencies of
131+
* each file, and calls a callback for each module that is discovered.
132+
*/
133+
CXDependencyMode_Full,
134+
} CXDependencyMode;
135+
136+
/**
137+
* Create a \c CXDependencyScannerService object.
138+
* Must be disposed with \c clang_DependencyScannerService_dispose().
139+
*/
140+
CINDEX_LINKAGE CXDependencyScannerService
141+
clang_experimental_DependencyScannerService_create_v0(CXDependencyMode Format);
142+
143+
/**
144+
* Dispose of a \c CXDependencyScannerService object.
145+
*
146+
* The service object must be disposed of after the workers are disposed of.
147+
*/
148+
CINDEX_LINKAGE void clang_experimental_DependencyScannerService_dispose_v0(
149+
CXDependencyScannerService);
150+
151+
/**
152+
* Object encapsulating instance of a dependency scanner worker.
153+
*
154+
* The dependency scanner workers are expected to be used in separate worker
155+
* threads. An individual worker is not thread safe.
156+
*
157+
* Operations on a worker are not thread-safe and should only be used from a
158+
* single thread at a time. They are intended to be used by a single dedicated
159+
* thread in a thread pool, but they are not inherently pinned to a thread.
160+
*/
161+
typedef struct CXOpaqueDependencyScannerWorker *CXDependencyScannerWorker;
162+
163+
/**
164+
* Create a \c CXDependencyScannerWorker object.
165+
* Must be disposed with
166+
* \c clang_experimental_DependencyScannerWorker_dispose_v0().
167+
*/
168+
CINDEX_LINKAGE CXDependencyScannerWorker
169+
clang_experimental_DependencyScannerWorker_create_v0(
170+
CXDependencyScannerService);
171+
172+
CINDEX_LINKAGE void clang_experimental_DependencyScannerWorker_dispose_v0(
173+
CXDependencyScannerWorker);
174+
175+
/**
176+
* A callback that is called whenever a module is discovered when in
177+
* \c CXDependencyMode_Full mode.
178+
*
179+
* \param Context the context that was passed to
180+
* \c clang_experimental_DependencyScannerWorker_getFileDependencies_v0.
181+
* \param MDS the list of discovered modules. Must be freed by calling
182+
* \c clang_experimental_ModuleDependencySet_dispose.
183+
*/
184+
typedef void CXModuleDiscoveredCallback(void *Context,
185+
CXModuleDependencySet *MDS);
186+
187+
/**
188+
* Returns the list of file dependencies for a particular compiler invocation.
189+
*
190+
* \param argc the number of compiler invocation arguments (including argv[0]).
191+
* \param argv the compiler invocation arguments (including argv[0]).
192+
* the invocation may be a -cc1 clang invocation or a driver
193+
* invocation.
194+
* \param WorkingDirectory the directory in which the invocation runs.
195+
* \param MDC a callback that is called whenever a new module is discovered.
196+
* This may receive the same module on different workers. This should
197+
* be NULL if
198+
* \c clang_experimental_DependencyScannerService_create_v0 was
199+
* called with \c CXDependencyMode_Flat. This callback will be called
200+
* on the same thread that called this function.
201+
* \param Context the context that will be passed to \c MDC each time it is
202+
* called.
203+
* \param [out] error the error string to pass back to client (if any).
204+
*
205+
* \returns A pointer to a CXFileDependencies on success, NULL otherwise. The
206+
* CXFileDependencies must be freed by calling
207+
* \c clang_experimental_FileDependencies_dispose.
208+
*/
209+
CINDEX_LINKAGE CXFileDependencies *
210+
clang_experimental_DependencyScannerWorker_getFileDependencies_v0(
211+
CXDependencyScannerWorker Worker, int argc, const char *const *argv,
212+
const char *WorkingDirectory, CXModuleDiscoveredCallback *MDC,
213+
void *Context, CXString *error);
214+
215+
/**
216+
* @}
217+
*/
218+
219+
#ifdef __cplusplus
220+
}
221+
#endif
222+
223+
#endif // LLVM_CLANG_C_DEPENDENCIES_H

clang/include/clang-c/Driver.h

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*==-- clang-c/Driver.h - A C Interface for the Clang Driver ------*- C -*-===*\
2+
|* *|
3+
|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
4+
|* Exceptions. *|
5+
|* See https://llvm.org/LICENSE.txt for license information. *|
6+
|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
7+
|* *|
8+
|*===----------------------------------------------------------------------===*|
9+
|* *|
10+
|* This header provides a C API for extracting information from the clang *|
11+
|* driver. *|
12+
|* *|
13+
\*===----------------------------------------------------------------------===*/
14+
15+
16+
#ifndef CLANG_CLANG_C_DRIVER
17+
#define CLANG_CLANG_C_DRIVER
18+
19+
#include "clang-c/Index.h"
20+
#include "clang-c/Platform.h"
21+
22+
#ifdef __cplusplus
23+
extern "C" {
24+
#endif
25+
26+
/**
27+
* Contains the command line arguments for an external action. Same format as
28+
* provided to main.
29+
*/
30+
typedef struct {
31+
/* Number of arguments in ArgV */
32+
int ArgC;
33+
/* Null terminated array of pointers to null terminated argument strings */
34+
const char **ArgV;
35+
} CXExternalAction;
36+
37+
/**
38+
* Contains the list of external actions clang would invoke.
39+
*/
40+
typedef struct {
41+
int Count;
42+
CXExternalAction **Actions;
43+
} CXExternalActionList;
44+
45+
/**
46+
* Get the external actions that the clang driver will invoke for the given
47+
* command line.
48+
*
49+
* \param ArgC number of arguments in \p ArgV.
50+
* \param ArgV array of null terminated arguments. Doesn't need to be null
51+
* terminated.
52+
* \param Environment must be null.
53+
* \param WorkingDirectory a null terminated path to the working directory to
54+
* use for this invocation. `nullptr` to use the current working directory of
55+
* the process.
56+
* \param OutDiags will be set to a \c CXDiagnosticSet if there's an error.
57+
* Must be freed by calling \c clang_disposeDiagnosticSet .
58+
* \returns A pointer to a \c CXExternalActionList on success, null on failure.
59+
* The returned \c CXExternalActionList must be freed by calling
60+
* \c clang_Driver_ExternalActionList_dispose .
61+
*/
62+
CINDEX_LINKAGE CXExternalActionList *
63+
clang_Driver_getExternalActionsForCommand_v0(int ArgC, const char **ArgV,
64+
const char **Environment,
65+
const char *WorkingDirectory,
66+
CXDiagnosticSet *OutDiags);
67+
68+
/**
69+
* Deallocate a \c CXExternalActionList
70+
*/
71+
CINDEX_LINKAGE void
72+
clang_Driver_ExternalActionList_dispose(CXExternalActionList *EAL);
73+
74+
#ifdef __cplusplus
75+
}
76+
#endif
77+
78+
#endif // CLANG_CLANG_C_DRIVER

clang/include/clang/Basic/Module.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ class Module {
109109
/// The name of the umbrella entry, as written in the module map.
110110
std::string UmbrellaAsWritten;
111111

112+
// The path to the umbrella entry relative to the root module's \c Directory.
113+
std::string UmbrellaRelativeToRootModuleDirectory;
114+
112115
/// The module through which entities defined in this module will
113116
/// eventually be exposed, for use in "private" modules.
114117
std::string ExportAsModule;
@@ -156,6 +159,7 @@ class Module {
156159
/// file.
157160
struct Header {
158161
std::string NameAsWritten;
162+
std::string PathRelativeToRootModuleDirectory;
159163
const FileEntry *Entry;
160164

161165
explicit operator bool() { return Entry; }
@@ -165,6 +169,7 @@ class Module {
165169
/// file.
166170
struct DirectoryName {
167171
std::string NameAsWritten;
172+
std::string PathRelativeToRootModuleDirectory;
168173
const DirectoryEntry *Entry;
169174

170175
explicit operator bool() { return Entry; }
@@ -491,7 +496,8 @@ class Module {
491496
/// module.
492497
Header getUmbrellaHeader() const {
493498
if (auto *E = Umbrella.dyn_cast<const FileEntry *>())
494-
return Header{UmbrellaAsWritten, E};
499+
return Header{UmbrellaAsWritten, UmbrellaRelativeToRootModuleDirectory,
500+
E};
495501
return Header{};
496502
}
497503

clang/include/clang/Driver/CC1Options.td

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,18 @@
1212

1313
let Flags = [CC1Option, NoDriverOption] in {
1414

15+
//===----------------------------------------------------------------------===//
16+
// Option Options
17+
//===----------------------------------------------------------------------===//
18+
19+
def remove_preceeding_explicit_module_build_incompatible_options :
20+
Flag<["-"], "remove-preceeding-explicit-module-build-incompatible-options">,
21+
HelpText<"Removes any arguments before this one that would be incompatible "
22+
"with explicitly building a module. This includes things like -o "
23+
"and input files. This option can be used to append arguments to "
24+
"convert a build of a translation unit with implicit modules "
25+
"into an explicit build of a specific module.">;
26+
1527
//===----------------------------------------------------------------------===//
1628
// Target Options
1729
//===----------------------------------------------------------------------===//

clang/include/clang/Driver/Options.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1548,7 +1548,7 @@ def fno_merge_all_constants : Flag<["-"], "fno-merge-all-constants">, Group<f_Gr
15481548
def fno_modules : Flag <["-"], "fno-modules">, Group<f_Group>,
15491549
Flags<[DriverOption]>;
15501550
def fno_implicit_module_maps : Flag <["-"], "fno-implicit-module-maps">, Group<f_Group>,
1551-
Flags<[DriverOption]>;
1551+
Flags<[DriverOption, CC1Option]>;
15521552
def fno_module_maps : Flag <["-"], "fno-module-maps">, Alias<fno_implicit_module_maps>;
15531553
def fno_modules_decluse : Flag <["-"], "fno-modules-decluse">, Group<f_Group>,
15541554
Flags<[DriverOption]>;

clang/include/clang/Lex/ModuleMap.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -653,12 +653,14 @@ class ModuleMap {
653653
/// Sets the umbrella header of the given module to the given
654654
/// header.
655655
void setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
656-
Twine NameAsWritten);
656+
Twine NameAsWritten,
657+
Twine PathRelativeToRootModuleDirectory);
657658

658659
/// Sets the umbrella directory of the given module to the given
659660
/// directory.
660661
void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
661-
Twine NameAsWritten);
662+
Twine NameAsWritten,
663+
Twine PathRelativeToRootModuleDirectory);
662664

663665
/// Adds this header to the given module.
664666
/// \param Role The role of the header wrt the module.

clang/include/clang/Tooling/DependencyScanning/DependencyScanningWorker.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,15 @@ class DependencyScanningWorker {
6363
const CompilationDatabase &CDB,
6464
DependencyConsumer &Consumer);
6565

66+
llvm::Error
67+
computeDependenciesForClangInvocation(StringRef WorkingDirectory,
68+
ArrayRef<std::string> Arguments,
69+
DependencyConsumer &Consumer);
70+
71+
ScanningOutputFormat getFormat() const { return Format; }
72+
73+
llvm::StringSet<> AlreadySeen;
74+
6675
private:
6776
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
6877
std::shared_ptr<PCHContainerOperations> PCHContainerOps;

0 commit comments

Comments
 (0)