logic: only use precompiled headers for compilation database commands that specify the "-include-pch" flag (issue #719)

This commit is contained in:
mlangkabel
2019-08-13 17:31:33 +02:00
parent 084bc3dc43
commit e89dc0ab0a
8 changed files with 121 additions and 9 deletions
+12 -7
View File
@@ -101,7 +101,8 @@ std::shared_ptr<IndexerCommandProvider> SourceGroupCxxCdb::getIndexerCommandProv
std::vector<std::wstring> compilerFlags = getBaseCompilerFlags();
utility::append(compilerFlags, m_settings->getCompilerFlags());
utility::append(compilerFlags, utility::getIncludePchFlags(m_settings.get()));
const std::vector<std::wstring> includePchFlags = utility::getIncludePchFlags(m_settings.get());
const std::set<FilePath> indexedHeaderPaths = utility::toSet(m_settings->getIndexedHeaderPathsExpandedAndAbsolute());
const std::set<FilePathFilter> excludeFilters = utility::toSet(m_settings->getExcludeFiltersExpandedAndAbsolute());
@@ -122,13 +123,17 @@ std::shared_ptr<IndexerCommandProvider> SourceGroupCxxCdb::getIndexerCommandProv
if (filesToIndex.find(sourcePath) != filesToIndex.end() &&
sourceFilePaths.find(sourcePath) != sourceFilePaths.end())
{
std::vector<std::wstring> mergedCompilerFlags;
mergedCompilerFlags.reserve(compilerFlags.size() + command.CommandLine.size());
for (const std::string& arg : command.CommandLine)
std::vector<std::wstring> cdbFlags = utility::convert<std::string, std::wstring>(
command.CommandLine,
[](const std::string& s) { return utility::decodeFromUtf8(s); }
);
utility::removeIncludePchFlag(cdbFlags);
if (command.CommandLine.size() != cdbFlags.size())
{
mergedCompilerFlags.emplace_back(utility::decodeFromUtf8(arg));
utility::append(cdbFlags, includePchFlags);
}
mergedCompilerFlags.insert(mergedCompilerFlags.end(), compilerFlags.begin(), compilerFlags.end());
provider->addCommand(std::make_shared<IndexerCommandCxx>(
sourcePath,
@@ -136,7 +141,7 @@ std::shared_ptr<IndexerCommandProvider> SourceGroupCxxCdb::getIndexerCommandProv
excludeFilters,
std::set<FilePathFilter>(),
FilePath(utility::decodeFromUtf8(command.Directory)),
mergedCompilerFlags
utility::concat(cdbFlags, compilerFlags)
));
}
}
@@ -1,5 +1,7 @@
#include "utilitySourceGroupCxx.h"
#include <clang/Tooling/JSONCompilationDatabase.h>
#include "CanonicalFilePathCache.h"
#include "CxxCompilationDatabaseSingle.h"
#include "CxxDiagnosticConsumer.h"
@@ -48,6 +50,7 @@ namespace utility
const FilePath pchOutputFilePath =
pchDependenciesDirectoryPath.getConcatenated(pchInputFilePath.fileName()).replaceExtension(L"pch");
utility::removeIncludePchFlag(compilerFlags);
compilerFlags.push_back(pchInputFilePath.wstr());
compilerFlags.push_back(L"-emit-pch");
compilerFlags.push_back(L"-o");
@@ -102,6 +105,48 @@ namespace utility
);
}
bool containsIncludePchFlags(std::shared_ptr<clang::tooling::JSONCompilationDatabase> cdb)
{
for (const clang::tooling::CompileCommand& command : cdb->getAllCompileCommands())
{
if (command.CommandLine.size() != getWithRemoveIncludePchFlag(utility::convert<std::string, std::wstring>(
command.CommandLine,
[](const std::string& s) {return utility::decodeFromUtf8(s); }
)).size())
{
return true;
}
}
return false;
}
std::vector<std::wstring> getWithRemoveIncludePchFlag(const std::vector<std::wstring>& args)
{
std::vector<std::wstring> ret = args;
removeIncludePchFlag(ret);
return ret;
}
void removeIncludePchFlag(std::vector<std::wstring>& args)
{
const std::wstring includePchPrefix = L"-include-pch";
for (size_t i = 0; i < args.size(); i++)
{
const std::wstring arg = utility::trim(args[i]);
if (utility::isPrefix<std::wstring>(includePchPrefix, arg))
{
if (i + 1 < args.size() &&
!utility::isPrefix<std::wstring>(L"-", utility::trim(args[i + 1])) &&
arg == includePchPrefix)
{
args.erase(args.begin() + i + 1);
}
args.erase(args.begin() + i);
i--;
}
}
}
std::vector<std::wstring> getIncludePchFlags(const SourceGroupSettingsCxx* settings)
{
const SourceGroupSettingsWithCxxPchOptions* pchSettings =
@@ -5,6 +5,12 @@
#include <string>
#include <vector>
namespace clang {
namespace tooling {
class JSONCompilationDatabase;
}
}
class DialogView;
class SourceGroupSettingsCxx;
class StorageProvider;
@@ -15,6 +21,9 @@ namespace utility
std::shared_ptr<Task> createBuildPchTask(
const SourceGroupSettingsCxx* settings, std::vector<std::wstring> compilerFlags,
std::shared_ptr<StorageProvider> storageProvider, std::shared_ptr<DialogView> dialogView);
bool containsIncludePchFlags(std::shared_ptr<clang::tooling::JSONCompilationDatabase> cdb);
std::vector<std::wstring> getWithRemoveIncludePchFlag(const std::vector<std::wstring>& args);
void removeIncludePchFlag(std::vector<std::wstring>& args);
std::vector<std::wstring> getIncludePchFlags(const SourceGroupSettingsCxx* settings);
}
@@ -1,8 +1,13 @@
#include "QtProjectWizardContentPathCxxPch.h"
#include <QMessageBox>
#include "IndexerCommandCxx.h"
#include "SourceGroupSettingsCxxCdb.h"
#include "SourceGroupSettingsWithCxxPchOptions.h"
#include "utility.h"
#include "utilityFile.h"
#include "utilitySourceGroupCxx.h"
QtProjectWizardContentPathCxxPch::QtProjectWizardContentPathCxxPch(
std::shared_ptr<SourceGroupSettings> settings,
@@ -40,6 +45,44 @@ void QtProjectWizardContentPathCxxPch::save()
m_settingsCxxPch->setPchInputFilePathFilePath(FilePath(m_picker->getText().toStdWString()));
}
bool QtProjectWizardContentPathCxxPch::check()
{
if (std::shared_ptr<SourceGroupSettingsCxxCdb> cdbSettings = std::dynamic_pointer_cast<SourceGroupSettingsCxxCdb>(m_settings))
{
const FilePath cdbPath = cdbSettings->getCompilationDatabasePathExpandedAndAbsolute();
std::shared_ptr<clang::tooling::JSONCompilationDatabase> cdb = IndexerCommandCxx::loadCDB(cdbPath);
if (!cdb)
{
QMessageBox msgBox;
msgBox.setText("Unable to open and read the provided compilation database file.");
msgBox.exec();
return false;
}
if (utility::containsIncludePchFlags(cdb))
{
if (m_settingsCxxPch->getPchInputFilePath().empty())
{
QMessageBox msgBox;
msgBox.setText("The provided compilation database file uses precompiled headers. Please specify a Precompiled Header input file.");
msgBox.exec();
return false;
}
}
else
{
if (!m_settingsCxxPch->getPchInputFilePath().empty())
{
QMessageBox msgBox;
msgBox.setText("The provided compilation database file does not use precompiled headers. Please do not specify a Precompiled Header input file.");
msgBox.exec();
return false;
}
}
}
return true;
}
std::shared_ptr<SourceGroupSettings> QtProjectWizardContentPathCxxPch::getSourceGroupSettings()
{
return m_settings;
@@ -22,6 +22,7 @@ public:
void load() override;
void save() override;
bool check() override;
private:
std::shared_ptr<SourceGroupSettings> getSourceGroupSettings() override;
@@ -13,6 +13,12 @@
* Validate "Header Files & Directories to Index" contains "src" entry
* Add "**/Foo.h" to "Excluded Files & Directories"
* Click "Next"
* Pick any file at "Precompiled Header File"
* Click "Next"
* Validate dialog appears that asks NOT to specify PCH input file
* Click "OK"
* Clear "Precompiled Header File"
* Click "Next"
* Click "Create"
* Validate "All files" is the only option selectable
* Click "Start"
+1 -1
View File
@@ -21,7 +21,7 @@ cp -a $SRC_PATH/. $WORKING_COPY_PATH
echo "[" >> $CDB_PATH
echo " {" >> $CDB_PATH
echo " \"directory\": \"${WORKING_COPY_PATH}\"," >> $CDB_PATH
echo " \"command\": \"clang-tool -fms-extensions -fms-compatibility -fms-compatibility-version=19 -isystem \\\"${WORKING_COPY_SRC_PATH}/include\\\" -DCDB_FLAG -D _DEBUG -D _MT -D _DLL -D WIN32 -D _WINDOWS -D BUILD_TYPE=\\\"\\\" -D QT_WIDGETS_LIB -D QT_GUI_LIB -D QT_CORE_LIB -D QT_NETWORK_LIB -D QT_WINEXTRAS_LIB -D QT_SVG_LIB -D CMAKE_INTDIR=\\\"Debug\\\" -D _MBCS -std=c++14 \\\"${WORKING_COPY_SRC_PATH}/main.cpp\\\"\"," >> $CDB_PATH
echo " \"command\": \"clang-tool -fms-extensions -fms-compatibility -fms-compatibility-version=19 -isystem \\\"${WORKING_COPY_SRC_PATH}/include\\\" -DCDB_FLAG -D _DEBUG -D _MT -D _DLL -D WIN32 -D _WINDOWS -D BUILD_TYPE=\\\"\\\" -D QT_WIDGETS_LIB -D QT_GUI_LIB -D QT_CORE_LIB -D QT_NETWORK_LIB -D QT_WINEXTRAS_LIB -D QT_SVG_LIB -D CMAKE_INTDIR=\\\"Debug\\\" -D _MBCS -std=c++14 -include-pch some/file/path \\\"${WORKING_COPY_SRC_PATH}/main.cpp\\\"\"," >> $CDB_PATH
echo " \"file\": \"${WORKING_COPY_SRC_PATH}/main.cpp\"" >> $CDB_PATH
echo " }" >> $CDB_PATH
echo "]" >> $CDB_PATH
@@ -14,8 +14,11 @@
* Add "**/Foo.h" to "Excluded Files & Directories"
* Click "Next"
* Click "Next"
* Add "-DCOMPILER_FLAG" to "Additional Compiler Flags"
* Validate dialog appears that asks to specify PCH input file
* Click "OK"
* Add "./src/pch.h" to "Precompiled Header File"
* Click "Next"
* Add "-DCOMPILER_FLAG" to "Additional Compiler Flags"
* Add "-DPCH_FLAG" to "Precompiled Header Flags"
* Click "Create"
* Validate "All files" is the only option selectable