forked from qt-creator/qt-creator
Docker: Create a partial kit on device creation
Device, Toolchain, and Qt; no Debugger, cmake, ... Change-Id: Icca660aef62470dda638050fddb74fb1a3032af2 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -33,11 +33,14 @@
|
|||||||
#include <coreplugin/messagemanager.h>
|
#include <coreplugin/messagemanager.h>
|
||||||
|
|
||||||
#include <projectexplorer/devicesupport/idevicewidget.h>
|
#include <projectexplorer/devicesupport/idevicewidget.h>
|
||||||
|
#include <projectexplorer/kitinformation.h>
|
||||||
|
#include <projectexplorer/kitmanager.h>
|
||||||
#include <projectexplorer/runcontrol.h>
|
#include <projectexplorer/runcontrol.h>
|
||||||
#include <projectexplorer/toolchain.h>
|
#include <projectexplorer/toolchain.h>
|
||||||
#include <projectexplorer/toolchainmanager.h>
|
#include <projectexplorer/toolchainmanager.h>
|
||||||
|
|
||||||
#include <qtsupport/baseqtversion.h>
|
#include <qtsupport/baseqtversion.h>
|
||||||
|
#include <qtsupport/qtkitinformation.h>
|
||||||
#include <qtsupport/qtversionfactory.h>
|
#include <qtsupport/qtversionfactory.h>
|
||||||
#include <qtsupport/qtversionmanager.h>
|
#include <qtsupport/qtversionmanager.h>
|
||||||
|
|
||||||
@@ -268,7 +271,7 @@ IDeviceWidget *DockerDevice::createWidget()
|
|||||||
class DockerDevicePrivate : public QObject
|
class DockerDevicePrivate : public QObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DockerDevicePrivate()
|
DockerDevicePrivate(DockerDevice *parent) : q(parent)
|
||||||
{
|
{
|
||||||
connect(&m_mergedDirWatcher, &QFileSystemWatcher::fileChanged, this, [](const QString &path) {
|
connect(&m_mergedDirWatcher, &QFileSystemWatcher::fileChanged, this, [](const QString &path) {
|
||||||
Q_UNUSED(path)
|
Q_UNUSED(path)
|
||||||
@@ -284,6 +287,14 @@ public:
|
|||||||
|
|
||||||
int runSynchronously(const CommandLine &cmd) const;
|
int runSynchronously(const CommandLine &cmd) const;
|
||||||
|
|
||||||
|
void tryCreateLocalFileAccess();
|
||||||
|
|
||||||
|
void setupKit();
|
||||||
|
BaseQtVersion *autoDetectQtVersion() const;
|
||||||
|
QList<ToolChain *> autoDetectToolChains();
|
||||||
|
void autoDetectCMake();
|
||||||
|
|
||||||
|
DockerDevice *q;
|
||||||
DockerDeviceData m_data;
|
DockerDeviceData m_data;
|
||||||
|
|
||||||
// For local file access
|
// For local file access
|
||||||
@@ -294,7 +305,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
DockerDevice::DockerDevice(const DockerDeviceData &data)
|
DockerDevice::DockerDevice(const DockerDeviceData &data)
|
||||||
: d(new DockerDevicePrivate)
|
: d(new DockerDevicePrivate(this))
|
||||||
{
|
{
|
||||||
d->m_data = data;
|
d->m_data = data;
|
||||||
|
|
||||||
@@ -346,59 +357,97 @@ const DockerDeviceData &DockerDevice::data() const
|
|||||||
return d->m_data;
|
return d->m_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockerDevice::autoDetectQtVersion() const
|
BaseQtVersion *DockerDevicePrivate::autoDetectQtVersion() const
|
||||||
{
|
{
|
||||||
QString error;
|
QString error;
|
||||||
QString source = "docker:" + d->m_data.imageId;
|
QString source = "docker:" + m_data.imageId;
|
||||||
const QStringList candidates = {"/usr/local/bin/qmake", "/usr/bin/qmake"};
|
const QStringList candidates = {"/usr/local/bin/qmake", "/usr/bin/qmake"};
|
||||||
for (const QString &candidate : candidates) {
|
for (const QString &candidate : candidates) {
|
||||||
const FilePath qmake = mapToGlobalPath(FilePath::fromString(candidate));
|
const FilePath qmake = q->mapToGlobalPath(FilePath::fromString(candidate));
|
||||||
if (auto qtVersion = QtVersionFactory::createQtVersionFromQMakePath(qmake, false, source, &error)) {
|
if (auto qtVersion = QtVersionFactory::createQtVersionFromQMakePath(qmake, false, source, &error)) {
|
||||||
QtVersionManager::addVersion(qtVersion);
|
QtVersionManager::addVersion(qtVersion);
|
||||||
return;
|
return qtVersion;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockerDevice::autoDetectToolChains()
|
QList<ToolChain *> DockerDevicePrivate::autoDetectToolChains()
|
||||||
{
|
{
|
||||||
const QList<ToolChainFactory *> factories = ToolChainFactory::allToolChainFactories();
|
const QList<ToolChainFactory *> factories = ToolChainFactory::allToolChainFactories();
|
||||||
|
|
||||||
QList<ToolChain *> toolChains;
|
QList<ToolChain *> toolChains;
|
||||||
for (ToolChainFactory *factory : factories) {
|
for (ToolChainFactory *factory : factories) {
|
||||||
const QList<ToolChain *> newToolChains = factory->autoDetect(toolChains, sharedFromThis());
|
const QList<ToolChain *> newToolChains = factory->autoDetect(toolChains, q->sharedFromThis());
|
||||||
for (ToolChain *toolChain : newToolChains) {
|
for (ToolChain *toolChain : newToolChains) {
|
||||||
LOG("Found ToolChain: " << toolChain->compilerCommand().toUserOutput());
|
LOG("Found ToolChain: " << toolChain->compilerCommand().toUserOutput());
|
||||||
ToolChainManager::registerToolChain(toolChain);
|
ToolChainManager::registerToolChain(toolChain);
|
||||||
toolChains.append(toolChain);
|
toolChains.append(toolChain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return toolChains;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockerDevice::autoDetectCMake()
|
void DockerDevicePrivate::autoDetectCMake()
|
||||||
{
|
{
|
||||||
QObject *cmakeManager = ExtensionSystem::PluginManager::getObjectByName("CMakeToolManager");
|
QObject *cmakeManager = ExtensionSystem::PluginManager::getObjectByName("CMakeToolManager");
|
||||||
if (!cmakeManager)
|
if (!cmakeManager)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QString error;
|
QString error;
|
||||||
QString source = "docker:" + d->m_data.imageId;
|
QString source = "docker:" + m_data.imageId;
|
||||||
const QStringList candidates = {"/usr/local/bin/cmake", "/usr/bin/cmake"};
|
const QStringList candidates = {"/usr/local/bin/cmake", "/usr/bin/cmake"};
|
||||||
for (const QString &candidate : candidates) {
|
for (const QString &candidate : candidates) {
|
||||||
const FilePath cmake = mapToGlobalPath(FilePath::fromString(candidate));
|
const FilePath cmake = q->mapToGlobalPath(FilePath::fromString(candidate));
|
||||||
QTC_CHECK(hasLocalFileAccess());
|
QTC_CHECK(q->hasLocalFileAccess());
|
||||||
if (cmake.isExecutableFile()) {
|
if (cmake.isExecutableFile()) {
|
||||||
const bool res = QMetaObject::invokeMethod(cmakeManager,
|
const bool res = QMetaObject::invokeMethod(cmakeManager,
|
||||||
"registerCMakeByPath",
|
"registerCMakeByPath",
|
||||||
Q_ARG(Utils::FilePath, cmake));
|
Q_ARG(Utils::FilePath, cmake));
|
||||||
QTC_CHECK(res);
|
QTC_CHECK(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockerDevicePrivate::setupKit()
|
||||||
|
{
|
||||||
|
tryCreateLocalFileAccess();
|
||||||
|
|
||||||
|
QList<ToolChain *> toolChains = autoDetectToolChains();
|
||||||
|
|
||||||
|
BaseQtVersion *qt = autoDetectQtVersion();
|
||||||
|
|
||||||
|
autoDetectCMake();
|
||||||
|
|
||||||
|
const auto initializeKit = [this, toolChains, qt](Kit *k) {
|
||||||
|
k->setAutoDetected(false);
|
||||||
|
k->setAutoDetectionSource("DockerDevice:" + m_data.imageId);
|
||||||
|
k->setUnexpandedDisplayName("%{Device:Name}");
|
||||||
|
|
||||||
|
DeviceTypeKitAspect::setDeviceTypeId(k, Constants::DOCKER_DEVICE_TYPE);
|
||||||
|
DeviceKitAspect::setDevice(k, q->sharedFromThis());
|
||||||
|
for (ToolChain *tc : toolChains)
|
||||||
|
ToolChainKitAspect::setToolChain(k, tc);
|
||||||
|
QtSupport::QtKitAspect::setQtVersion(k, qt);
|
||||||
|
|
||||||
|
k->setSticky(ToolChainKitAspect::id(), true);
|
||||||
|
k->setSticky(QtSupport::QtKitAspect::id(), true);
|
||||||
|
k->setSticky(DeviceKitAspect::id(), true);
|
||||||
|
k->setSticky(DeviceTypeKitAspect::id(), true);
|
||||||
|
};
|
||||||
|
|
||||||
|
KitManager::registerKit(initializeKit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockerDevice::tryCreateLocalFileAccess() const
|
void DockerDevice::tryCreateLocalFileAccess() const
|
||||||
{
|
{
|
||||||
if (!d->m_container.isEmpty())
|
d->tryCreateLocalFileAccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockerDevicePrivate::tryCreateLocalFileAccess()
|
||||||
|
{
|
||||||
|
if (!m_container.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QString tempFileName;
|
QString tempFileName;
|
||||||
@@ -409,25 +458,25 @@ void DockerDevice::tryCreateLocalFileAccess() const
|
|||||||
tempFileName = temp.fileName();
|
tempFileName = temp.fileName();
|
||||||
}
|
}
|
||||||
|
|
||||||
d->m_shell = new QtcProcess;
|
m_shell = new QtcProcess;
|
||||||
// FIXME: Make mounts flexible
|
// FIXME: Make mounts flexible
|
||||||
d->m_shell->setCommand({"docker", {"run", "-i", "--cidfile=" + tempFileName,
|
m_shell->setCommand({"docker", {"run", "-i", "--cidfile=" + tempFileName,
|
||||||
"-v", "/opt:/opt",
|
"-v", "/opt:/opt",
|
||||||
"-v", "/data:/data",
|
"-v", "/data:/data",
|
||||||
"-e", "DISPLAY=:0",
|
"-e", "DISPLAY=:0",
|
||||||
"-e", "XAUTHORITY=/.Xauthority",
|
"-e", "XAUTHORITY=/.Xauthority",
|
||||||
"--net", "host",
|
"--net", "host",
|
||||||
d->m_data.imageId, "/bin/sh"}});
|
m_data.imageId, "/bin/sh"}});
|
||||||
LOG("RUNNING: " << d->m_shell->commandLine().toUserOutput());
|
LOG("RUNNING: " << m_shell->commandLine().toUserOutput());
|
||||||
d->m_shell->start();
|
m_shell->start();
|
||||||
d->m_shell->waitForStarted();
|
m_shell->waitForStarted();
|
||||||
|
|
||||||
LOG("CHECKING: " << tempFileName);
|
LOG("CHECKING: " << tempFileName);
|
||||||
for (int i = 0; i <= 10; ++i) {
|
for (int i = 0; i <= 10; ++i) {
|
||||||
QFile file(tempFileName);
|
QFile file(tempFileName);
|
||||||
file.open(QIODevice::ReadOnly);
|
file.open(QIODevice::ReadOnly);
|
||||||
d->m_container = QString::fromUtf8(file.readAll()).trimmed();
|
m_container = QString::fromUtf8(file.readAll()).trimmed();
|
||||||
if (!d->m_container.isEmpty()) {
|
if (!m_container.isEmpty()) {
|
||||||
LOG("Container: " << d->m_container);
|
LOG("Container: " << d->m_container);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -439,16 +488,16 @@ void DockerDevice::tryCreateLocalFileAccess() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
QtcProcess proc;
|
QtcProcess proc;
|
||||||
proc.setCommand({"docker", {"inspect", "--format={{.GraphDriver.Data.MergedDir}}", d->m_container}});
|
proc.setCommand({"docker", {"inspect", "--format={{.GraphDriver.Data.MergedDir}}", m_container}});
|
||||||
//LOG(proc2.commandLine().toUserOutput());
|
//LOG(proc2.commandLine().toUserOutput());
|
||||||
proc.start();
|
proc.start();
|
||||||
proc.waitForFinished();
|
proc.waitForFinished();
|
||||||
const QByteArray out = proc.readAllStandardOutput();
|
const QByteArray out = proc.readAllStandardOutput();
|
||||||
d->m_mergedDir = QString::fromUtf8(out).trimmed();
|
m_mergedDir = QString::fromUtf8(out).trimmed();
|
||||||
if (d->m_mergedDir.endsWith('/'))
|
if (m_mergedDir.endsWith('/'))
|
||||||
d->m_mergedDir.chop(1);
|
m_mergedDir.chop(1);
|
||||||
|
|
||||||
d->m_mergedDirWatcher.addPath(d->m_mergedDir);
|
m_mergedDirWatcher.addPath(m_mergedDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DockerDevice::hasLocalFileAccess() const
|
bool DockerDevice::hasLocalFileAccess() const
|
||||||
@@ -822,10 +871,7 @@ public:
|
|||||||
device->setType(Constants::DOCKER_DEVICE_TYPE);
|
device->setType(Constants::DOCKER_DEVICE_TYPE);
|
||||||
device->setMachineType(IDevice::Hardware);
|
device->setMachineType(IDevice::Hardware);
|
||||||
|
|
||||||
device->tryCreateLocalFileAccess();
|
device->d->setupKit();
|
||||||
device->autoDetectToolChains();
|
|
||||||
device->autoDetectQtVersion();
|
|
||||||
device->autoDetectCMake();
|
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -85,9 +85,6 @@ public:
|
|||||||
void runProcess(Utils::QtcProcess &process) const override;
|
void runProcess(Utils::QtcProcess &process) const override;
|
||||||
|
|
||||||
const DockerDeviceData &data() const;
|
const DockerDeviceData &data() const;
|
||||||
void autoDetectQtVersion() const;
|
|
||||||
void autoDetectToolChains();
|
|
||||||
void autoDetectCMake();
|
|
||||||
|
|
||||||
void tryCreateLocalFileAccess() const;
|
void tryCreateLocalFileAccess() const;
|
||||||
bool hasLocalFileAccess() const;
|
bool hasLocalFileAccess() const;
|
||||||
@@ -101,6 +98,7 @@ private:
|
|||||||
QVariantMap toMap() const final;
|
QVariantMap toMap() const final;
|
||||||
|
|
||||||
class DockerDevicePrivate *d = nullptr;
|
class DockerDevicePrivate *d = nullptr;
|
||||||
|
friend class DockerDeviceSetupWizard;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DockerDeviceFactory final : public ProjectExplorer::IDeviceFactory
|
class DockerDeviceFactory final : public ProjectExplorer::IDeviceFactory
|
||||||
|
Reference in New Issue
Block a user