aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@qt.io>2019-04-12 14:49:59 +0200
committerChristian Kandeler <christian.kandeler@qt.io>2019-04-23 15:52:05 +0000
commit261d7752b00dfe7191ebd1436e9e96a5212e1bb3 (patch)
tree08e5040fe25cd244221b0dd5f9b296ef0487a331
parent8827d83115b5b3c88446dd3ba50341ca3b738c0a (diff)
RemoteLinux: Retrieve deployment info from local install root
This provides correct deployment information as seen by the build system when Qt Creator cannot retrieve it directly. It's most useful for autotools and cmake projects, but can also help with qmake in certain edge cases. [ChangeLog] It is no longer necessary to provide a QtCreatorDeployment.txt file when using CMake projects with remote Linux devices. Fixes: QTCREATORBUG-21855 Change-Id: I27e07a45dd1565e489f4b573cc3fff8191c57d9b Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io> Reviewed-by: hjk <hjk@qt.io>
-rw-r--r--doc/src/cmake/creator-projects-cmake-deploying.qdocinc11
-rw-r--r--src/plugins/autotoolsprojectmanager/autotoolsproject.h2
-rw-r--r--src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp8
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeproject.cpp24
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeproject.h5
-rw-r--r--src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h1
-rw-r--r--src/plugins/genericprojectmanager/genericproject.cpp5
-rw-r--r--src/plugins/genericprojectmanager/genericproject.h2
-rw-r--r--src/plugins/projectexplorer/deploymentdata.h12
-rw-r--r--src/plugins/projectexplorer/makestep.h4
-rw-r--r--src/plugins/projectexplorer/project.cpp15
-rw-r--r--src/plugins/projectexplorer/project.h5
-rw-r--r--src/plugins/projectexplorer/target.cpp5
-rw-r--r--src/plugins/projectexplorer/target.h2
-rw-r--r--src/plugins/qbsprojectmanager/qbsproject.cpp5
-rw-r--r--src/plugins/qbsprojectmanager/qbsproject.h2
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeproject.cpp5
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeproject.h4
-rw-r--r--src/plugins/qmlprojectmanager/qmlproject.cpp5
-rw-r--r--src/plugins/qmlprojectmanager/qmlproject.h2
-rw-r--r--src/plugins/remotelinux/genericdirectuploadstep.cpp7
-rw-r--r--src/plugins/remotelinux/genericdirectuploadstep.h1
-rw-r--r--src/plugins/remotelinux/makeinstallstep.cpp205
-rw-r--r--src/plugins/remotelinux/makeinstallstep.h62
-rw-r--r--src/plugins/remotelinux/remotelinux.pro2
-rw-r--r--src/plugins/remotelinux/remotelinux.qbs4
-rw-r--r--src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp6
-rw-r--r--src/plugins/remotelinux/remotelinuxplugin.cpp2
-rw-r--r--src/plugins/remotelinux/rsyncdeploystep.cpp7
-rw-r--r--src/plugins/remotelinux/rsyncdeploystep.h1
30 files changed, 409 insertions, 12 deletions
diff --git a/doc/src/cmake/creator-projects-cmake-deploying.qdocinc b/doc/src/cmake/creator-projects-cmake-deploying.qdocinc
index a5adb5e19e..a9c53ea4e2 100644
--- a/doc/src/cmake/creator-projects-cmake-deploying.qdocinc
+++ b/doc/src/cmake/creator-projects-cmake-deploying.qdocinc
@@ -34,10 +34,13 @@
\section1 Deploying CMake Projects to Embedded Linux Devices
- \QC cannot extract files to be installed from a CMake project, and
- therefore, only executable targets are automatically added to deployment
- files. You must specify all other files in the \c {QtCreatorDeployment.txt}
- file that you create and place in either the root directory of the CMake
+ \QC cannot directly extract files to be installed from a CMake project.
+ Therefore, a special deploy step is created that installs the project into
+ a local directory. The files in that directory are then deployed to the
+ remote device.
+ Alternatively, you can provide a \c {QtCreatorDeployment.txt} file in which
+ you must specify all files to be deployed which are not executables or
+ libraries. You place this file in either the root directory of the CMake
project or the build directory of the active build configuration.
Currently, \QC first checks the root directory and only if no
\c {QtCreatorDeployment.txt} exists it checks the active build directory.
diff --git a/src/plugins/autotoolsprojectmanager/autotoolsproject.h b/src/plugins/autotoolsprojectmanager/autotoolsproject.h
index b9016bdcc0..36bf187a07 100644
--- a/src/plugins/autotoolsprojectmanager/autotoolsproject.h
+++ b/src/plugins/autotoolsprojectmanager/autotoolsproject.h
@@ -63,6 +63,8 @@ protected:
RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) override;
private:
+ bool hasMakeInstallEquivalent() const override { return true; }
+
/**
* Loads the project tree by parsing the makefiles.
*/
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp
index 1e7e66655a..08d5c5d69c 100644
--- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp
@@ -230,11 +230,11 @@ DeploymentData CMakeBuildConfiguration::deploymentData() const
deploymentFilePath = buildDir.filePath("QtCreatorDeployment.txt");
hasDeploymentFile = QFileInfo::exists(deploymentFilePath);
}
- if (hasDeploymentFile) {
- deploymentPrefix = result.addFilesFromDeploymentFile(deploymentFilePath,
- sourceDir.absolutePath());
- }
+ if (!hasDeploymentFile)
+ return result;
+ deploymentPrefix = result.addFilesFromDeploymentFile(deploymentFilePath,
+ sourceDir.absolutePath());
for (const CMakeBuildTarget &ct : m_buildTargets) {
if (ct.targetType == ExecutableType || ct.targetType == DynamicLibraryType) {
if (!ct.executable.isEmpty()) {
diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
index 5005caa29e..67a2a6020e 100644
--- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
@@ -26,6 +26,7 @@
#include "cmakeproject.h"
#include "cmakebuildconfiguration.h"
+#include "cmakebuildstep.h"
#include "cmakekitinformation.h"
#include "cmakeprojectconstants.h"
#include "cmakeprojectnodes.h"
@@ -37,6 +38,7 @@
#include <cpptools/generatedcodemodelsupport.h>
#include <cpptools/projectinfo.h>
#include <cpptools/cpptoolsconstants.h>
+#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/buildtargetinfo.h>
#include <projectexplorer/deploymentdata.h>
#include <projectexplorer/headerpath.h>
@@ -619,6 +621,28 @@ QStringList CMakeProject::filesGeneratedFrom(const QString &sourceFile) const
}
}
+ProjectExplorer::DeploymentKnowledge CMakeProject::deploymentKnowledge() const
+{
+ return contains(files(AllFiles), [](const FileName &f) {
+ return f.fileName() == "QtCreatorDeployment.txt";
+ }) ? DeploymentKnowledge::Approximative : DeploymentKnowledge::Bad;
+}
+
+MakeInstallCommand CMakeProject::makeInstallCommand(const Target *target,
+ const QString &installRoot)
+{
+ MakeInstallCommand cmd;
+ if (const BuildConfiguration * const bc = target->activeBuildConfiguration()) {
+ if (const auto cmakeStep = bc->stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD)
+ ->firstOfType<CMakeBuildStep>()) {
+ cmd.command = FileName::fromString(cmakeStep->cmakeCommand());
+ }
+ }
+ cmd.arguments << "--build" << "." << "--target" << "install";
+ cmd.environment.set("DESTDIR", QDir::toNativeSeparators(installRoot));
+ return cmd;
+}
+
bool CMakeProject::mustUpdateCMakeStateBeforeBuild()
{
return m_delayedParsingTimer.isActive();
diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.h b/src/plugins/cmakeprojectmanager/cmakeproject.h
index ab4717b2b0..f77f0982c5 100644
--- a/src/plugins/cmakeprojectmanager/cmakeproject.h
+++ b/src/plugins/cmakeprojectmanager/cmakeproject.h
@@ -103,6 +103,11 @@ private:
QList<ProjectExplorer::ExtraCompiler *> findExtraCompilers() const;
QStringList filesGeneratedFrom(const QString &sourceFile) const final;
+ ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override;
+ bool hasMakeInstallEquivalent() const override { return true; }
+ ProjectExplorer::MakeInstallCommand makeInstallCommand(const ProjectExplorer::Target *target,
+ const QString &installRoot) override;
+
// TODO probably need a CMake specific node structure
QList<CMakeBuildTarget> m_buildTargets;
CppTools::CppProjectUpdater *m_cppCodeModelUpdater = nullptr;
diff --git a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h
index de887e5463..73ffae75b0 100644
--- a/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h
+++ b/src/plugins/compilationdatabaseprojectmanager/compilationdatabaseproject.h
@@ -55,6 +55,7 @@ public:
private:
RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) override;
+
void reparseProject();
void buildTreeAndProjectParts(const Utils::FileName &projectFile);
diff --git a/src/plugins/genericprojectmanager/genericproject.cpp b/src/plugins/genericprojectmanager/genericproject.cpp
index f58e5bff01..b7c1066ac5 100644
--- a/src/plugins/genericprojectmanager/genericproject.cpp
+++ b/src/plugins/genericprojectmanager/genericproject.cpp
@@ -566,5 +566,10 @@ Project::RestoreResult GenericProject::fromMap(const QVariantMap &map, QString *
return RestoreResult::Ok;
}
+ProjectExplorer::DeploymentKnowledge GenericProject::deploymentKnowledge() const
+{
+ return DeploymentKnowledge::Approximative;
+}
+
} // namespace Internal
} // namespace GenericProjectManager
diff --git a/src/plugins/genericprojectmanager/genericproject.h b/src/plugins/genericprojectmanager/genericproject.h
index 0a1469588c..7202d91810 100644
--- a/src/plugins/genericprojectmanager/genericproject.h
+++ b/src/plugins/genericprojectmanager/genericproject.h
@@ -58,6 +58,8 @@ protected:
RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) override;
private:
+ ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override;
+
bool saveRawFileList(const QStringList &rawFileList);
bool saveRawList(const QStringList &rawList, const QString &fileName);
void parseProject(RefreshOptions options);
diff --git a/src/plugins/projectexplorer/deploymentdata.h b/src/plugins/projectexplorer/deploymentdata.h
index 7297ad84b2..d9e05a1d83 100644
--- a/src/plugins/projectexplorer/deploymentdata.h
+++ b/src/plugins/projectexplorer/deploymentdata.h
@@ -28,10 +28,22 @@
#include "deployablefile.h"
#include "projectexplorer_export.h"
+#include <utils/environment.h>
+
#include <QList>
namespace ProjectExplorer {
+enum class DeploymentKnowledge { Perfect, Approximative, Bad };
+
+class PROJECTEXPLORER_EXPORT MakeInstallCommand
+{
+public:
+ Utils::FileName command;
+ QStringList arguments;
+ Utils::Environment environment;
+};
+
class PROJECTEXPLORER_EXPORT DeploymentData
{
public:
diff --git a/src/plugins/projectexplorer/makestep.h b/src/plugins/projectexplorer/makestep.h
index 036b55e254..84718858b1 100644
--- a/src/plugins/projectexplorer/makestep.h
+++ b/src/plugins/projectexplorer/makestep.h
@@ -80,9 +80,11 @@ public:
Utils::Environment environment(BuildConfiguration *bc) const;
+protected:
+ bool fromMap(const QVariantMap &map) override;
+
private:
QVariantMap toMap() const override;
- bool fromMap(const QVariantMap &map) override;
static int defaultJobCount();
QStringList jobArguments() const;
diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp
index a439beecc7..b2b96ccb65 100644
--- a/src/plugins/projectexplorer/project.cpp
+++ b/src/plugins/projectexplorer/project.cpp
@@ -30,6 +30,7 @@
#include "deployconfiguration.h"
#include "editorconfiguration.h"
#include "kit.h"
+#include "makestep.h"
#include "projectexplorer.h"
#include "projectnodes.h"
#include "target.h"
@@ -847,6 +848,20 @@ bool Project::knowsAllBuildExecutables() const
return true;
}
+MakeInstallCommand Project::makeInstallCommand(const Target *target, const QString &installRoot)
+{
+ QTC_ASSERT(hasMakeInstallEquivalent(), return MakeInstallCommand());
+ MakeInstallCommand cmd;
+ if (const BuildConfiguration * const bc = target->activeBuildConfiguration()) {
+ if (const auto makeStep = bc->stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD)
+ ->firstOfType<MakeStep>()) {
+ cmd.command = Utils::FileName::fromString(makeStep->effectiveMakeCommand());
+ }
+ }
+ cmd.arguments << "install" << ("INSTALL_ROOT=" + QDir::toNativeSeparators(installRoot));
+ return cmd;
+}
+
void Project::setup(const QList<BuildInfo> &infoList)
{
std::vector<std::unique_ptr<Target>> toRegister;
diff --git a/src/plugins/projectexplorer/project.h b/src/plugins/projectexplorer/project.h
index 0709bb5e26..85f514ff33 100644
--- a/src/plugins/projectexplorer/project.h
+++ b/src/plugins/projectexplorer/project.h
@@ -27,6 +27,7 @@
#include "projectexplorer_export.h"
+#include "deploymentdata.h"
#include "kit.h"
#include "subscription.h"
@@ -165,6 +166,10 @@ public:
// of configuration.
virtual bool knowsAllBuildExecutables() const;
+ virtual DeploymentKnowledge deploymentKnowledge() const { return DeploymentKnowledge::Bad; }
+ virtual bool hasMakeInstallEquivalent() const { return false; }
+ virtual MakeInstallCommand makeInstallCommand(const Target *target, const QString &installRoot);
+
void setup(const QList<BuildInfo> &infoList);
Utils::MacroExpander *macroExpander() const;
diff --git a/src/plugins/projectexplorer/target.cpp b/src/plugins/projectexplorer/target.cpp
index a6a5c9a94c..6c05bb100f 100644
--- a/src/plugins/projectexplorer/target.cpp
+++ b/src/plugins/projectexplorer/target.cpp
@@ -694,6 +694,11 @@ QVariant Target::additionalData(Core::Id id) const
return project()->additionalData(id, this);
}
+MakeInstallCommand Target::makeInstallCommand(const QString &installRoot) const
+{
+ return project()->makeInstallCommand(this, installRoot);
+}
+
void Target::updateDeviceState()
{
IDevice::ConstPtr current = DeviceKitAspect::device(kit());
diff --git a/src/plugins/projectexplorer/target.h b/src/plugins/projectexplorer/target.h
index e236d22dcb..3ac437787c 100644
--- a/src/plugins/projectexplorer/target.h
+++ b/src/plugins/projectexplorer/target.h
@@ -41,6 +41,7 @@ class BuildTargetInfo;
class DeployConfiguration;
class DeploymentData;
class Kit;
+class MakeInstallCommand;
class Project;
class RunConfiguration;
@@ -118,6 +119,7 @@ public:
void setNamedSettings(const QString &name, const QVariant &value);
QVariant additionalData(Core::Id id) const;
+ MakeInstallCommand makeInstallCommand(const QString &installRoot) const;
template<typename S, typename R, typename T>
void subscribeSignal(void (S::*sig)(), R*recv, T (R::*sl)()) {
diff --git a/src/plugins/qbsprojectmanager/qbsproject.cpp b/src/plugins/qbsprojectmanager/qbsproject.cpp
index b621031131..b7a188f86d 100644
--- a/src/plugins/qbsprojectmanager/qbsproject.cpp
+++ b/src/plugins/qbsprojectmanager/qbsproject.cpp
@@ -201,6 +201,11 @@ QVariant QbsProject::additionalData(Id id, const Target *target) const
return Project::additionalData(id, target);
}
+ProjectExplorer::DeploymentKnowledge QbsProject::deploymentKnowledge() const
+{
+ return DeploymentKnowledge::Perfect;
+}
+
QStringList QbsProject::filesGeneratedFrom(const QString &sourceFile) const
{
QStringList generated;
diff --git a/src/plugins/qbsprojectmanager/qbsproject.h b/src/plugins/qbsprojectmanager/qbsproject.h
index 5a2db0fa65..835f6c6b55 100644
--- a/src/plugins/qbsprojectmanager/qbsproject.h
+++ b/src/plugins/qbsprojectmanager/qbsproject.h
@@ -134,6 +134,8 @@ private:
ProjectExplorer::ProjectImporter *projectImporter() const override;
QVariant additionalData(Core::Id id, const ProjectExplorer::Target *target) const final;
+ ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override;
+
static bool ensureWriteableQbsFile(const QString &file);
template<typename Options> qbs::AbstractJob *buildOrClean(const Options &opts,
diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.cpp b/src/plugins/qmakeprojectmanager/qmakeproject.cpp
index 7def8da738..163bf755aa 100644
--- a/src/plugins/qmakeprojectmanager/qmakeproject.cpp
+++ b/src/plugins/qmakeprojectmanager/qmakeproject.cpp
@@ -203,6 +203,11 @@ Project::RestoreResult QmakeProject::fromMap(const QVariantMap &map, QString *er
return RestoreResult::Ok;
}
+DeploymentKnowledge QmakeProject::deploymentKnowledge() const
+{
+ return DeploymentKnowledge::Approximative; // E.g. QTCREATORBUG-21855
+}
+
void QmakeProject::updateCodeModels()
{
if (activeTarget() && !activeTarget()->activeBuildConfiguration())
diff --git a/src/plugins/qmakeprojectmanager/qmakeproject.h b/src/plugins/qmakeprojectmanager/qmakeproject.h
index bdcb1c477a..f042d190aa 100644
--- a/src/plugins/qmakeprojectmanager/qmakeproject.h
+++ b/src/plugins/qmakeprojectmanager/qmakeproject.h
@@ -30,6 +30,7 @@
#include "qmakenodes.h"
#include "qmakeparsernodes.h"
+#include <projectexplorer/deploymentdata.h>
#include <projectexplorer/project.h>
#include <QStringList>
@@ -120,6 +121,9 @@ protected:
RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) final;
private:
+ ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override;
+ bool hasMakeInstallEquivalent() const override { return true; }
+
void asyncUpdate();
void buildFinished(bool success);
void activeTargetWasChanged();
diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp
index 82d5faf653..eea6758274 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.cpp
+++ b/src/plugins/qmlprojectmanager/qmlproject.cpp
@@ -347,6 +347,11 @@ Project::RestoreResult QmlProject::fromMap(const QVariantMap &map, QString *erro
return RestoreResult::Ok;
}
+ProjectExplorer::DeploymentKnowledge QmlProject::deploymentKnowledge() const
+{
+ return DeploymentKnowledge::Perfect;
+}
+
void QmlProject::generateProjectTree()
{
if (!m_projectItem)
diff --git a/src/plugins/qmlprojectmanager/qmlproject.h b/src/plugins/qmlprojectmanager/qmlproject.h
index 8f7bf30c04..67cc9127f9 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.h
+++ b/src/plugins/qmlprojectmanager/qmlproject.h
@@ -83,6 +83,8 @@ protected:
RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) override;
private:
+ ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override;
+
void generateProjectTree();
void updateDeploymentData(ProjectExplorer::Target *target);
void refreshFiles(const QSet<QString> &added, const QSet<QString> &removed);
diff --git a/src/plugins/remotelinux/genericdirectuploadstep.cpp b/src/plugins/remotelinux/genericdirectuploadstep.cpp
index a3f234685e..54b538ab45 100644
--- a/src/plugins/remotelinux/genericdirectuploadstep.cpp
+++ b/src/plugins/remotelinux/genericdirectuploadstep.cpp
@@ -73,7 +73,6 @@ GenericDirectUploadStep::~GenericDirectUploadStep()
bool GenericDirectUploadStep::initInternal(QString *error)
{
- d->deployService.setDeployableFiles(target()->deploymentData().allFiles());
d->deployService.setIncrementalDeployment(d->incrementalAspect->value());
d->deployService.setIgnoreMissingFiles(d->ignoreMissingFilesAspect->value());
return d->deployService.isDeploymentPossible(error);
@@ -84,6 +83,12 @@ GenericDirectUploadService *GenericDirectUploadStep::deployService() const
return &d->deployService;
}
+void GenericDirectUploadStep::doRun()
+{
+ d->deployService.setDeployableFiles(target()->deploymentData().allFiles());
+ AbstractRemoteLinuxDeployStep::doRun();
+}
+
Core::Id GenericDirectUploadStep::stepId()
{
return "RemoteLinux.DirectUploadStep";
diff --git a/src/plugins/remotelinux/genericdirectuploadstep.h b/src/plugins/remotelinux/genericdirectuploadstep.h
index 5751e833b6..a543134e36 100644
--- a/src/plugins/remotelinux/genericdirectuploadstep.h
+++ b/src/plugins/remotelinux/genericdirectuploadstep.h
@@ -47,6 +47,7 @@ public:
private:
GenericDirectUploadService *deployService() const override;
+ void doRun() override;
Internal::GenericDirectUploadStepPrivate *d;
};
diff --git a/src/plugins/remotelinux/makeinstallstep.cpp b/src/plugins/remotelinux/makeinstallstep.cpp
new file mode 100644
index 0000000000..2980ea5ad0
--- /dev/null
+++ b/src/plugins/remotelinux/makeinstallstep.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#include "makeinstallstep.h"
+
+#include <projectexplorer/buildsteplist.h>
+#include <projectexplorer/deployconfiguration.h>
+#include <projectexplorer/processparameters.h>
+#include <projectexplorer/runconfigurationaspects.h>
+#include <projectexplorer/target.h>
+#include <projectexplorer/task.h>
+#include <utils/fileutils.h>
+#include <utils/qtcassert.h>
+#include <utils/qtcprocess.h>
+
+#include <QDirIterator>
+#include <QFileInfo>
+#include <QFormLayout>
+#include <QTemporaryDir>
+
+using namespace ProjectExplorer;
+using namespace Utils;
+
+namespace RemoteLinux {
+namespace Internal {
+
+const char MakeAspectId[] = "RemoteLinux.MakeInstall.Make";
+const char InstallRootAspectId[] = "RemoteLinux.MakeInstall.InstallRoot";
+const char CleanInstallRootAspectId[] = "RemoteLinux.MakeInstall.CleanInstallRoot";
+const char FullCommandLineAspectId[] = "RemoteLinux.MakeInstall.FullCommandLine";
+
+MakeInstallStep::MakeInstallStep(BuildStepList *parent) : MakeStep(parent, stepId())
+{
+ setDefaultDisplayName(displayName());
+
+ const auto makeAspect = addAspect<ExecutableAspect>();
+ makeAspect->setId(MakeAspectId);
+ makeAspect->setSettingsKey(MakeAspectId);
+ makeAspect->setDisplayStyle(BaseStringAspect::PathChooserDisplay);
+ makeAspect->setLabelText(tr("Command:"));
+ connect(makeAspect, &ExecutableAspect::changed,
+ this, &MakeInstallStep::updateCommandFromAspect);
+
+ const auto installRootAspect = addAspect<BaseStringAspect>();
+ installRootAspect->setId(InstallRootAspectId);
+ installRootAspect->setSettingsKey(InstallRootAspectId);
+ installRootAspect->setDisplayStyle(BaseStringAspect::PathChooserDisplay);
+ installRootAspect->setExpectedKind(PathChooser::Directory);
+ installRootAspect->setLabelText(tr("Install root:"));
+ connect(installRootAspect, &BaseStringAspect::changed,
+ this, &MakeInstallStep::updateArgsFromAspect);
+
+ const auto cleanInstallRootAspect = addAspect<BaseBoolAspect>();
+ cleanInstallRootAspect->setId(CleanInstallRootAspectId);
+ cleanInstallRootAspect->setSettingsKey(CleanInstallRootAspectId);
+ cleanInstallRootAspect->setLabel(tr("Clean install root first"));
+ cleanInstallRootAspect->setValue(false);
+
+ const auto commandLineAspect = addAspect<BaseStringAspect>();
+ commandLineAspect->setId(FullCommandLineAspectId);
+ commandLineAspect->setDisplayStyle(BaseStringAspect::LabelDisplay);
+ commandLineAspect->setLabelText(tr("Full command line:"));
+
+ QTemporaryDir tmpDir;
+ installRootAspect->setFileName(FileName::fromString(tmpDir.path()));
+ const MakeInstallCommand cmd = target()->makeInstallCommand(tmpDir.path());
+ QTC_ASSERT(!cmd.command.isEmpty(), return);
+ makeAspect->setExecutable(cmd.command);
+}
+
+Core::Id MakeInstallStep::stepId()
+{
+ return "RemoteLinux.MakeInstall";
+}
+
+QString MakeInstallStep::displayName()
+{
+ return tr("Install into temporary host directory");
+}
+
+BuildStepConfigWidget *MakeInstallStep::createConfigWidget()
+{
+ return BuildStep::createConfigWidget();
+}
+
+bool MakeInstallStep::init()
+{
+ if (!MakeStep::init())
+ return false;
+ const QString rootDirPath = installRoot().toString();
+ if (rootDirPath.isEmpty()) {
+ emit addTask(Task(Task::Error, tr("You must provide an install root."), FileName(), -1,
+ Constants::TASK_CATEGORY_BUILDSYSTEM));
+ return false;
+ }
+ QDir rootDir(rootDirPath);
+ if (cleanInstallRoot() && !rootDir.removeRecursively()) {
+ emit addTask(Task(Task::Error, tr("The install root '%1' could not be cleaned.")
+ .arg(installRoot().toUserOutput()),
+ FileName(), -1, Constants::TASK_CATEGORY_BUILDSYSTEM));
+ return false;
+ }
+ if (!rootDir.exists() && !QDir::root().mkpath(rootDirPath)) {
+ emit addTask(Task(Task::Error, tr("The install root '%1' could not be created.")
+ .arg(installRoot().toUserOutput()),
+ FileName(), -1, Constants::TASK_CATEGORY_BUILDSYSTEM));
+ return false;
+ }
+ if (this == deployConfiguration()->stepList()->steps().last()) {
+ emit addTask(Task(Task::Warning, tr("The \"make install\" step should probably not be "
+ "last in the list of deploy steps. "
+ "Consider moving it up."), FileName(), -1,
+ Constants::TASK_CATEGORY_BUILDSYSTEM));
+ }
+ const MakeInstallCommand cmd = target()->makeInstallCommand(installRoot().toString());
+ if (cmd.environment.size() > 0) {
+ Environment env = processParameters()->environment();
+ for (auto it = cmd.environment.constBegin(); it != cmd.environment.constEnd(); ++it)
+ env.set(it.key(), it.value());
+ processParameters()->setEnvironment(env);
+ }
+ return true;
+}
+
+void MakeInstallStep::finish(bool success)
+{
+ if (success) {
+ m_deploymentData = DeploymentData();
+ m_deploymentData.setLocalInstallRoot(installRoot());
+ QDirIterator dit(installRoot().toString(), QDir::Files, QDirIterator::Subdirectories);
+ while (dit.hasNext()) {
+ dit.next();
+ const QFileInfo fi = dit.fileInfo();
+ m_deploymentData.addFile(fi.filePath(),
+ fi.dir().path().mid(installRoot().toString().length()));
+ }
+ target()->setDeploymentData(m_deploymentData);
+ }
+ MakeStep::finish(success);
+}
+
+FileName MakeInstallStep::installRoot() const
+{
+ return static_cast<BaseStringAspect *>(aspect(InstallRootAspectId))->fileName();
+}
+
+bool MakeInstallStep::cleanInstallRoot() const
+{
+ return static_cast<BaseBoolAspect *>(aspect(CleanInstallRootAspectId))->value();
+}
+
+void MakeInstallStep::updateCommandFromAspect()
+{
+ setMakeCommand(aspect<ExecutableAspect>()->executable().toString());
+ updateFullCommandLine();
+}
+
+void MakeInstallStep::updateArgsFromAspect()
+{
+ setUserArguments(QtcProcess::joinArgs(target()->makeInstallCommand(
+ static_cast<BaseStringAspect *>(aspect(InstallRootAspectId))->fileName().toString())
+ .arguments));
+ updateFullCommandLine();
+}
+
+void MakeInstallStep::updateFullCommandLine()
+{
+ static_cast<BaseStringAspect *>(aspect(FullCommandLineAspectId))->setValue(
+ QDir::toNativeSeparators(QtcProcess::quoteArg(effectiveMakeCommand()))
+ + ' ' + userArguments());
+}
+
+bool MakeInstallStep::fromMap(const QVariantMap &map)
+{
+ if (!MakeStep::fromMap(map))
+ return false;
+ updateCommandFromAspect();
+ updateArgsFromAspect();
+ return true;
+}
+
+} // namespace Internal
+} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/makeinstallstep.h b/src/plugins/remotelinux/makeinstallstep.h
new file mode 100644
index 0000000000..e9c4e9e25d
--- /dev/null
+++ b/src/plugins/remotelinux/makeinstallstep.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+****************************************************************************/
+
+#pragma once
+
+#include <projectexplorer/deploymentdata.h>
+#include <projectexplorer/makestep.h>
+
+namespace Utils { class FileName; }
+
+namespace RemoteLinux {
+namespace Internal {
+
+class MakeInstallStep : public ProjectExplorer::MakeStep
+{
+ Q_OBJECT
+public:
+ MakeInstallStep(ProjectExplorer::BuildStepList *parent);
+
+ static Core::Id stepId();
+ static QString displayName();
+
+private:
+ bool fromMap(const QVariantMap &map) override;
+ ProjectExplorer::BuildStepConfigWidget * createConfigWidget() override;
+ bool init() override;
+ void finish(bool success) override;
+
+ Utils::FileName installRoot() const;
+ bool cleanInstallRoot() const;
+
+ void updateCommandFromAspect();
+ void updateArgsFromAspect();
+ void updateFullCommandLine();
+
+ ProjectExplorer::DeploymentData m_deploymentData;
+};
+
+} // namespace Internal
+} // namespace RemoteLinux
diff --git a/src/plugins/remotelinux/remotelinux.pro b/src/plugins/remotelinux/remotelinux.pro
index 338461b28b..4ec8891937 100644
--- a/src/plugins/remotelinux/remotelinux.pro
+++ b/src/plugins/remotelinux/remotelinux.pro
@@ -4,6 +4,7 @@ include(../../qtcreatorplugin.pri)
HEADERS += \
embeddedlinuxqtversion.h \
+ makeinstallstep.h \
remotelinuxenvironmentaspect.h \
remotelinuxenvironmentaspectwidget.h \
remotelinuxplugin.h \
@@ -47,6 +48,7 @@ HEADERS += \
SOURCES += \
embeddedlinuxqtversion.cpp \
+ makeinstallstep.cpp \
remotelinuxenvironmentaspect.cpp \
remotelinuxenvironmentaspectwidget.cpp \
remotelinuxplugin.cpp \
diff --git a/src/plugins/remotelinux/remotelinux.qbs b/src/plugins/remotelinux/remotelinux.qbs
index f353997fdb..92e94b6549 100644
--- a/src/plugins/remotelinux/remotelinux.qbs
+++ b/src/plugins/remotelinux/remotelinux.qbs
@@ -47,6 +47,8 @@ Project {
"linuxdeviceprocess.h",
"linuxdevicetester.cpp",
"linuxdevicetester.h",
+ "makeinstallstep.cpp",
+ "makeinstallstep.h",
"packageuploader.cpp",
"packageuploader.h",
"publickeydeploymentdialog.cpp",
@@ -101,7 +103,7 @@ Project {
"typespecificdeviceconfigurationlistmodel.h",
"uploadandinstalltarpackagestep.cpp",
"uploadandinstalltarpackagestep.h",
- "images/embeddedtarget.png"
+ "images/embeddedtarget.png",
]
Export {
diff --git a/src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp b/src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp
index 5f2ad0b594..88cd76f66d 100644
--- a/src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp
+++ b/src/plugins/remotelinux/remotelinuxdeployconfiguration.cpp
@@ -27,6 +27,7 @@
#include "genericdirectuploadstep.h"
#include "linuxdevice.h"
+#include "makeinstallstep.h"
#include "remotelinuxcheckforfreediskspacestep.h"
#include "remotelinuxkillappstep.h"
#include "remotelinux_constants.h"
@@ -60,6 +61,11 @@ RemoteLinuxDeployConfigurationFactory::RemoteLinuxDeployConfigurationFactory()
"Deploy to Remote Linux Host"));
setUseDeploymentDataView();
+ addInitialStep(MakeInstallStep::stepId(), [](Target *target) {
+ const Project * const prj = target->project();
+ return prj->deploymentKnowledge() == DeploymentKnowledge::Bad
+ && prj->hasMakeInstallEquivalent();
+ });
addInitialStep(RemoteLinuxCheckForFreeDiskSpaceStep::stepId());
addInitialStep(RemoteLinuxKillAppStep::stepId());
addInitialStep(RsyncDeployStep::stepId(), [](Target *target) {
diff --git a/src/plugins/remotelinux/remotelinuxplugin.cpp b/src/plugins/remotelinux/remotelinuxplugin.cpp
index 00fbf0f9a0..1f25666cbf 100644
--- a/src/plugins/remotelinux/remotelinuxplugin.cpp
+++ b/src/plugins/remotelinux/remotelinuxplugin.cpp
@@ -35,6 +35,7 @@
#include "remotelinuxrunconfiguration.h"
#include "genericdirectuploadstep.h"
+#include "makeinstallstep.h"
#include "remotelinuxcheckforfreediskspacestep.h"
#include "remotelinuxdeployconfiguration.h"
#include "remotelinuxcustomcommanddeploymentstep.h"
@@ -80,6 +81,7 @@ public:
GenericDeployStepFactory<RemoteLinuxCheckForFreeDiskSpaceStep>
checkForFreeDiskSpaceStepFactory;
GenericDeployStepFactory<RemoteLinuxKillAppStep> remoteLinuxKillAppStepFactory;
+ GenericDeployStepFactory<MakeInstallStep> makeInstallStepFactory;
EmbeddedLinuxQtVersionFactory embeddedLinuxQtVersionFactory;
};
diff --git a/src/plugins/remotelinux/rsyncdeploystep.cpp b/src/plugins/remotelinux/rsyncdeploystep.cpp
index 96747de16c..7b872b5fa3 100644
--- a/src/plugins/remotelinux/rsyncdeploystep.cpp
+++ b/src/plugins/remotelinux/rsyncdeploystep.cpp
@@ -201,7 +201,6 @@ RsyncDeployStep::~RsyncDeployStep()
bool RsyncDeployStep::initInternal(QString *error)
{
- d->deployService.setDeployableFiles(target()->deploymentData().allFiles());
d->deployService.setIgnoreMissingFiles(d->ignoreMissingFilesAspect->value());
return d->deployService.isDeploymentPossible(error);
}
@@ -211,6 +210,12 @@ AbstractRemoteLinuxDeployService *RsyncDeployStep::deployService() const
return &d->deployService;
}
+void RsyncDeployStep::doRun()
+{
+ d->deployService.setDeployableFiles(target()->deploymentData().allFiles());
+ AbstractRemoteLinuxDeployStep::doRun();
+}
+
Core::Id RsyncDeployStep::stepId()
{
return "RemoteLinux.RsyncDeployStep";
diff --git a/src/plugins/remotelinux/rsyncdeploystep.h b/src/plugins/remotelinux/rsyncdeploystep.h
index ddc627e7dc..ec936f6e5e 100644
--- a/src/plugins/remotelinux/rsyncdeploystep.h
+++ b/src/plugins/remotelinux/rsyncdeploystep.h
@@ -55,6 +55,7 @@ public:
private:
AbstractRemoteLinuxDeployService *deployService() const override;
+ void doRun() override;
bool initInternal(QString *error = nullptr) override;