diff --git a/src/plugins/cmakeprojectmanager/builddirmanager.cpp b/src/plugins/cmakeprojectmanager/builddirmanager.cpp index 86d9e0945f6..67ae9387af0 100644 --- a/src/plugins/cmakeprojectmanager/builddirmanager.cpp +++ b/src/plugins/cmakeprojectmanager/builddirmanager.cpp @@ -44,6 +44,7 @@ #include #include +#include #include #include #include @@ -72,12 +73,22 @@ BuildDirManager::~BuildDirManager() = default; const Utils::FileName BuildDirManager::workDirectory() const { const Utils::FileName bdir = m_buildConfiguration->buildDirectory(); - if (bdir.exists()) + const CMakeTool *cmake = CMakeKitInformation::cmakeTool(m_buildConfiguration->target()->kit()); + if (bdir.exists()) { 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) { m_tempDir.reset(new Utils::TemporaryDirectory("qtc-cmake-XXXXXXXX")); - if (!m_tempDir->isValid()) - emitErrorOccured(tr("Failed to create temporary directory \"%1\".").arg(m_tempDir->path())); + if (!m_tempDir->isValid()) { + emitErrorOccured(tr("Failed to create temporary directory \"%1\".") + .arg(QDir::toNativeSeparators(m_tempDir->path()))); + } } return Utils::FileName::fromString(m_tempDir->path()); } diff --git a/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp b/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp index 8381323759d..9f1b7538924 100644 --- a/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp +++ b/src/plugins/cmakeprojectmanager/cmakesettingspage.cpp @@ -66,13 +66,13 @@ public: CMakeToolTreeItem *cmakeToolItem(const Core::Id &id) 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); TreeItem *autoGroupItem() const; TreeItem *manualGroupItem() const; void reevaluateChangedFlag(CMakeToolTreeItem *item) const; 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 apply(); @@ -95,16 +95,18 @@ public: m_name(item->displayName()), m_executable(item->cmakeExecutable()), m_isAutoRun(item->isAutoRun()), + m_autoCreateBuildDirectory(item->autoCreateBuildDirectory()), m_autodetected(item->isAutoDetected()), m_changed(changed) {} 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_name(name), m_executable(executable), m_isAutoRun(autoRun), + m_autoCreateBuildDirectory(autoCreate), m_autodetected(autodetected), m_changed(true) {} @@ -143,6 +145,7 @@ public: QString m_name; FileName m_executable; bool m_isAutoRun = true; + bool m_autoCreateBuildDirectory = false; bool m_autodetected = false; bool m_changed = true; }; @@ -166,9 +169,10 @@ CMakeToolItemModel::CMakeToolItemModel() } 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) autoGroupItem()->appendChild(item); else @@ -219,7 +223,8 @@ void CMakeToolItemModel::reevaluateChangedFlag(CMakeToolTreeItem *item) const } 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); QTC_ASSERT(treeItem, return); @@ -227,6 +232,7 @@ void CMakeToolItemModel::updateCMakeTool(const Core::Id &id, const QString &disp treeItem->m_name = displayName; treeItem->m_executable = executable; treeItem->m_isAutoRun = autoRun; + treeItem->m_autoCreateBuildDirectory = autoCreate; reevaluateChangedFlag(treeItem); } @@ -262,6 +268,7 @@ void CMakeToolItemModel::apply() cmake->setDisplayName(item->m_name); cmake->setCMakeExecutable(item->m_executable); cmake->setAutorun(item->m_isAutoRun); + cmake->setAutoCreateBuildDirectory(item->m_autoCreateBuildDirectory); } else { toRegister.append(item); } @@ -329,6 +336,7 @@ private: CMakeToolItemModel *m_model; QLineEdit *m_displayNameLineEdit; QCheckBox *m_autoRunCheckBox; + QCheckBox *m_autoCreateBuildDirectoryCheckBox; PathChooser *m_binaryChooser; Core::Id m_id; bool m_loadingItem; @@ -349,11 +357,16 @@ CMakeToolItemConfigWidget::CMakeToolItemConfigWidget(CMakeToolItemModel *model) m_autoRunCheckBox->setText(tr("Autorun CMake")); 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); formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); formLayout->addRow(new QLabel(tr("Name:")), m_displayNameLineEdit); formLayout->addRow(new QLabel(tr("Path:")), m_binaryChooser); formLayout->addRow(m_autoRunCheckBox); + formLayout->addRow(m_autoCreateBuildDirectoryCheckBox); connect(m_binaryChooser, &PathChooser::rawPathChanged, this, &CMakeToolItemConfigWidget::store); @@ -361,13 +374,16 @@ CMakeToolItemConfigWidget::CMakeToolItemConfigWidget(CMakeToolItemModel *model) this, &CMakeToolItemConfigWidget::store); connect(m_autoRunCheckBox, &QCheckBox::toggled, this, &CMakeToolItemConfigWidget::store); + connect(m_autoCreateBuildDirectoryCheckBox, &QCheckBox::toggled, + this, &CMakeToolItemConfigWidget::store); } void CMakeToolItemConfigWidget::store() const { if (!m_loadingItem && m_id.isValid()) 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) @@ -387,6 +403,7 @@ void CMakeToolItemConfigWidget::load(const CMakeToolTreeItem *item) m_binaryChooser->setFileName(item->m_executable); m_autoRunCheckBox->setChecked(item->m_isAutoRun); + m_autoCreateBuildDirectoryCheckBox->setChecked(item->m_autoCreateBuildDirectory); m_id = item->m_id; m_loadingItem = false; @@ -492,7 +509,8 @@ void CMakeToolConfigWidget::cloneCMakeTool() QModelIndex newItem = m_model.addCMakeTool(tr("Clone of %1").arg(m_currentItem->m_name), m_currentItem->m_executable, - m_currentItem->m_isAutoRun, false); + m_currentItem->m_isAutoRun, + m_currentItem->m_autoCreateBuildDirectory, false); m_cmakeToolsView->setCurrentIndex(newItem); } @@ -500,7 +518,7 @@ void CMakeToolConfigWidget::cloneCMakeTool() void CMakeToolConfigWidget::addCMakeTool() { QModelIndex newItem = m_model.addCMakeTool(m_model.uniqueDisplayName(tr("New CMake")), - FileName(), true, false); + FileName(), true, false, false); m_cmakeToolsView->setCurrentIndex(newItem); } diff --git a/src/plugins/cmakeprojectmanager/cmaketool.cpp b/src/plugins/cmakeprojectmanager/cmaketool.cpp index 1a107ccd554..9c071dacb85 100644 --- a/src/plugins/cmakeprojectmanager/cmaketool.cpp +++ b/src/plugins/cmakeprojectmanager/cmaketool.cpp @@ -46,6 +46,7 @@ const char CMAKE_INFORMATION_ID[] = "Id"; const char CMAKE_INFORMATION_COMMAND[] = "Binary"; const char CMAKE_INFORMATION_DISPLAYNAME[] = "DisplayName"; const char CMAKE_INFORMATION_AUTORUN[] = "AutoRun"; +const char CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY[] = "AutoCreateBuildDirectory"; const char CMAKE_INFORMATION_AUTODETECTED[] = "AutoDetected"; @@ -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_displayName = map.value(CMAKE_INFORMATION_DISPLAYNAME).toString(); 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 if (!fromSdk) @@ -102,6 +104,15 @@ void CMakeTool::setAutorun(bool autoRun) CMakeToolManager::notifyAboutUpdate(this); } +void CMakeTool::setAutoCreateBuildDirectory(bool autoBuildDir) +{ + if (m_autoCreateBuildDirectory == autoBuildDir) + return; + + m_autoCreateBuildDirectory = autoBuildDir; + CMakeToolManager::notifyAboutUpdate(this); +} + bool CMakeTool::isValid() const { if (!m_id.isValid()) @@ -142,6 +153,7 @@ QVariantMap CMakeTool::toMap() const data.insert(CMAKE_INFORMATION_ID, m_id.toSetting()); data.insert(CMAKE_INFORMATION_COMMAND, m_executable.toString()); data.insert(CMAKE_INFORMATION_AUTORUN, m_isAutoRun); + data.insert(CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY, m_autoCreateBuildDirectory); data.insert(CMAKE_INFORMATION_AUTODETECTED, m_isAutoDetected); return data; } @@ -162,6 +174,11 @@ bool CMakeTool::isAutoRun() const return m_isAutoRun; } +bool CMakeTool::autoCreateBuildDirectory() const +{ + return m_autoCreateBuildDirectory; +} + QList CMakeTool::supportedGenerators() const { readInformation(QueryType::GENERATORS); diff --git a/src/plugins/cmakeprojectmanager/cmaketool.h b/src/plugins/cmakeprojectmanager/cmaketool.h index 5851c75bfc7..95556cefd70 100644 --- a/src/plugins/cmakeprojectmanager/cmaketool.h +++ b/src/plugins/cmakeprojectmanager/cmaketool.h @@ -90,9 +90,11 @@ public: void setCMakeExecutable(const Utils::FileName &executable); void setAutorun(bool autoRun); + void setAutoCreateBuildDirectory(bool autoBuildDir); Utils::FileName cmakeExecutable() const; bool isAutoRun() const; + bool autoCreateBuildDirectory() const; QList supportedGenerators() const; TextEditor::Keywords keywords(); bool hasServerMode() const; @@ -127,6 +129,7 @@ private: bool m_isAutoRun = true; bool m_isAutoDetected = false; + bool m_autoCreateBuildDirectory = false; mutable bool m_didAttemptToRun = false; mutable bool m_didRun = false;