2013-04-25 16:02:17 +02:00
|
|
|
/****************************************************************************
|
|
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2013-04-25 16:02:17 +02:00
|
|
|
**
|
|
|
|
|
** 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
|
2016-01-15 14:57:40 +01:00
|
|
|
** 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.
|
2013-04-25 16:02:17 +02:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** 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.
|
2013-04-25 16:02:17 +02:00
|
|
|
**
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "iosprobe.h"
|
2013-10-02 15:13:17 +02:00
|
|
|
|
2016-04-29 16:52:58 +02:00
|
|
|
#include <utils/synchronousprocess.h>
|
|
|
|
|
|
2013-04-25 16:02:17 +02:00
|
|
|
#include <QDir>
|
2014-08-26 15:53:13 +02:00
|
|
|
#include <QFileInfo>
|
2013-04-25 16:02:17 +02:00
|
|
|
#include <QFileInfoList>
|
2014-08-26 15:53:13 +02:00
|
|
|
#include <QLoggingCategory>
|
|
|
|
|
#include <QProcess>
|
|
|
|
|
|
2018-10-12 09:33:30 +03:00
|
|
|
static Q_LOGGING_CATEGORY(probeLog, "qtc.ios.probe", QtWarningMsg)
|
2013-04-25 16:02:17 +02:00
|
|
|
|
|
|
|
|
namespace Ios {
|
|
|
|
|
|
2017-05-24 23:26:35 -07:00
|
|
|
static QString defaultDeveloperPath = QLatin1String("/Applications/Xcode.app/Contents/Developer");
|
2013-04-25 16:02:17 +02:00
|
|
|
|
2017-05-24 23:26:35 -07:00
|
|
|
QMap<QString, XcodePlatform> XcodeProbe::detectPlatforms(const QString &devPath)
|
2013-04-25 16:02:17 +02:00
|
|
|
{
|
2017-05-24 23:26:35 -07:00
|
|
|
XcodeProbe probe;
|
2013-04-25 16:02:17 +02:00
|
|
|
probe.addDeveloperPath(devPath);
|
2013-10-07 20:14:54 +02:00
|
|
|
probe.detectFirst();
|
2013-04-25 16:02:17 +02:00
|
|
|
return probe.detectedPlatforms();
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-24 23:26:35 -07:00
|
|
|
void XcodeProbe::addDeveloperPath(const QString &path)
|
2013-04-25 16:02:17 +02:00
|
|
|
{
|
|
|
|
|
if (path.isEmpty())
|
2013-10-02 15:13:17 +02:00
|
|
|
return;
|
2013-04-25 16:02:17 +02:00
|
|
|
QFileInfo pInfo(path);
|
|
|
|
|
if (!pInfo.exists() || !pInfo.isDir())
|
2013-10-02 15:13:17 +02:00
|
|
|
return;
|
2013-04-25 16:02:17 +02:00
|
|
|
if (m_developerPaths.contains(path))
|
2013-10-02 15:13:17 +02:00
|
|
|
return;
|
2013-04-25 16:02:17 +02:00
|
|
|
m_developerPaths.append(path);
|
2014-07-07 09:24:17 +02:00
|
|
|
qCDebug(probeLog) << QString::fromLatin1("Added developer path %1").arg(path);
|
2013-04-25 16:02:17 +02:00
|
|
|
}
|
|
|
|
|
|
2017-05-24 23:26:35 -07:00
|
|
|
void XcodeProbe::detectDeveloperPaths()
|
2013-04-25 16:02:17 +02:00
|
|
|
{
|
2016-04-29 16:52:58 +02:00
|
|
|
Utils::SynchronousProcess selectedXcode;
|
|
|
|
|
selectedXcode.setTimeoutS(5);
|
2017-05-24 23:26:35 -07:00
|
|
|
Utils::SynchronousProcessResponse response = selectedXcode.run(
|
|
|
|
|
QLatin1String("/usr/bin/xcode-select"), QStringList("--print-path"));
|
|
|
|
|
if (response.result != Utils::SynchronousProcessResponse::Finished)
|
|
|
|
|
qCWarning(probeLog)
|
|
|
|
|
<< QString::fromLatin1("Could not detect selected Xcode using xcode-select");
|
|
|
|
|
else
|
|
|
|
|
addDeveloperPath(response.stdOut().trimmed());
|
|
|
|
|
addDeveloperPath(defaultDeveloperPath);
|
2013-04-25 16:02:17 +02:00
|
|
|
}
|
|
|
|
|
|
2017-05-24 23:26:35 -07:00
|
|
|
void XcodeProbe::setupDefaultToolchains(const QString &devPath)
|
2013-04-25 16:02:17 +02:00
|
|
|
{
|
2017-05-24 23:26:35 -07:00
|
|
|
auto getClangInfo = [devPath](const QString &compiler) {
|
2016-11-16 14:59:10 +01:00
|
|
|
QFileInfo compilerInfo(devPath
|
|
|
|
|
+ QLatin1String("/Toolchains/XcodeDefault.xctoolchain/usr/bin/")
|
|
|
|
|
+ compiler);
|
|
|
|
|
if (!compilerInfo.exists())
|
2017-05-24 23:26:35 -07:00
|
|
|
qCWarning(probeLog) << QString::fromLatin1("Default toolchain %1 not found.")
|
2016-11-16 14:59:10 +01:00
|
|
|
.arg(compilerInfo.canonicalFilePath());
|
|
|
|
|
return compilerInfo;
|
|
|
|
|
};
|
|
|
|
|
|
2017-05-24 23:26:35 -07:00
|
|
|
XcodePlatform clangProfile;
|
|
|
|
|
clangProfile.developerPath = Utils::FileName::fromString(devPath);
|
2016-11-16 14:59:10 +01:00
|
|
|
|
|
|
|
|
const QFileInfo clangCInfo = getClangInfo("clang");
|
2017-05-24 23:26:35 -07:00
|
|
|
if (clangCInfo.exists())
|
|
|
|
|
clangProfile.cCompilerPath = Utils::FileName(clangCInfo);
|
2016-11-16 14:59:10 +01:00
|
|
|
|
2017-05-24 23:26:35 -07:00
|
|
|
const QFileInfo clangCppInfo = getClangInfo("clang++");
|
|
|
|
|
if (clangCppInfo.exists())
|
|
|
|
|
clangProfile.cxxCompilerPath = Utils::FileName(clangCppInfo);
|
|
|
|
|
|
|
|
|
|
QSet<QString> allArchitectures;
|
|
|
|
|
static const std::map<QString, QStringList> sdkConfigs {
|
|
|
|
|
{QLatin1String("AppleTVOS"), QStringList("arm64")},
|
|
|
|
|
{QLatin1String("AppleTVSimulator"), QStringList("x86_64")},
|
|
|
|
|
{QLatin1String("iPhoneOS"), QStringList { QLatin1String("arm64"), QLatin1String("armv7") }},
|
|
|
|
|
{QLatin1String("iPhoneSimulator"), QStringList { QLatin1String("x86_64"),
|
|
|
|
|
QLatin1String("i386") }},
|
|
|
|
|
{QLatin1String("MacOSX"), QStringList { QLatin1String("x86_64"), QLatin1String("i386") }},
|
|
|
|
|
{QLatin1String("WatchOS"), QStringList("armv7k")},
|
|
|
|
|
{QLatin1String("WatchSimulator"), QStringList("i386")}
|
|
|
|
|
};
|
|
|
|
|
for (const auto &sdkConfig : sdkConfigs) {
|
|
|
|
|
XcodePlatform::SDK sdk;
|
|
|
|
|
sdk.directoryName = sdkConfig.first;
|
|
|
|
|
sdk.path = Utils::FileName::fromString(devPath
|
|
|
|
|
+ QString(QLatin1String("/Platforms/%1.platform/Developer/SDKs/%1.sdk")).arg(
|
|
|
|
|
sdk.directoryName));
|
|
|
|
|
sdk.architectures = sdkConfig.second;
|
|
|
|
|
const QFileInfo sdkPathInfo(sdk.path.toString());
|
|
|
|
|
if (sdkPathInfo.exists() && sdkPathInfo.isDir()) {
|
|
|
|
|
clangProfile.sdks.push_back(sdk);
|
|
|
|
|
allArchitectures += sdk.architectures.toSet();
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-11-16 14:59:10 +01:00
|
|
|
|
2017-05-24 23:26:35 -07:00
|
|
|
if (!clangProfile.cCompilerPath.isEmpty() || !clangProfile.cxxCompilerPath.isEmpty()) {
|
|
|
|
|
for (const QString &arch : allArchitectures) {
|
|
|
|
|
const QString clangFullName = QString(QLatin1String("Apple Clang (%1)")).arg(arch)
|
|
|
|
|
+ ((devPath != defaultDeveloperPath)
|
|
|
|
|
? QString(QLatin1String(" in %1")).arg(devPath)
|
|
|
|
|
: QString());
|
|
|
|
|
|
|
|
|
|
XcodePlatform::ToolchainTarget target;
|
|
|
|
|
target.name = clangFullName;
|
|
|
|
|
target.architecture = arch;
|
|
|
|
|
target.backendFlags = QStringList { QLatin1String("-arch"), arch };
|
|
|
|
|
clangProfile.targets.push_back(target);
|
2013-04-25 16:02:17 +02:00
|
|
|
}
|
|
|
|
|
}
|
2017-05-24 23:26:35 -07:00
|
|
|
|
|
|
|
|
m_platforms[devPath] = clangProfile;
|
2013-04-25 16:02:17 +02:00
|
|
|
}
|
|
|
|
|
|
2017-05-24 23:26:35 -07:00
|
|
|
void XcodeProbe::detectFirst()
|
2013-04-25 16:02:17 +02:00
|
|
|
{
|
|
|
|
|
detectDeveloperPaths();
|
2013-10-07 20:14:54 +02:00
|
|
|
if (!m_developerPaths.isEmpty())
|
2017-05-24 23:26:35 -07:00
|
|
|
setupDefaultToolchains(m_developerPaths.first());
|
2013-04-25 16:02:17 +02:00
|
|
|
}
|
|
|
|
|
|
2017-05-24 23:26:35 -07:00
|
|
|
QMap<QString, XcodePlatform> XcodeProbe::detectedPlatforms()
|
2013-04-25 16:02:17 +02:00
|
|
|
{
|
|
|
|
|
return m_platforms;
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-24 23:26:35 -07:00
|
|
|
bool XcodePlatform::operator==(const XcodePlatform &other) const
|
|
|
|
|
{
|
|
|
|
|
return developerPath == other.developerPath;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint qHash(const XcodePlatform &platform)
|
2015-10-09 09:50:07 +02:00
|
|
|
{
|
2017-05-24 23:26:35 -07:00
|
|
|
return qHash(platform.developerPath);
|
2015-10-09 09:50:07 +02:00
|
|
|
}
|
|
|
|
|
|
2017-05-24 23:26:35 -07:00
|
|
|
uint qHash(const XcodePlatform::ToolchainTarget &target)
|
2015-10-09 09:50:07 +02:00
|
|
|
{
|
2017-05-24 23:26:35 -07:00
|
|
|
return qHash(target.name);
|
2015-10-09 09:50:07 +02:00
|
|
|
}
|
|
|
|
|
|
2017-05-24 23:26:35 -07:00
|
|
|
bool XcodePlatform::ToolchainTarget::operator==(const XcodePlatform::ToolchainTarget &other) const
|
2015-10-09 09:50:07 +02:00
|
|
|
{
|
2017-05-24 23:26:35 -07:00
|
|
|
return architecture == other.architecture;
|
2015-10-09 09:50:07 +02:00
|
|
|
}
|
|
|
|
|
|
2013-04-25 16:02:17 +02:00
|
|
|
}
|