Skip to content

Commit f53685e

Browse files
committed
refactor: modular cmake functions
1 parent 59681e8 commit f53685e

File tree

3 files changed

+110
-73
lines changed

3 files changed

+110
-73
lines changed

src/lib/Lib/CMakeExecution.cpp

Lines changed: 49 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -195,49 +195,34 @@ parseCmakeArgs(std::string const& cmakeArgsStr) {
195195
return args;
196196
}
197197

198-
} // anonymous namespace
199-
200-
Expected<std::string>
201-
executeCmakeExportCompileCommands(llvm::StringRef projectPath, llvm::StringRef cmakeArgs)
202-
{
203-
MRDOCS_CHECK(llvm::sys::fs::exists(projectPath), "Project path does not exist");
204-
MRDOCS_TRY(auto const cmakePath, getCmakePath());
205-
206-
llvm::SmallString<128> tempDir;
207-
MRDOCS_CHECK(!llvm::sys::fs::createUniqueDirectory("compile_commands", tempDir), "Failed to create temporary directory");
208-
209-
llvm::SmallString<128> errorPath;
210-
MRDOCS_CHECK(!llvm::sys::fs::createTemporaryFile("cmake-error", "txt", errorPath),
211-
"Failed to create temporary file");
212-
213-
std::optional<llvm::StringRef> const redirects[] = {llvm::StringRef(), llvm::StringRef(), errorPath.str()};
214-
std::vector<llvm::StringRef> args = {cmakePath, "-S", projectPath, "-B", tempDir.str(), "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"};
215-
216-
auto const additionalArgs = parseCmakeArgs(cmakeArgs.str());
217-
198+
Expected<void>
199+
pushCMakeArgs(
200+
std::string const& cmakePath,
201+
std::vector<llvm::StringRef> &args,
202+
std::vector<std::string> const& additionalArgs) {
218203
bool visualStudioFound = false;
219-
for (size_t i = 0; i < additionalArgs.size(); ++i)
204+
for (size_t i = 0; i < additionalArgs.size(); ++i)
220205
{
221206
auto const& arg = additionalArgs[i];
222207
if (arg.starts_with("-G"))
223208
{
224-
if (arg.size() == 2)
209+
if (arg.size() == 2)
225210
{
226-
if (i + 1 < additionalArgs.size())
211+
if (i + 1 < additionalArgs.size())
227212
{
228213
auto const& generatorName = additionalArgs[i + 1];
229-
if (generatorName.starts_with("Visual Studio"))
214+
if (generatorName.starts_with("Visual Studio"))
230215
{
231-
args.push_back("-GNinja");
216+
args.emplace_back("-GNinja");
232217
visualStudioFound = true;
233218
++i;
234219
continue;
235220
}
236221
}
237222
} else {
238-
if (arg.find("Visual Studio", 2) != std::string::npos)
223+
if (arg.find("Visual Studio", 2) != std::string::npos)
239224
{
240-
args.push_back("-GNinja");
225+
args.emplace_back("-GNinja");
241226
visualStudioFound = true;
242227
continue;
243228
}
@@ -246,39 +231,63 @@ executeCmakeExportCompileCommands(llvm::StringRef projectPath, llvm::StringRef c
246231

247232
if (arg.starts_with("-D"))
248233
{
249-
if (arg.size() == 2)
234+
if (arg.size() == 2)
250235
{
251-
if (i + 1 < additionalArgs.size())
236+
if (i + 1 < additionalArgs.size())
252237
{
253238
auto const& optionName = additionalArgs[i + 1];
254-
if (optionName.starts_with("CMAKE_EXPORT_COMPILE_COMMANDS"))
239+
if (optionName.starts_with("CMAKE_EXPORT_COMPILE_COMMANDS"))
255240
{
256241
++i;
257242
continue;
258243
}
259244
}
260245
} else {
261-
if (arg.find("CMAKE_EXPORT_COMPILE_COMMANDS", 2) != std::string::npos)
246+
if (arg.find("CMAKE_EXPORT_COMPILE_COMMANDS", 2) != std::string::npos)
262247
{
263248
continue;
264249
}
265250
}
266-
}
267-
args.push_back(arg);
251+
}
252+
args.emplace_back(arg);
268253
}
269-
270-
if ( ! visualStudioFound)
254+
255+
if (!visualStudioFound)
271256
{
272-
MRDOCS_TRY(auto const cmakeDefaultGeneratorIsVisualStudio, cmakeDefaultGeneratorIsVisualStudio(cmakePath));
273-
if (cmakeDefaultGeneratorIsVisualStudio)
257+
MRDOCS_TRY(
258+
bool const cmakeDefaultGeneratorIsVisualStudio,
259+
cmakeDefaultGeneratorIsVisualStudio(cmakePath));
260+
if (cmakeDefaultGeneratorIsVisualStudio)
274261
{
275-
args.push_back("-GNinja");
262+
args.emplace_back("-GNinja");
276263
}
277264
}
265+
return {};
266+
}
267+
268+
} // anonymous namespace
269+
270+
Expected<std::string>
271+
executeCmakeExportCompileCommands(llvm::StringRef projectPath, llvm::StringRef cmakeArgs)
272+
{
273+
MRDOCS_CHECK(llvm::sys::fs::exists(projectPath), "Project path does not exist");
274+
MRDOCS_TRY(auto const cmakePath, getCmakePath());
275+
276+
llvm::SmallString<128> tempDir;
277+
MRDOCS_CHECK(!llvm::sys::fs::createUniqueDirectory("compile_commands", tempDir), "Failed to create temporary directory");
278+
279+
ScopedTempFile const errorPath("cmake-error", "txt");
280+
MRDOCS_CHECK(errorPath, "Failed to create temporary file");
281+
282+
std::optional<llvm::StringRef> const redirects[] = {llvm::StringRef(), llvm::StringRef(), errorPath.path()};
283+
std::vector<llvm::StringRef> args = {cmakePath, "-S", projectPath, "-B", tempDir.str(), "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"};
284+
285+
auto const additionalArgs = parseCmakeArgs(cmakeArgs.str());
286+
MRDOCS_TRY(pushCMakeArgs(cmakePath, args, additionalArgs));
278287

279288
int const result = llvm::sys::ExecuteAndWait(cmakePath, args, std::nullopt, redirects);
280289
if (result != 0) {
281-
auto bufferOrError = llvm::MemoryBuffer::getFile(errorPath);
290+
auto bufferOrError = llvm::MemoryBuffer::getFile(errorPath.path());
282291
MRDOCS_CHECK(bufferOrError, "CMake execution failed (no error output available)");
283292
return Unexpected(Error("CMake execution failed: \n" + bufferOrError.get()->getBuffer().str()));
284293
}
@@ -289,5 +298,6 @@ executeCmakeExportCompileCommands(llvm::StringRef projectPath, llvm::StringRef c
289298
return compileCommandsPath.str().str();
290299
}
291300

301+
292302
} // mrdocs
293303
} // clang

src/tool/CompilerInfo.cpp

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ namespace mrdocs {
2121
std::optional<std::string>
2222
getCompilerVerboseOutput(llvm::StringRef compilerPath)
2323
{
24-
if ( ! llvm::sys::fs::exists(compilerPath)) {
24+
if ( ! llvm::sys::fs::exists(compilerPath))
25+
{
2526
return std::nullopt;
2627
}
2728

@@ -43,7 +44,7 @@ getCompilerVerboseOutput(llvm::StringRef compilerPath)
4344

4445
auto bufferOrError = llvm::MemoryBuffer::getFile(outputPath);
4546
llvm::sys::fs::remove(outputPath);
46-
if ( ! bufferOrError)
47+
if (!bufferOrError)
4748
{
4849
return std::nullopt;
4950
}
@@ -86,20 +87,25 @@ getCompilersDefaultIncludeDir(clang::tooling::CompilationDatabase const& compDb)
8687
std::unordered_map<std::string, std::vector<std::string>> res;
8788
auto const allCommands = compDb.getAllCompileCommands();
8889

89-
for (auto const& cmd : allCommands) {
90-
if ( ! cmd.CommandLine.empty()) {
90+
for (auto const& cmd : allCommands)
91+
{
92+
if (!cmd.CommandLine.empty())
93+
{
9194
auto const& compilerPath = cmd.CommandLine[0];
92-
if (res.contains(compilerPath)) {
95+
if (res.contains(compilerPath))
96+
{
9397
continue;
9498
}
9599

100+
std::vector<std::string> includePaths;
96101
auto const compilerOutput = getCompilerVerboseOutput(compilerPath);
97-
if ( ! compilerOutput) {
98-
report::warn("Warning: could not get compiler info for \"{}\"", compilerPath);
102+
if (!compilerOutput)
103+
{
104+
res.emplace(compilerPath, includePaths);
99105
continue;
100106
}
101-
std::vector<std::string> includePaths = parseIncludePaths(*compilerOutput);
102-
res.emplace(compilerPath, std::move(includePaths));
107+
includePaths = parseIncludePaths(*compilerOutput);
108+
res.emplace(compilerPath, std::move(includePaths));
103109
}
104110
}
105111

src/tool/GenerateAction.cpp

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -51,21 +51,31 @@ generateCompileCommandsFile(llvm::StringRef projectPath, llvm::StringRef cmakeAr
5151
fs::file_status fileStatus;
5252
MRDOCS_CHECK(!fs::status(projectPath, fileStatus), "Failed to get file status");
5353

54+
// --------------------------------------------------------------
55+
// Input path is a project directory
56+
// --------------------------------------------------------------
5457
if (fs::is_directory(fileStatus))
5558
{
5659
return executeCmakeExportCompileCommands(projectPath, cmakeArgs);
5760
}
58-
61+
62+
// --------------------------------------------------------------
63+
// Input path is a CMakeLists.txt
64+
// --------------------------------------------------------------
5965
auto const fileName = files::getFileName(projectPath);
66+
if (fileName == "CMakeLists.txt")
67+
{
68+
return executeCmakeExportCompileCommands(files::getParentDir(projectPath), cmakeArgs);
69+
}
70+
71+
// --------------------------------------------------------------
72+
// Input path is a compile_commands.json
73+
// --------------------------------------------------------------
6074
if (fileName == "compile_commands.json")
6175
{
6276
return projectPath.str();
6377
}
64-
65-
if (fileName == "CMakeLists.txt")
66-
{
67-
return executeCmakeExportCompileCommands(files::getParentDir(projectPath), cmakeArgs);
68-
}
78+
6979
return projectPath.str();
7080
}
7181

@@ -94,12 +104,14 @@ DoGenerateAction()
94104
ThreadPool threadPool(toolArgs.concurrency);
95105
{
96106
MRDOCS_CHECK(toolArgs.configPath, "The config path argument is missing");
97-
MRDOCS_TRY(auto configFile, loadConfigFile(
98-
toolArgs.configPath,
99-
toolArgs.addonsDir,
100-
extraYaml,
101-
nullptr,
102-
threadPool));
107+
MRDOCS_TRY(
108+
std::shared_ptr<ConfigImpl const> configFile,
109+
loadConfigFile(
110+
toolArgs.configPath,
111+
toolArgs.addonsDir,
112+
extraYaml,
113+
nullptr,
114+
threadPool));
103115
config = std::move(configFile);
104116
}
105117

@@ -117,33 +129,39 @@ DoGenerateAction()
117129

118130
// --------------------------------------------------------------
119131
//
120-
// Load the compilation database file
132+
// Generate compile_commands.json
121133
//
122134
// --------------------------------------------------------------
123-
124135
MRDOCS_CHECK(toolArgs.inputPaths, "The compilation database path argument is missing");
125136
MRDOCS_CHECK(toolArgs.inputPaths.size() == 1,
126137
formatError(
127138
"got {} input paths where 1 was expected",
128139
toolArgs.inputPaths.size()));
129140

130-
131141
std::string_view cmakeArgs = config->object().exists("cmake") ?
132142
config->object().get("cmake").getString() : "";
133-
auto const inputPath = generateCompileCommandsFile(toolArgs.inputPaths.front(), cmakeArgs);
134-
if ( ! inputPath)
143+
Expected<std::string> const compileCommandsPathExp =
144+
generateCompileCommandsFile(toolArgs.inputPaths.front(), cmakeArgs);
145+
if (!compileCommandsPathExp)
135146
{
136-
report::error("Failed to generate compile_commands.json file: {}", inputPath.error());
137-
return {};
147+
report::error(
148+
"Failed to generate compile_commands.json file: {}",
149+
compileCommandsPathExp.error());
150+
return Unexpected(compileCommandsPathExp.error());
138151
}
139152

140-
auto compilationsPath = files::normalizePath(*inputPath);
141-
MRDOCS_TRY(compilationsPath, files::makeAbsolute(compilationsPath));
153+
// --------------------------------------------------------------
154+
//
155+
// Load the compilation database file
156+
//
157+
// --------------------------------------------------------------
158+
std::string compileCommandsPath = files::normalizePath(*compileCommandsPathExp);
159+
MRDOCS_TRY(compileCommandsPath, files::makeAbsolute(compileCommandsPath));
142160
std::string errorMessage;
143161
MRDOCS_TRY_MSG(
144162
auto& compileCommands,
145163
tooling::JSONCompilationDatabase::loadFromFile(
146-
compilationsPath,
164+
compileCommandsPath,
147165
errorMessage,
148166
tooling::JSONCommandLineSyntax::AutoDetect),
149167
std::move(errorMessage));
@@ -152,9 +170,12 @@ DoGenerateAction()
152170
auto const defaultIncludePaths = getCompilersDefaultIncludeDir(compileCommands);
153171

154172
// Custom compilation database that converts relative paths to absolute
155-
auto compileCommandsDir = files::getParentDir(compilationsPath);
173+
auto compileCommandsDir = files::getParentDir(compileCommandsPath);
174+
MRDOCS_ASSERT(files::isDirsy(compileCommandsDir));
156175
MrDocsCompilationDatabase compilationDatabase(
157-
compileCommandsDir, compileCommands, config, defaultIncludePaths);
176+
compileCommandsDir,
177+
compileCommands, config,
178+
defaultIncludePaths);
158179

159180
// Normalize outputPath path
160181
MRDOCS_CHECK(toolArgs.outputPath, "The output path argument is missing");
@@ -172,7 +193,7 @@ DoGenerateAction()
172193
CorpusImpl::build(
173194
report::Level::info, config, compilationDatabase));
174195

175-
if(corpus->empty())
196+
if (corpus->empty())
176197
{
177198
report::warn("Corpus is empty, not generating docs");
178199
return {};

0 commit comments

Comments
 (0)