Commit 8fb3105e authored by Tobias Hunger's avatar Tobias Hunger

CMake: Add option to auto-create build directories

Add an option to CMakeTools to force auto-creation of build directories.
This does lead to cmake cluttering up the file system with directories, but
does not force users to go through the oftentimes long configuration process
twice (once in a temporary directory and once in the real location).

Task-number: QTCREATORBUG-16794
Change-Id: I68d92fc58638ad0a0a7622b7ef1621e055c9f2a7
Reviewed-by: Riitta-Leena Miettinen's avatarLeena Miettinen <riitta-leena.miettinen@qt.io>
Reviewed-by: Tim Jenssen's avatarTim Jenssen <tim.jenssen@qt.io>
parent ab1d1dae
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QDir>
#include <QMessageBox> #include <QMessageBox>
#include <QPushButton> #include <QPushButton>
#include <QSet> #include <QSet>
...@@ -72,12 +73,22 @@ BuildDirManager::~BuildDirManager() = default; ...@@ -72,12 +73,22 @@ BuildDirManager::~BuildDirManager() = default;
const Utils::FileName BuildDirManager::workDirectory() const const Utils::FileName BuildDirManager::workDirectory() const
{ {
const Utils::FileName bdir = m_buildConfiguration->buildDirectory(); const Utils::FileName bdir = m_buildConfiguration->buildDirectory();
if (bdir.exists()) const CMakeTool *cmake = CMakeKitInformation::cmakeTool(m_buildConfiguration->target()->kit());
if (bdir.exists()) {
return bdir; return bdir;
} else {
if (cmake && cmake->autoCreateBuildDirectory()) {
if (!QDir().mkpath(bdir.toString()))
emitErrorOccured(tr("Failed to create build directory \"%1\".").arg(bdir.toUserOutput()));
return bdir;
}
}
if (!m_tempDir) { if (!m_tempDir) {
m_tempDir.reset(new Utils::TemporaryDirectory("qtc-cmake-XXXXXXXX")); m_tempDir.reset(new Utils::TemporaryDirectory("qtc-cmake-XXXXXXXX"));
if (!m_tempDir->isValid()) if (!m_tempDir->isValid()) {
emitErrorOccured(tr("Failed to create temporary directory \"%1\".").arg(m_tempDir->path())); emitErrorOccured(tr("Failed to create temporary directory \"%1\".")
.arg(QDir::toNativeSeparators(m_tempDir->path())));
}
} }
return Utils::FileName::fromString(m_tempDir->path()); return Utils::FileName::fromString(m_tempDir->path());
} }
......
...@@ -66,13 +66,13 @@ public: ...@@ -66,13 +66,13 @@ public:
CMakeToolTreeItem *cmakeToolItem(const Core::Id &id) const; CMakeToolTreeItem *cmakeToolItem(const Core::Id &id) const;
CMakeToolTreeItem *cmakeToolItem(const QModelIndex &index) const; CMakeToolTreeItem *cmakeToolItem(const QModelIndex &index) const;
QModelIndex addCMakeTool(const QString &name, const FileName &executable, const bool autoRun, const bool isAutoDetected); QModelIndex addCMakeTool(const QString &name, const FileName &executable, const bool autoRun, const bool autoCreate, const bool isAutoDetected);
void addCMakeTool(const CMakeTool *item, bool changed); void addCMakeTool(const CMakeTool *item, bool changed);
TreeItem *autoGroupItem() const; TreeItem *autoGroupItem() const;
TreeItem *manualGroupItem() const; TreeItem *manualGroupItem() const;
void reevaluateChangedFlag(CMakeToolTreeItem *item) const; void reevaluateChangedFlag(CMakeToolTreeItem *item) const;
void updateCMakeTool(const Core::Id &id, const QString &displayName, const FileName &executable, void updateCMakeTool(const Core::Id &id, const QString &displayName, const FileName &executable,
bool autoRun); bool autoRun, bool autoCreate);
void removeCMakeTool(const Core::Id &id); void removeCMakeTool(const Core::Id &id);
void apply(); void apply();
...@@ -95,16 +95,18 @@ public: ...@@ -95,16 +95,18 @@ public:
m_name(item->displayName()), m_name(item->displayName()),
m_executable(item->cmakeExecutable()), m_executable(item->cmakeExecutable()),
m_isAutoRun(item->isAutoRun()), m_isAutoRun(item->isAutoRun()),
m_autoCreateBuildDirectory(item->autoCreateBuildDirectory()),
m_autodetected(item->isAutoDetected()), m_autodetected(item->isAutoDetected()),
m_changed(changed) m_changed(changed)
{} {}
CMakeToolTreeItem(const QString &name, const Utils::FileName &executable, CMakeToolTreeItem(const QString &name, const Utils::FileName &executable,
bool autoRun, bool autodetected) : bool autoRun, bool autoCreate, bool autodetected) :
m_id(Core::Id::fromString(QUuid::createUuid().toString())), m_id(Core::Id::fromString(QUuid::createUuid().toString())),
m_name(name), m_name(name),
m_executable(executable), m_executable(executable),
m_isAutoRun(autoRun), m_isAutoRun(autoRun),
m_autoCreateBuildDirectory(autoCreate),
m_autodetected(autodetected), m_autodetected(autodetected),
m_changed(true) m_changed(true)
{} {}
...@@ -143,6 +145,7 @@ public: ...@@ -143,6 +145,7 @@ public:
QString m_name; QString m_name;
FileName m_executable; FileName m_executable;
bool m_isAutoRun = true; bool m_isAutoRun = true;
bool m_autoCreateBuildDirectory = false;
bool m_autodetected = false; bool m_autodetected = false;
bool m_changed = true; bool m_changed = true;
}; };
...@@ -166,9 +169,10 @@ CMakeToolItemModel::CMakeToolItemModel() ...@@ -166,9 +169,10 @@ CMakeToolItemModel::CMakeToolItemModel()
} }
QModelIndex CMakeToolItemModel::addCMakeTool(const QString &name, const FileName &executable, QModelIndex CMakeToolItemModel::addCMakeTool(const QString &name, const FileName &executable,
const bool autoRun, const bool isAutoDetected) const bool autoRun, const bool autoCreate,
const bool isAutoDetected)
{ {
CMakeToolTreeItem *item = new CMakeToolTreeItem(name, executable, autoRun, isAutoDetected); CMakeToolTreeItem *item = new CMakeToolTreeItem(name, executable, autoRun, autoCreate, isAutoDetected);
if (isAutoDetected) if (isAutoDetected)
autoGroupItem()->appendChild(item); autoGroupItem()->appendChild(item);
else else
...@@ -219,7 +223,8 @@ void CMakeToolItemModel::reevaluateChangedFlag(CMakeToolTreeItem *item) const ...@@ -219,7 +223,8 @@ void CMakeToolItemModel::reevaluateChangedFlag(CMakeToolTreeItem *item) const
} }
void CMakeToolItemModel::updateCMakeTool(const Core::Id &id, const QString &displayName, void CMakeToolItemModel::updateCMakeTool(const Core::Id &id, const QString &displayName,
const FileName &executable, bool autoRun) const FileName &executable, bool autoRun,
bool autoCreate)
{ {
CMakeToolTreeItem *treeItem = cmakeToolItem(id); CMakeToolTreeItem *treeItem = cmakeToolItem(id);
QTC_ASSERT(treeItem, return); QTC_ASSERT(treeItem, return);
...@@ -227,6 +232,7 @@ void CMakeToolItemModel::updateCMakeTool(const Core::Id &id, const QString &disp ...@@ -227,6 +232,7 @@ void CMakeToolItemModel::updateCMakeTool(const Core::Id &id, const QString &disp
treeItem->m_name = displayName; treeItem->m_name = displayName;
treeItem->m_executable = executable; treeItem->m_executable = executable;
treeItem->m_isAutoRun = autoRun; treeItem->m_isAutoRun = autoRun;
treeItem->m_autoCreateBuildDirectory = autoCreate;
reevaluateChangedFlag(treeItem); reevaluateChangedFlag(treeItem);
} }
...@@ -262,6 +268,7 @@ void CMakeToolItemModel::apply() ...@@ -262,6 +268,7 @@ void CMakeToolItemModel::apply()
cmake->setDisplayName(item->m_name); cmake->setDisplayName(item->m_name);
cmake->setCMakeExecutable(item->m_executable); cmake->setCMakeExecutable(item->m_executable);
cmake->setAutorun(item->m_isAutoRun); cmake->setAutorun(item->m_isAutoRun);
cmake->setAutoCreateBuildDirectory(item->m_autoCreateBuildDirectory);
} else { } else {
toRegister.append(item); toRegister.append(item);
} }
...@@ -329,6 +336,7 @@ private: ...@@ -329,6 +336,7 @@ private:
CMakeToolItemModel *m_model; CMakeToolItemModel *m_model;
QLineEdit *m_displayNameLineEdit; QLineEdit *m_displayNameLineEdit;
QCheckBox *m_autoRunCheckBox; QCheckBox *m_autoRunCheckBox;
QCheckBox *m_autoCreateBuildDirectoryCheckBox;
PathChooser *m_binaryChooser; PathChooser *m_binaryChooser;
Core::Id m_id; Core::Id m_id;
bool m_loadingItem; bool m_loadingItem;
...@@ -349,11 +357,16 @@ CMakeToolItemConfigWidget::CMakeToolItemConfigWidget(CMakeToolItemModel *model) ...@@ -349,11 +357,16 @@ CMakeToolItemConfigWidget::CMakeToolItemConfigWidget(CMakeToolItemModel *model)
m_autoRunCheckBox->setText(tr("Autorun CMake")); m_autoRunCheckBox->setText(tr("Autorun CMake"));
m_autoRunCheckBox->setToolTip(tr("Automatically run CMake after changes to CMake project files.")); m_autoRunCheckBox->setToolTip(tr("Automatically run CMake after changes to CMake project files."));
m_autoCreateBuildDirectoryCheckBox = new QCheckBox;
m_autoCreateBuildDirectoryCheckBox->setText(tr("Auto-create build directories"));
m_autoCreateBuildDirectoryCheckBox->setToolTip(tr("Automatically create build directories for CMake projects."));
QFormLayout *formLayout = new QFormLayout(this); QFormLayout *formLayout = new QFormLayout(this);
formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
formLayout->addRow(new QLabel(tr("Name:")), m_displayNameLineEdit); formLayout->addRow(new QLabel(tr("Name:")), m_displayNameLineEdit);
formLayout->addRow(new QLabel(tr("Path:")), m_binaryChooser); formLayout->addRow(new QLabel(tr("Path:")), m_binaryChooser);
formLayout->addRow(m_autoRunCheckBox); formLayout->addRow(m_autoRunCheckBox);
formLayout->addRow(m_autoCreateBuildDirectoryCheckBox);
connect(m_binaryChooser, &PathChooser::rawPathChanged, connect(m_binaryChooser, &PathChooser::rawPathChanged,
this, &CMakeToolItemConfigWidget::store); this, &CMakeToolItemConfigWidget::store);
...@@ -361,13 +374,16 @@ CMakeToolItemConfigWidget::CMakeToolItemConfigWidget(CMakeToolItemModel *model) ...@@ -361,13 +374,16 @@ CMakeToolItemConfigWidget::CMakeToolItemConfigWidget(CMakeToolItemModel *model)
this, &CMakeToolItemConfigWidget::store); this, &CMakeToolItemConfigWidget::store);
connect(m_autoRunCheckBox, &QCheckBox::toggled, connect(m_autoRunCheckBox, &QCheckBox::toggled,
this, &CMakeToolItemConfigWidget::store); this, &CMakeToolItemConfigWidget::store);
connect(m_autoCreateBuildDirectoryCheckBox, &QCheckBox::toggled,
this, &CMakeToolItemConfigWidget::store);
} }
void CMakeToolItemConfigWidget::store() const void CMakeToolItemConfigWidget::store() const
{ {
if (!m_loadingItem && m_id.isValid()) if (!m_loadingItem && m_id.isValid())
m_model->updateCMakeTool(m_id, m_displayNameLineEdit->text(), m_binaryChooser->fileName(), m_model->updateCMakeTool(m_id, m_displayNameLineEdit->text(), m_binaryChooser->fileName(),
m_autoRunCheckBox->checkState() == Qt::Checked); m_autoRunCheckBox->checkState() == Qt::Checked,
m_autoCreateBuildDirectoryCheckBox->checkState() == Qt::Checked);
} }
void CMakeToolItemConfigWidget::load(const CMakeToolTreeItem *item) void CMakeToolItemConfigWidget::load(const CMakeToolTreeItem *item)
...@@ -387,6 +403,7 @@ void CMakeToolItemConfigWidget::load(const CMakeToolTreeItem *item) ...@@ -387,6 +403,7 @@ void CMakeToolItemConfigWidget::load(const CMakeToolTreeItem *item)
m_binaryChooser->setFileName(item->m_executable); m_binaryChooser->setFileName(item->m_executable);
m_autoRunCheckBox->setChecked(item->m_isAutoRun); m_autoRunCheckBox->setChecked(item->m_isAutoRun);
m_autoCreateBuildDirectoryCheckBox->setChecked(item->m_autoCreateBuildDirectory);
m_id = item->m_id; m_id = item->m_id;
m_loadingItem = false; m_loadingItem = false;
...@@ -492,7 +509,8 @@ void CMakeToolConfigWidget::cloneCMakeTool() ...@@ -492,7 +509,8 @@ void CMakeToolConfigWidget::cloneCMakeTool()
QModelIndex newItem = m_model.addCMakeTool(tr("Clone of %1").arg(m_currentItem->m_name), QModelIndex newItem = m_model.addCMakeTool(tr("Clone of %1").arg(m_currentItem->m_name),
m_currentItem->m_executable, m_currentItem->m_executable,
m_currentItem->m_isAutoRun, false); m_currentItem->m_isAutoRun,
m_currentItem->m_autoCreateBuildDirectory, false);
m_cmakeToolsView->setCurrentIndex(newItem); m_cmakeToolsView->setCurrentIndex(newItem);
} }
...@@ -500,7 +518,7 @@ void CMakeToolConfigWidget::cloneCMakeTool() ...@@ -500,7 +518,7 @@ void CMakeToolConfigWidget::cloneCMakeTool()
void CMakeToolConfigWidget::addCMakeTool() void CMakeToolConfigWidget::addCMakeTool()
{ {
QModelIndex newItem = m_model.addCMakeTool(m_model.uniqueDisplayName(tr("New CMake")), QModelIndex newItem = m_model.addCMakeTool(m_model.uniqueDisplayName(tr("New CMake")),
FileName(), true, false); FileName(), true, false, false);
m_cmakeToolsView->setCurrentIndex(newItem); m_cmakeToolsView->setCurrentIndex(newItem);
} }
......
...@@ -46,6 +46,7 @@ const char CMAKE_INFORMATION_ID[] = "Id"; ...@@ -46,6 +46,7 @@ const char CMAKE_INFORMATION_ID[] = "Id";
const char CMAKE_INFORMATION_COMMAND[] = "Binary"; const char CMAKE_INFORMATION_COMMAND[] = "Binary";
const char CMAKE_INFORMATION_DISPLAYNAME[] = "DisplayName"; const char CMAKE_INFORMATION_DISPLAYNAME[] = "DisplayName";
const char CMAKE_INFORMATION_AUTORUN[] = "AutoRun"; const char CMAKE_INFORMATION_AUTORUN[] = "AutoRun";
const char CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY[] = "AutoCreateBuildDirectory";
const char CMAKE_INFORMATION_AUTODETECTED[] = "AutoDetected"; const char CMAKE_INFORMATION_AUTODETECTED[] = "AutoDetected";
...@@ -68,6 +69,7 @@ CMakeTool::CMakeTool(const QVariantMap &map, bool fromSdk) : m_isAutoDetected(fr ...@@ -68,6 +69,7 @@ CMakeTool::CMakeTool(const QVariantMap &map, bool fromSdk) : m_isAutoDetected(fr
m_id = Core::Id::fromSetting(map.value(CMAKE_INFORMATION_ID)); m_id = Core::Id::fromSetting(map.value(CMAKE_INFORMATION_ID));
m_displayName = map.value(CMAKE_INFORMATION_DISPLAYNAME).toString(); m_displayName = map.value(CMAKE_INFORMATION_DISPLAYNAME).toString();
m_isAutoRun = map.value(CMAKE_INFORMATION_AUTORUN, true).toBool(); m_isAutoRun = map.value(CMAKE_INFORMATION_AUTORUN, true).toBool();
m_autoCreateBuildDirectory = map.value(CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY, false).toBool();
//loading a CMakeTool from SDK is always autodetection //loading a CMakeTool from SDK is always autodetection
if (!fromSdk) if (!fromSdk)
...@@ -102,6 +104,15 @@ void CMakeTool::setAutorun(bool autoRun) ...@@ -102,6 +104,15 @@ void CMakeTool::setAutorun(bool autoRun)
CMakeToolManager::notifyAboutUpdate(this); CMakeToolManager::notifyAboutUpdate(this);
} }
void CMakeTool::setAutoCreateBuildDirectory(bool autoBuildDir)
{
if (m_autoCreateBuildDirectory == autoBuildDir)
return;
m_autoCreateBuildDirectory = autoBuildDir;
CMakeToolManager::notifyAboutUpdate(this);
}
bool CMakeTool::isValid() const bool CMakeTool::isValid() const
{ {
if (!m_id.isValid()) if (!m_id.isValid())
...@@ -142,6 +153,7 @@ QVariantMap CMakeTool::toMap() const ...@@ -142,6 +153,7 @@ QVariantMap CMakeTool::toMap() const
data.insert(CMAKE_INFORMATION_ID, m_id.toSetting()); data.insert(CMAKE_INFORMATION_ID, m_id.toSetting());
data.insert(CMAKE_INFORMATION_COMMAND, m_executable.toString()); data.insert(CMAKE_INFORMATION_COMMAND, m_executable.toString());
data.insert(CMAKE_INFORMATION_AUTORUN, m_isAutoRun); data.insert(CMAKE_INFORMATION_AUTORUN, m_isAutoRun);
data.insert(CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY, m_autoCreateBuildDirectory);
data.insert(CMAKE_INFORMATION_AUTODETECTED, m_isAutoDetected); data.insert(CMAKE_INFORMATION_AUTODETECTED, m_isAutoDetected);
return data; return data;
} }
...@@ -162,6 +174,11 @@ bool CMakeTool::isAutoRun() const ...@@ -162,6 +174,11 @@ bool CMakeTool::isAutoRun() const
return m_isAutoRun; return m_isAutoRun;
} }
bool CMakeTool::autoCreateBuildDirectory() const
{
return m_autoCreateBuildDirectory;
}
QList<CMakeTool::Generator> CMakeTool::supportedGenerators() const QList<CMakeTool::Generator> CMakeTool::supportedGenerators() const
{ {
readInformation(QueryType::GENERATORS); readInformation(QueryType::GENERATORS);
......
...@@ -90,9 +90,11 @@ public: ...@@ -90,9 +90,11 @@ public:
void setCMakeExecutable(const Utils::FileName &executable); void setCMakeExecutable(const Utils::FileName &executable);
void setAutorun(bool autoRun); void setAutorun(bool autoRun);
void setAutoCreateBuildDirectory(bool autoBuildDir);
Utils::FileName cmakeExecutable() const; Utils::FileName cmakeExecutable() const;
bool isAutoRun() const; bool isAutoRun() const;
bool autoCreateBuildDirectory() const;
QList<Generator> supportedGenerators() const; QList<Generator> supportedGenerators() const;
TextEditor::Keywords keywords(); TextEditor::Keywords keywords();
bool hasServerMode() const; bool hasServerMode() const;
...@@ -127,6 +129,7 @@ private: ...@@ -127,6 +129,7 @@ private:
bool m_isAutoRun = true; bool m_isAutoRun = true;
bool m_isAutoDetected = false; bool m_isAutoDetected = false;
bool m_autoCreateBuildDirectory = false;
mutable bool m_didAttemptToRun = false; mutable bool m_didAttemptToRun = false;
mutable bool m_didRun = false; mutable bool m_didRun = false;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment