summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Bornemann <joerg.bornemann@qt.io>2020-09-28 21:26:04 +0200
committerJoerg Bornemann <joerg.bornemann@qt.io>2020-10-01 11:33:53 +0200
commit092f23cdacb5dd0ad2307cd4c18546054f7f5245 (patch)
tree213e26438c11222bdbe2402c548e4e0b789229d1
parent30c12c44baa77806bd9d45980ed82bf45e7c2396 (diff)
lupdate: Revisit how to specify the compilation database
The compilation database's file path was passed to clang's CommonOptionsParser with the "-p" argument. This, however, specifies a directory, not the path to the compilation database itself. There doesn't seem to be a way to directly specify the file path of the compilation database itself. The whole API revolves around directories. This is also what I observe in other clang-based tools, see for example the -compile-commands-dir option of clangd. Remove CommonOptionsParser, and directly use CompilationDatabase to explicitly control how to search for the compilation database, and actually do what the help output claims. Reflect in the help output that lupdate expects a directory path, not a file path. Properly forward the error message from CompilationDatabase, and bail out with an error exit code. Change-Id: I935da6078d020431d0f69509da69a52089e23f8a Reviewed-by: Karsten Heimrich <karsten.heimrich@qt.io>
-rw-r--r--src/linguist/lupdate/cpp_clang.cpp43
-rw-r--r--src/linguist/lupdate/cpp_clang.h3
-rw-r--r--src/linguist/lupdate/main.cpp22
-rw-r--r--src/linguist/shared/translator.h2
4 files changed, 41 insertions, 29 deletions
diff --git a/src/linguist/lupdate/cpp_clang.cpp b/src/linguist/lupdate/cpp_clang.cpp
index d0744d14c..a618fa5da 100644
--- a/src/linguist/lupdate/cpp_clang.cpp
+++ b/src/linguist/lupdate/cpp_clang.cpp
@@ -34,17 +34,14 @@
#include <thread>
-#include <clang/Tooling/CommonOptionsParser.h>
-#include <llvm/Option/Option.h>
+#include <clang/Tooling/CompilationDatabase.h>
+
+using clang::tooling::CompilationDatabase;
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcClang, "qt.lupdate.clang");
-// This is a way to add options related to the customized clang tool
-// Needed as one of the arguments to create the OptionParser.
-static llvm::cl::OptionCategory MyToolCategory("my-tool options");
-
// Makes sure all the comments will be parsed and part of the AST
// Clang will run with the flag -fparse-all-comments
clang::tooling::ArgumentsAdjuster getClangArgumentAdjuster()
@@ -105,7 +102,8 @@ bool ClangCppParser::containsTranslationInformation(llvm::StringRef ba)
return false;
}
-void ClangCppParser::loadCPP(Translator &translator, const QStringList &files, ConversionData &cd)
+void ClangCppParser::loadCPP(Translator &translator, const QStringList &files, ConversionData &cd,
+ bool *fail)
{
// pre-process the files by a simple text search if there is any occurrence
// of things we are interested in
@@ -133,11 +131,24 @@ void ClangCppParser::loadCPP(Translator &translator, const QStringList &files, C
sourcesPP.insert(sourcesPP.cend(), sources.cbegin(), sources.cend());
sourcesAst.insert(sourcesAst.cend(), sources.cbegin(), sources.cend());
- int argc = 4;
- // NEED 2 empty one to start!!! otherwise: LLVM::ERROR
- const QByteArray jsonPath = cd.m_compileCommandsPath.toLocal8Bit();
- const char *argv[4] = { "", "", "-p", jsonPath.constData() };
- clang::tooling::CommonOptionsParser optionsParser(argc, argv, MyToolCategory);
+ std::string errorMessage;
+ std::unique_ptr<CompilationDatabase> db;
+ if (cd.m_compilationDatabaseDir.isEmpty()) {
+ db = CompilationDatabase::autoDetectFromDirectory(".", errorMessage);
+ if (!db && !files.isEmpty()) {
+ db = CompilationDatabase::autoDetectFromSource(files.first().toStdString(),
+ errorMessage);
+ }
+ } else {
+ db = CompilationDatabase::autoDetectFromDirectory(cd.m_compilationDatabaseDir.toStdString(),
+ errorMessage);
+ }
+
+ if (!db) {
+ *fail = true;
+ cd.appendError(QString::fromStdString(errorMessage));
+ return;
+ }
TranslationStores ast, qdecl, qnoop;
Stores stores(ast, qdecl, qnoop);
@@ -148,10 +159,10 @@ void ClangCppParser::loadCPP(Translator &translator, const QStringList &files, C
size_t idealProducerCount = std::min(ppSources.size(), size_t(std::thread::hardware_concurrency()));
for (size_t i = 0; i < idealProducerCount; ++i) {
- std::thread producer([&ppSources, &optionsParser, &ppStore]() {
+ std::thread producer([&ppSources, &db, &ppStore]() {
std::string file;
while (ppSources.next(&file)) {
- clang::tooling::ClangTool tool(optionsParser.getCompilations(), file);
+ clang::tooling::ClangTool tool(*db, file);
tool.appendArgumentsAdjuster(getClangArgumentAdjuster());
tool.run(new LupdatePreprocessorActionFactory(&ppStore));
}
@@ -165,10 +176,10 @@ void ClangCppParser::loadCPP(Translator &translator, const QStringList &files, C
ReadSynchronizedRef<std::string> astSources(sourcesAst);
idealProducerCount = std::min(astSources.size(), size_t(std::thread::hardware_concurrency()));
for (size_t i = 0; i < idealProducerCount; ++i) {
- std::thread producer([&astSources, &optionsParser, &stores]() {
+ std::thread producer([&astSources, &db, &stores]() {
std::string file;
while (astSources.next(&file)) {
- clang::tooling::ClangTool tool(optionsParser.getCompilations(), file);
+ clang::tooling::ClangTool tool(*db, file);
tool.appendArgumentsAdjuster(getClangArgumentAdjuster());
tool.run(new LupdateToolActionFactory(&stores));
}
diff --git a/src/linguist/lupdate/cpp_clang.h b/src/linguist/lupdate/cpp_clang.h
index b33a27a93..ca5a5acc8 100644
--- a/src/linguist/lupdate/cpp_clang.h
+++ b/src/linguist/lupdate/cpp_clang.h
@@ -246,7 +246,8 @@ namespace LupdatePrivate
namespace ClangCppParser
{
- void loadCPP(Translator &translator, const QStringList &filenames, ConversionData &cd);
+ void loadCPP(Translator &translator, const QStringList &filenames, ConversionData &cd,
+ bool *fail);
void fillTranslator(const TranslationRelatedStore &store, Translator &tor, ConversionData &cd);
TranslatorMessage translatorMessage(const TranslationRelatedStore &store,
diff --git a/src/linguist/lupdate/main.cpp b/src/linguist/lupdate/main.cpp
index 9dcba2b3c..77e5c29bc 100644
--- a/src/linguist/lupdate/main.cpp
+++ b/src/linguist/lupdate/main.cpp
@@ -50,7 +50,7 @@
#include <iostream>
bool useClangToParseCpp = false;
-QString commandLineCompileCommands; // for the path to the json file passed as a command line argument.
+QString commandLineCompilationDatabaseDir; // for the path to the json file passed as a command line argument.
// Has priority over what is in the .pro file and passed to the project.
// Can't have an array of QStaticStringData<N> for different N, so
@@ -280,14 +280,14 @@ static void printUsage()
" Specify the output file(s). This will override the TRANSLATIONS.\n"
" -version\n"
" Display the version of lupdate and exit.\n"
- " -clang-parser [compilation-database]\n"
+ " -clang-parser [compilation-database-dir]\n"
" Use clang to parse cpp files. Otherwise a custom parser is used.\n"
" This option needs a clang compilation database (compile_commands.json)\n"
" for the files that needs to be parsed.\n"
- " The path to this file can be specified on the command line, \n"
- " directly after the -clang-parser option, or in the .pro file\n"
+ " The path to the directory containing this file can be specified on the \n"
+ " command line, directly after the -clang-parser option, or in the .pro file\n"
" by setting the variable LUPDATE_COMPILE_COMMANDS_PATH.\n"
- " A compilation database specified on the command line takes precedence.\n"
+ " A directory specified on the command line takes precedence.\n"
" If no path is given, the compilation database will be searched\n"
" in all parent paths of the first input file.\n"
" @lst-file\n"
@@ -530,7 +530,7 @@ static void processSources(Translator &fetchedTor,
if (useClangToParseCpp) {
#if QT_CONFIG(clangcpp)
- ClangCppParser::loadCPP(fetchedTor, sourceFilesCpp, cd);
+ ClangCppParser::loadCPP(fetchedTor, sourceFilesCpp, cd, fail);
#else
*fail = true;
printErr(LU::tr("lupdate error: lupdate was built without clang support."));
@@ -604,10 +604,10 @@ private:
cd.m_includePath = prj.includePaths;
cd.m_excludes = prj.excluded;
cd.m_sourceIsUtf16 = options & SourceIsUtf16;
- if (commandLineCompileCommands.isEmpty())
- cd.m_compileCommandsPath = prj.compileCommands;
+ if (commandLineCompilationDatabaseDir.isEmpty())
+ cd.m_compilationDatabaseDir = prj.compileCommands;
else
- cd.m_compileCommandsPath = commandLineCompileCommands;
+ cd.m_compilationDatabaseDir = commandLineCompilationDatabaseDir;
QStringList tsFiles;
if (prj.translations) {
@@ -869,7 +869,7 @@ int main(int argc, char **argv)
// the option after -clang-parser is optional
if ((i + 1) != argc && !args[i + 1].startsWith(QLatin1String("-"))) {
i++;
- commandLineCompileCommands = args[i];
+ commandLineCompilationDatabaseDir = args[i];
}
continue;
}
@@ -1036,7 +1036,7 @@ int main(int argc, char **argv)
cd.m_projectRoots = projectRoots;
cd.m_includePath = includePath;
cd.m_allCSources = allCSources;
- cd.m_compileCommandsPath = commandLineCompileCommands;
+ cd.m_compilationDatabaseDir = commandLineCompilationDatabaseDir;
for (const QString &resource : qAsConst(resourceFiles))
sourceFiles << getResources(resource);
processSources(fetchedTor, sourceFiles, cd, &fail);
diff --git a/src/linguist/shared/translator.h b/src/linguist/shared/translator.h
index 80bb201e1..8b58e4986 100644
--- a/src/linguist/shared/translator.h
+++ b/src/linguist/shared/translator.h
@@ -80,7 +80,7 @@ public:
QString m_unTrPrefix; // QM specific
QString m_sourceFileName;
QString m_targetFileName;
- QString m_compileCommandsPath;
+ QString m_compilationDatabaseDir;
QStringList m_excludes;
QDir m_sourceDir;
QDir m_targetDir; // FIXME: TS specific