CMakeProjectManager: Use CMAKE_HOME_DIRECTORY as source directory

The CMakeCache.txt file has CMAKE_HOME_DIRECTORY pointing to the
project source directory used to configure the project.

When importing a cmake build the CMAKE_HOME_DIRECTORY from
CMakeCache.txt might not point to the same CMakeLists.txt that was
opened as a project.

qt-cmake-standalone-test from Qt6 uses a CMake template project which
does a add_subdirectory with the test source directory, which will not
work if opened standalone.

Normally this is a user error though, so ask the user if this was
intended, before actually importing the build.

Task-number: QTBUG-88776
Change-Id: Ifdd5e1d1cb8a1ef9955d22493eba3a1a55dc689f
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
Reviewed-by: Cristian Adam <cristian.adam@qt.io>
This commit is contained in:
Cristian Adam
2020-12-02 19:16:40 +01:00
parent ac378fbe2a
commit 707a3cfaf3
15 changed files with 104 additions and 22 deletions

View File

@@ -27,6 +27,7 @@
#include "cmakebuildconfiguration.h"
#include "cmakekitinformation.h"
#include "cmakeprojectconstants.h"
#include "cmakeprojectplugin.h"
#include "cmakespecificsettings.h"
#include "cmaketoolmanager.h"
@@ -67,7 +68,9 @@ BuildDirParameters::BuildDirParameters(CMakeBuildConfiguration *bc)
projectName = p->displayName();
sourceDirectory = p->projectDirectory();
sourceDirectory = bc->sourceDirectory();
if (sourceDirectory.isEmpty())
sourceDirectory = p->projectDirectory();
buildDirectory = bc->buildDirectory();
environment = bc->environment();

View File

@@ -129,6 +129,8 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(Target *target, Utils::Id id)
auto initialCMakeArgumentsAspect = addAspect<InitialCMakeArgumentsAspect>();
initialCMakeArgumentsAspect->setMacroExpanderProvider([this]{ return macroExpander(); });
addAspect<SourceDirectoryAspect>();
appendInitialBuildStep(Constants::CMAKE_BUILD_STEP_ID);
appendInitialCleanStep(Constants::CMAKE_BUILD_STEP_ID);
@@ -190,6 +192,11 @@ CMakeBuildConfiguration::CMakeBuildConfiguration(Target *target, Utils::Id id)
info.buildType));
}
if (info.extraInfo.isValid()) {
setSourceDirectory(FilePath::fromVariant(
info.extraInfo.value<QVariantMap>().value(Constants::CMAKE_HOME_DIR)));
}
setInitialCMakeArguments(initialArgs);
});
@@ -486,6 +493,16 @@ void CMakeBuildConfiguration::runCMakeWithExtraArguments()
m_buildSystem->runCMakeWithExtraArguments();
}
void CMakeBuildConfiguration::setSourceDirectory(const FilePath &path)
{
aspect<SourceDirectoryAspect>()->setValue(path.toString());
}
Utils::FilePath CMakeBuildConfiguration::sourceDirectory() const
{
return Utils::FilePath::fromString(aspect<SourceDirectoryAspect>()->value());
}
// ----------------------------------------------------------------------
// - InitialCMakeParametersAspect:
// ----------------------------------------------------------------------
@@ -497,5 +514,14 @@ InitialCMakeArgumentsAspect::InitialCMakeArgumentsAspect()
setDisplayStyle(TextEditDisplay);
}
// -----------------------------------------------------------------------------
// SourceDirectoryAspect:
// -----------------------------------------------------------------------------
SourceDirectoryAspect::SourceDirectoryAspect()
{
// Will not be displayed, only persisted
setSettingsKey("CMake.Source.Directory");
}
} // namespace Internal
} // namespace CMakeProjectManager

View File

@@ -67,6 +67,9 @@ public:
void runCMakeWithExtraArguments();
void setSourceDirectory(const Utils::FilePath& path);
Utils::FilePath sourceDirectory() const;
signals:
void errorOccurred(const QString &message);
void warningOccurred(const QString &message);
@@ -133,5 +136,13 @@ public:
InitialCMakeArgumentsAspect();
};
class SourceDirectoryAspect final : public Utils::StringAspect
{
Q_OBJECT
public:
SourceDirectoryAspect();
};
} // namespace Internal
} // namespace CMakeProjectManager

View File

@@ -37,6 +37,7 @@ const char RESCAN_PROJECT[] = "CMakeProject.RescanProject";
const char RUN_CMAKE_CONTEXT_MENU[] = "CMakeProject.RunCMakeContextMenu";
const char BUILD_FILE_CONTEXT_MENU[] = "CMakeProject.BuildFileContextMenu";
const char BUILD_FILE[] = "CMakeProject.BuildFile";
const char CMAKE_HOME_DIR[] = "CMakeProject.HomeDirectory";
// Project
const char CMAKE_PROJECT_ID[] = "CMakeProjectManager.CMakeProject";

View File

@@ -28,8 +28,11 @@
#include "cmakebuildconfiguration.h"
#include "cmakebuildsystem.h"
#include "cmakekitinformation.h"
#include "cmakeprojectconstants.h"
#include "cmaketoolmanager.h"
#include <coreplugin/messagemanager.h>
#include <projectexplorer/buildinfo.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorerconstants.h>
@@ -58,6 +61,7 @@ struct DirectoryData
// Project Stuff:
QByteArray cmakeBuildType;
FilePath buildDirectory;
FilePath cmakeHomeDirectory;
// Kit Stuff
FilePath cmakeBinary;
@@ -266,7 +270,8 @@ static QVector<ToolChainDescription> extractToolChainsFromCache(const CMakeConfi
return result;
}
QList<void *> CMakeProjectImporter::examineDirectory(const FilePath &importPath) const
QList<void *> CMakeProjectImporter::examineDirectory(const FilePath &importPath,
QString *warningMessage) const
{
qCInfo(cmInputLog) << "Examining directory:" << importPath.toUserOutput();
const FilePath cacheFile = importPath.pathAppended("CMakeCache.txt");
@@ -282,18 +287,22 @@ QList<void *> CMakeProjectImporter::examineDirectory(const FilePath &importPath)
qCDebug(cmInputLog) << "Failed to read configuration from" << cacheFile << errorMessage;
return { };
}
const auto homeDir = FilePath::fromUserInput(
QString::fromUtf8(
CMakeConfigItem::valueOf("CMAKE_HOME_DIRECTORY", config)))
.canonicalPath();
auto data = std::make_unique<DirectoryData>();
data->cmakeHomeDirectory = FilePath::fromUserInput(
QString::fromUtf8(
CMakeConfigItem::valueOf("CMAKE_HOME_DIRECTORY", config)))
.canonicalPath();
const FilePath canonicalProjectDirectory = projectDirectory().canonicalPath();
if (homeDir != canonicalProjectDirectory) {
qCDebug(cmInputLog) << "Wrong source directory:" << homeDir.toUserOutput()
<< "expected:" << canonicalProjectDirectory.toUserOutput();
return { };
if (data->cmakeHomeDirectory != canonicalProjectDirectory) {
*warningMessage = tr("Unexpected source directory \"%1\", expected \"%2\". "
"This can be correct in some situations, for example when "
"importing a standalone Qt test, but usually this is an error. "
"Import the build anyway?")
.arg(data->cmakeHomeDirectory.toUserOutput(),
canonicalProjectDirectory.toUserOutput());
}
auto data = std::make_unique<DirectoryData>();
data->buildDirectory = importPath;
data->cmakeBuildType = CMakeConfigItem::valueOf("CMAKE_BUILD_TYPE", config);
@@ -395,6 +404,10 @@ const QList<BuildInfo> CMakeProjectImporter::buildInfoList(void *directoryData)
info.buildDirectory = data->buildDirectory;
info.displayName = info.typeName;
QVariantMap config;
config.insert(Constants::CMAKE_HOME_DIR, data->cmakeHomeDirectory.toString());
info.extraInfo = config;
qCDebug(cmInputLog) << "BuildInfo configured.";
return {info};
}

View File

@@ -41,7 +41,8 @@ public:
QStringList importCandidates() final;
private:
QList<void *> examineDirectory(const Utils::FilePath &importPath) const final;
QList<void *> examineDirectory(const Utils::FilePath &importPath,
QString *warningMessage) const final;
bool matchKit(void *directoryData, const ProjectExplorer::Kit *k) const final;
ProjectExplorer::Kit *createKit(void *directoryData) const final;
const QList<ProjectExplorer::BuildInfo> buildInfoList(void *directoryData) const final;