[clang-tools-extra] [clang-doc] Add --asset option to clang-doc (PR #94717)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jun 6 22:40:53 PDT 2024
https://github.com/PeterChou1 updated https://github.com/llvm/llvm-project/pull/94717
>From eeb334620df72c395a5ad27f44a864a6a0c194a5 Mon Sep 17 00:00:00 2001
From: PeterChou1 <peter.chou at mail.utoronto.ca>
Date: Thu, 6 Jun 2024 23:18:12 -0400
Subject: [PATCH 1/2] [clang][clang-doc] add asset path
---
.../clang-doc/tool/ClangDocMain.cpp | 73 ++++++++++++++-----
1 file changed, 55 insertions(+), 18 deletions(-)
diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
index 21b581fa6df2e..df53c46b4a76e 100644
--- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
+++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
@@ -81,6 +81,12 @@ static llvm::cl::list<std::string> UserStylesheets(
llvm::cl::desc("CSS stylesheets to extend the default styles."),
llvm::cl::cat(ClangDocCategory));
+static llvm::cl::opt<std::string>
+ UserAssetPath("asset",
+ llvm::cl::desc("User supplied asset path for html output to "
+ "override the default css and js files"),
+ llvm::cl::cat(ClangDocCategory));
+
static llvm::cl::opt<std::string> SourceRoot("source-root", llvm::cl::desc(R"(
Directory where processed files are stored.
Links to definition locations will only be
@@ -131,12 +137,54 @@ std::string GetExecutablePath(const char *Argv0, void *MainAddr) {
return llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
}
+void GetAssetFiles(clang::doc::ClangDocContext CDCtx) {
+ std::error_code Code;
+ for (auto DirIt = llvm::sys::fs::directory_iterator(
+ std::string(UserAssetPath), Code),
+ dir_end = llvm::sys::fs::directory_iterator();
+ !Code && DirIt != dir_end; DirIt.increment(Code)) {
+ llvm::SmallString<128> filePath = llvm::SmallString<128>(DirIt->path());
+ if (llvm::sys::fs::is_regular_file(filePath)) {
+ if (filePath.ends_with(".css")) {
+ CDCtx.UserStylesheets.push_back(std::string(filePath));
+ } else if (filePath.ends_with(".js")) {
+ CDCtx.FilesToCopy.push_back(std::string(filePath));
+ }
+ }
+ }
+}
+
+void GetDefaultAssetFiles(const char *Argv0,
+ clang::doc::ClangDocContext CDCtx) {
+ void *MainAddr = (void *)(intptr_t)GetExecutablePath;
+ std::string ClangDocPath = GetExecutablePath(Argv0, MainAddr);
+ llvm::SmallString<128> NativeClangDocPath;
+ llvm::sys::path::native(ClangDocPath, NativeClangDocPath);
+
+ llvm::SmallString<128> AssetsPath;
+ AssetsPath = llvm::sys::path::parent_path(NativeClangDocPath);
+ llvm::sys::path::append(AssetsPath, "..", "share", "clang");
+ llvm::SmallString<128> DefaultStylesheet;
+ llvm::sys::path::native(AssetsPath, DefaultStylesheet);
+ llvm::sys::path::append(DefaultStylesheet,
+ "clang-doc-default-stylesheet.css");
+ llvm::SmallString<128> IndexJS;
+ llvm::sys::path::native(AssetsPath, IndexJS);
+ llvm::sys::path::append(IndexJS, "index.js");
+ CDCtx.UserStylesheets.insert(CDCtx.UserStylesheets.begin(),
+ std::string(DefaultStylesheet));
+ CDCtx.FilesToCopy.emplace_back(IndexJS.str());
+
+ llvm::outs() << "No default asset path found using default asset path: "
+ << AssetsPath << "\n";
+}
+
int main(int argc, const char **argv) {
llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
std::error_code OK;
const char *Overview =
- R"(Generates documentation from source code and comments.
+ R"(Generates documentation from source code and comments.
Example usage for files without flags (default):
@@ -182,23 +230,12 @@ Example usage for a project using a compile commands database:
{"index.js", "index_json.js"}};
if (Format == "html") {
- void *MainAddr = (void *)(intptr_t)GetExecutablePath;
- std::string ClangDocPath = GetExecutablePath(argv[0], MainAddr);
- llvm::SmallString<128> NativeClangDocPath;
- llvm::sys::path::native(ClangDocPath, NativeClangDocPath);
- llvm::SmallString<128> AssetsPath;
- AssetsPath = llvm::sys::path::parent_path(NativeClangDocPath);
- llvm::sys::path::append(AssetsPath, "..", "share", "clang");
- llvm::SmallString<128> DefaultStylesheet;
- llvm::sys::path::native(AssetsPath, DefaultStylesheet);
- llvm::sys::path::append(DefaultStylesheet,
- "clang-doc-default-stylesheet.css");
- llvm::SmallString<128> IndexJS;
- llvm::sys::path::native(AssetsPath, IndexJS);
- llvm::sys::path::append(IndexJS, "index.js");
- CDCtx.UserStylesheets.insert(CDCtx.UserStylesheets.begin(),
- std::string(DefaultStylesheet));
- CDCtx.FilesToCopy.emplace_back(IndexJS.str());
+ if (!UserAssetPath.empty() &&
+ llvm::sys::fs::is_directory(std::string(UserAssetPath))) {
+ GetAssetFiles(CDCtx);
+ } else {
+ GetDefaultAssetFiles(argv[0], CDCtx);
+ }
}
// Mapping phase
>From d535cb7b7c92a22931b276a8c9fe97a2f04c2258 Mon Sep 17 00:00:00 2001
From: PeterChou1 <peter.chou at mail.utoronto.ca>
Date: Fri, 7 Jun 2024 01:40:29 -0400
Subject: [PATCH 2/2] [clang][clang-doc] fixes bug caused by not passing by
reference
---
.../clang-doc/tool/ClangDocMain.cpp | 455 +++++++++---------
1 file changed, 228 insertions(+), 227 deletions(-)
diff --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
index df53c46b4a76e..ab6f6198aae32 100644
--- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
+++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
@@ -54,38 +54,38 @@ static llvm::cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
static llvm::cl::OptionCategory ClangDocCategory("clang-doc options");
static llvm::cl::opt<std::string>
- ProjectName("project-name", llvm::cl::desc("Name of project."),
- llvm::cl::cat(ClangDocCategory));
+ ProjectName("project-name", llvm::cl::desc("Name of project."),
+ llvm::cl::cat(ClangDocCategory));
static llvm::cl::opt<bool> IgnoreMappingFailures(
- "ignore-map-errors",
- llvm::cl::desc("Continue if files are not mapped correctly."),
- llvm::cl::init(true), llvm::cl::cat(ClangDocCategory));
+ "ignore-map-errors",
+ llvm::cl::desc("Continue if files are not mapped correctly."),
+ llvm::cl::init(true), llvm::cl::cat(ClangDocCategory));
static llvm::cl::opt<std::string>
- OutDirectory("output",
- llvm::cl::desc("Directory for outputting generated files."),
- llvm::cl::init("docs"), llvm::cl::cat(ClangDocCategory));
+ OutDirectory("output",
+ llvm::cl::desc("Directory for outputting generated files."),
+ llvm::cl::init("docs"), llvm::cl::cat(ClangDocCategory));
static llvm::cl::opt<bool>
- PublicOnly("public", llvm::cl::desc("Document only public declarations."),
- llvm::cl::init(false), llvm::cl::cat(ClangDocCategory));
+ PublicOnly("public", llvm::cl::desc("Document only public declarations."),
+ llvm::cl::init(false), llvm::cl::cat(ClangDocCategory));
static llvm::cl::opt<bool> DoxygenOnly(
- "doxygen",
- llvm::cl::desc("Use only doxygen-style comments to generate docs."),
- llvm::cl::init(false), llvm::cl::cat(ClangDocCategory));
+ "doxygen",
+ llvm::cl::desc("Use only doxygen-style comments to generate docs."),
+ llvm::cl::init(false), llvm::cl::cat(ClangDocCategory));
static llvm::cl::list<std::string> UserStylesheets(
- "stylesheets", llvm::cl::CommaSeparated,
- llvm::cl::desc("CSS stylesheets to extend the default styles."),
- llvm::cl::cat(ClangDocCategory));
+ "stylesheets", llvm::cl::CommaSeparated,
+ llvm::cl::desc("CSS stylesheets to extend the default styles."),
+ llvm::cl::cat(ClangDocCategory));
static llvm::cl::opt<std::string>
- UserAssetPath("asset",
- llvm::cl::desc("User supplied asset path for html output to "
- "override the default css and js files"),
- llvm::cl::cat(ClangDocCategory));
+ UserAssetPath("asset",
+ llvm::cl::desc("User supplied asset path for html output to "
+ "override the default css and js files"),
+ llvm::cl::cat(ClangDocCategory));
static llvm::cl::opt<std::string> SourceRoot("source-root", llvm::cl::desc(R"(
Directory where processed files are stored.
@@ -94,38 +94,38 @@ generated if the file is in this dir.)"),
llvm::cl::cat(ClangDocCategory));
static llvm::cl::opt<std::string>
- RepositoryUrl("repository", llvm::cl::desc(R"(
+ RepositoryUrl("repository", llvm::cl::desc(R"(
URL of repository that hosts code.
Used for links to definition locations.)"),
- llvm::cl::cat(ClangDocCategory));
+ llvm::cl::cat(ClangDocCategory));
enum OutputFormatTy {
- md,
- yaml,
- html,
+ md,
+ yaml,
+ html,
};
static llvm::cl::opt<OutputFormatTy>
- FormatEnum("format", llvm::cl::desc("Format for outputted docs."),
- llvm::cl::values(clEnumValN(OutputFormatTy::yaml, "yaml",
- "Documentation in YAML format."),
- clEnumValN(OutputFormatTy::md, "md",
- "Documentation in MD format."),
- clEnumValN(OutputFormatTy::html, "html",
- "Documentation in HTML format.")),
- llvm::cl::init(OutputFormatTy::yaml),
- llvm::cl::cat(ClangDocCategory));
+ FormatEnum("format", llvm::cl::desc("Format for outputted docs."),
+ llvm::cl::values(clEnumValN(OutputFormatTy::yaml, "yaml",
+ "Documentation in YAML format."),
+ clEnumValN(OutputFormatTy::md, "md",
+ "Documentation in MD format."),
+ clEnumValN(OutputFormatTy::html, "html",
+ "Documentation in HTML format.")),
+ llvm::cl::init(OutputFormatTy::yaml),
+ llvm::cl::cat(ClangDocCategory));
std::string getFormatString() {
- switch (FormatEnum) {
- case OutputFormatTy::yaml:
- return "yaml";
- case OutputFormatTy::md:
- return "md";
- case OutputFormatTy::html:
- return "html";
- }
- llvm_unreachable("Unknown OutputFormatTy");
+ switch (FormatEnum) {
+ case OutputFormatTy::yaml:
+ return "yaml";
+ case OutputFormatTy::md:
+ return "md";
+ case OutputFormatTy::html:
+ return "html";
+ }
+ llvm_unreachable("Unknown OutputFormatTy");
}
// This function isn't referenced outside its translation unit, but it
@@ -134,57 +134,58 @@ std::string getFormatString() {
// address of main, and some platforms can't implement GetMainExecutable
// without being given the address of a function in the main executable).
std::string GetExecutablePath(const char *Argv0, void *MainAddr) {
- return llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
+ return llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
}
-void GetAssetFiles(clang::doc::ClangDocContext CDCtx) {
- std::error_code Code;
- for (auto DirIt = llvm::sys::fs::directory_iterator(
- std::string(UserAssetPath), Code),
- dir_end = llvm::sys::fs::directory_iterator();
- !Code && DirIt != dir_end; DirIt.increment(Code)) {
- llvm::SmallString<128> filePath = llvm::SmallString<128>(DirIt->path());
- if (llvm::sys::fs::is_regular_file(filePath)) {
- if (filePath.ends_with(".css")) {
- CDCtx.UserStylesheets.push_back(std::string(filePath));
- } else if (filePath.ends_with(".js")) {
- CDCtx.FilesToCopy.push_back(std::string(filePath));
- }
+void GetAssetFiles(clang::doc::ClangDocContext &CDCtx) {
+ std::error_code Code;
+ for (auto DirIt = llvm::sys::fs::directory_iterator(
+ std::string(UserAssetPath), Code),
+ dir_end = llvm::sys::fs::directory_iterator();
+ !Code && DirIt != dir_end; DirIt.increment(Code)) {
+ llvm::SmallString<128> filePath = llvm::SmallString<128>(DirIt->path());
+ if (llvm::sys::fs::is_regular_file(filePath)) {
+ if (filePath.ends_with(".css")) {
+ CDCtx.UserStylesheets.insert(CDCtx.UserStylesheets.begin(),
+ std::string(filePath));
+ } else if (filePath.ends_with(".js")) {
+ CDCtx.FilesToCopy.emplace_back(filePath.str());
+ }
+ }
}
- }
}
void GetDefaultAssetFiles(const char *Argv0,
- clang::doc::ClangDocContext CDCtx) {
- void *MainAddr = (void *)(intptr_t)GetExecutablePath;
- std::string ClangDocPath = GetExecutablePath(Argv0, MainAddr);
- llvm::SmallString<128> NativeClangDocPath;
- llvm::sys::path::native(ClangDocPath, NativeClangDocPath);
-
- llvm::SmallString<128> AssetsPath;
- AssetsPath = llvm::sys::path::parent_path(NativeClangDocPath);
- llvm::sys::path::append(AssetsPath, "..", "share", "clang");
- llvm::SmallString<128> DefaultStylesheet;
- llvm::sys::path::native(AssetsPath, DefaultStylesheet);
- llvm::sys::path::append(DefaultStylesheet,
- "clang-doc-default-stylesheet.css");
- llvm::SmallString<128> IndexJS;
- llvm::sys::path::native(AssetsPath, IndexJS);
- llvm::sys::path::append(IndexJS, "index.js");
- CDCtx.UserStylesheets.insert(CDCtx.UserStylesheets.begin(),
- std::string(DefaultStylesheet));
- CDCtx.FilesToCopy.emplace_back(IndexJS.str());
-
- llvm::outs() << "No default asset path found using default asset path: "
- << AssetsPath << "\n";
+ clang::doc::ClangDocContext &CDCtx) {
+ void *MainAddr = (void *)(intptr_t)GetExecutablePath;
+ std::string ClangDocPath = GetExecutablePath(Argv0, MainAddr);
+ llvm::SmallString<128> NativeClangDocPath;
+ llvm::sys::path::native(ClangDocPath, NativeClangDocPath);
+
+ llvm::SmallString<128> AssetsPath;
+ AssetsPath = llvm::sys::path::parent_path(NativeClangDocPath);
+ llvm::sys::path::append(AssetsPath, "..", "share", "clang");
+ llvm::SmallString<128> DefaultStylesheet;
+ llvm::sys::path::native(AssetsPath, DefaultStylesheet);
+ llvm::sys::path::append(DefaultStylesheet,
+ "clang-doc-default-stylesheet.css");
+ llvm::SmallString<128> IndexJS;
+ llvm::sys::path::native(AssetsPath, IndexJS);
+ llvm::sys::path::append(IndexJS, "index.js");
+ CDCtx.UserStylesheets.insert(CDCtx.UserStylesheets.begin(),
+ std::string(DefaultStylesheet));
+ CDCtx.FilesToCopy.emplace_back(IndexJS.str());
+
+ llvm::outs() << "No default asset path found using default asset path: "
+ << AssetsPath << "\n";
}
int main(int argc, const char **argv) {
- llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
- std::error_code OK;
+ llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
+ std::error_code OK;
- const char *Overview =
- R"(Generates documentation from source code and comments.
+ const char *Overview =
+ R"(Generates documentation from source code and comments.
Example usage for files without flags (default):
@@ -195,150 +196,150 @@ Example usage for a project using a compile commands database:
$ clang-doc --executor=all-TUs compile_commands.json
)";
- auto Executor = clang::tooling::createExecutorFromCommandLineArgs(
- argc, argv, ClangDocCategory, Overview);
-
- if (!Executor) {
- llvm::errs() << toString(Executor.takeError()) << "\n";
- return 1;
- }
-
- // Fail early if an invalid format was provided.
- std::string Format = getFormatString();
- llvm::outs() << "Emiting docs in " << Format << " format.\n";
- auto G = doc::findGeneratorByName(Format);
- if (!G) {
- llvm::errs() << toString(G.takeError()) << "\n";
- return 1;
- }
-
- ArgumentsAdjuster ArgAdjuster;
- if (!DoxygenOnly)
- ArgAdjuster = combineAdjusters(
- getInsertArgumentAdjuster("-fparse-all-comments",
- tooling::ArgumentInsertPosition::END),
- ArgAdjuster);
-
- clang::doc::ClangDocContext CDCtx = {
- Executor->get()->getExecutionContext(),
- ProjectName,
- PublicOnly,
- OutDirectory,
- SourceRoot,
- RepositoryUrl,
- {UserStylesheets.begin(), UserStylesheets.end()},
- {"index.js", "index_json.js"}};
-
- if (Format == "html") {
- if (!UserAssetPath.empty() &&
- llvm::sys::fs::is_directory(std::string(UserAssetPath))) {
- GetAssetFiles(CDCtx);
- } else {
- GetDefaultAssetFiles(argv[0], CDCtx);
+ auto Executor = clang::tooling::createExecutorFromCommandLineArgs(
+ argc, argv, ClangDocCategory, Overview);
+
+ if (!Executor) {
+ llvm::errs() << toString(Executor.takeError()) << "\n";
+ return 1;
+ }
+
+ // Fail early if an invalid format was provided.
+ std::string Format = getFormatString();
+ llvm::outs() << "Emiting docs in " << Format << " format.\n";
+ auto G = doc::findGeneratorByName(Format);
+ if (!G) {
+ llvm::errs() << toString(G.takeError()) << "\n";
+ return 1;
}
- }
-
- // Mapping phase
- llvm::outs() << "Mapping decls...\n";
- auto Err =
- Executor->get()->execute(doc::newMapperActionFactory(CDCtx), ArgAdjuster);
- if (Err) {
- if (IgnoreMappingFailures)
- llvm::errs() << "Error mapping decls in files. Clang-doc will ignore "
- "these files and continue:\n"
- << toString(std::move(Err)) << "\n";
- else {
- llvm::errs() << toString(std::move(Err)) << "\n";
- return 1;
+
+ ArgumentsAdjuster ArgAdjuster;
+ if (!DoxygenOnly)
+ ArgAdjuster = combineAdjusters(
+ getInsertArgumentAdjuster("-fparse-all-comments",
+ tooling::ArgumentInsertPosition::END),
+ ArgAdjuster);
+
+ clang::doc::ClangDocContext CDCtx = {
+ Executor->get()->getExecutionContext(),
+ ProjectName,
+ PublicOnly,
+ OutDirectory,
+ SourceRoot,
+ RepositoryUrl,
+ {UserStylesheets.begin(), UserStylesheets.end()},
+ {"index.js", "index_json.js"}};
+
+ if (Format == "html") {
+ if (!UserAssetPath.empty() &&
+ llvm::sys::fs::is_directory(std::string(UserAssetPath))) {
+ GetAssetFiles(CDCtx);
+ } else {
+ GetDefaultAssetFiles(argv[0], CDCtx);
+ }
}
- }
-
- // Collect values into output by key.
- // In ToolResults, the Key is the hashed USR and the value is the
- // bitcode-encoded representation of the Info object.
- llvm::outs() << "Collecting infos...\n";
- llvm::StringMap<std::vector<StringRef>> USRToBitcode;
- Executor->get()->getToolResults()->forEachResult(
- [&](StringRef Key, StringRef Value) {
- auto R = USRToBitcode.try_emplace(Key, std::vector<StringRef>());
- R.first->second.emplace_back(Value);
- });
-
- // Collects all Infos according to their unique USR value. This map is added
- // to from the thread pool below and is protected by the USRToInfoMutex.
- llvm::sys::Mutex USRToInfoMutex;
- llvm::StringMap<std::unique_ptr<doc::Info>> USRToInfo;
-
- // First reducing phase (reduce all decls into one info per decl).
- llvm::outs() << "Reducing " << USRToBitcode.size() << " infos...\n";
- std::atomic<bool> Error;
- Error = false;
- llvm::sys::Mutex IndexMutex;
- // ExecutorConcurrency is a flag exposed by AllTUsExecution.h
- llvm::DefaultThreadPool Pool(llvm::hardware_concurrency(ExecutorConcurrency));
- for (auto &Group : USRToBitcode) {
- Pool.async([&]() {
- std::vector<std::unique_ptr<doc::Info>> Infos;
-
- for (auto &Bitcode : Group.getValue()) {
- llvm::BitstreamCursor Stream(Bitcode);
- doc::ClangDocBitcodeReader Reader(Stream);
- auto ReadInfos = Reader.readBitcode();
- if (!ReadInfos) {
- llvm::errs() << toString(ReadInfos.takeError()) << "\n";
- Error = true;
- return;
+
+ // Mapping phase
+ llvm::outs() << "Mapping decls...\n";
+ auto Err =
+ Executor->get()->execute(doc::newMapperActionFactory(CDCtx), ArgAdjuster);
+ if (Err) {
+ if (IgnoreMappingFailures)
+ llvm::errs() << "Error mapping decls in files. Clang-doc will ignore "
+ "these files and continue:\n"
+ << toString(std::move(Err)) << "\n";
+ else {
+ llvm::errs() << toString(std::move(Err)) << "\n";
+ return 1;
}
- std::move(ReadInfos->begin(), ReadInfos->end(),
- std::back_inserter(Infos));
- }
-
- auto Reduced = doc::mergeInfos(Infos);
- if (!Reduced) {
- llvm::errs() << llvm::toString(Reduced.takeError());
- return;
- }
-
- // Add a reference to this Info in the Index
- {
- std::lock_guard<llvm::sys::Mutex> Guard(IndexMutex);
- clang::doc::Generator::addInfoToIndex(CDCtx.Idx, Reduced.get().get());
- }
-
- // Save in the result map (needs a lock due to threaded access).
- {
- std::lock_guard<llvm::sys::Mutex> Guard(USRToInfoMutex);
- USRToInfo[Group.getKey()] = std::move(Reduced.get());
- }
- });
- }
-
- Pool.wait();
-
- if (Error)
- return 1;
-
- // Ensure the root output directory exists.
- if (std::error_code Err = llvm::sys::fs::create_directories(OutDirectory);
- Err != std::error_code()) {
- llvm::errs() << "Failed to create directory '" << OutDirectory << "'\n";
- return 1;
- }
-
- // Run the generator.
- llvm::outs() << "Generating docs...\n";
- if (auto Err =
- G->get()->generateDocs(OutDirectory, std::move(USRToInfo), CDCtx)) {
- llvm::errs() << toString(std::move(Err)) << "\n";
- return 1;
- }
-
- llvm::outs() << "Generating assets for docs...\n";
- Err = G->get()->createResources(CDCtx);
- if (Err) {
- llvm::errs() << toString(std::move(Err)) << "\n";
- return 1;
- }
-
- return 0;
+ }
+
+ // Collect values into output by key.
+ // In ToolResults, the Key is the hashed USR and the value is the
+ // bitcode-encoded representation of the Info object.
+ llvm::outs() << "Collecting infos...\n";
+ llvm::StringMap<std::vector<StringRef>> USRToBitcode;
+ Executor->get()->getToolResults()->forEachResult(
+ [&](StringRef Key, StringRef Value) {
+ auto R = USRToBitcode.try_emplace(Key, std::vector<StringRef>());
+ R.first->second.emplace_back(Value);
+ });
+
+ // Collects all Infos according to their unique USR value. This map is added
+ // to from the thread pool below and is protected by the USRToInfoMutex.
+ llvm::sys::Mutex USRToInfoMutex;
+ llvm::StringMap<std::unique_ptr<doc::Info>> USRToInfo;
+
+ // First reducing phase (reduce all decls into one info per decl).
+ llvm::outs() << "Reducing " << USRToBitcode.size() << " infos...\n";
+ std::atomic<bool> Error;
+ Error = false;
+ llvm::sys::Mutex IndexMutex;
+ // ExecutorConcurrency is a flag exposed by AllTUsExecution.h
+ llvm::DefaultThreadPool Pool(llvm::hardware_concurrency(ExecutorConcurrency));
+ for (auto &Group : USRToBitcode) {
+ Pool.async([&]() {
+ std::vector<std::unique_ptr<doc::Info>> Infos;
+
+ for (auto &Bitcode : Group.getValue()) {
+ llvm::BitstreamCursor Stream(Bitcode);
+ doc::ClangDocBitcodeReader Reader(Stream);
+ auto ReadInfos = Reader.readBitcode();
+ if (!ReadInfos) {
+ llvm::errs() << toString(ReadInfos.takeError()) << "\n";
+ Error = true;
+ return;
+ }
+ std::move(ReadInfos->begin(), ReadInfos->end(),
+ std::back_inserter(Infos));
+ }
+
+ auto Reduced = doc::mergeInfos(Infos);
+ if (!Reduced) {
+ llvm::errs() << llvm::toString(Reduced.takeError());
+ return;
+ }
+
+ // Add a reference to this Info in the Index
+ {
+ std::lock_guard<llvm::sys::Mutex> Guard(IndexMutex);
+ clang::doc::Generator::addInfoToIndex(CDCtx.Idx, Reduced.get().get());
+ }
+
+ // Save in the result map (needs a lock due to threaded access).
+ {
+ std::lock_guard<llvm::sys::Mutex> Guard(USRToInfoMutex);
+ USRToInfo[Group.getKey()] = std::move(Reduced.get());
+ }
+ });
+ }
+
+ Pool.wait();
+
+ if (Error)
+ return 1;
+
+ // Ensure the root output directory exists.
+ if (std::error_code Err = llvm::sys::fs::create_directories(OutDirectory);
+ Err != std::error_code()) {
+ llvm::errs() << "Failed to create directory '" << OutDirectory << "'\n";
+ return 1;
+ }
+
+ // Run the generator.
+ llvm::outs() << "Generating docs...\n";
+ if (auto Err =
+ G->get()->generateDocs(OutDirectory, std::move(USRToInfo), CDCtx)) {
+ llvm::errs() << toString(std::move(Err)) << "\n";
+ return 1;
+ }
+
+ llvm::outs() << "Generating assets for docs...\n";
+ Err = G->get()->createResources(CDCtx);
+ if (Err) {
+ llvm::errs() << toString(std::move(Err)) << "\n";
+ return 1;
+ }
+
+ return 0;
}
More information about the cfe-commits
mailing list