Commit 0784dd20 authored by Jake Petroules's avatar Jake Petroules

Refactor iOS toolchain handling

This significantly simplifies the implementation, properly handles
C vs C++ compilers, and defaults to 64-bit architectures for iOS devices
and simulators.

LLVM-GCC support has been removed, as the last version to support it was
4.6.3, which is far below the version of Xcode we still intend to
support. The toolchains are also given more sensible names
("Apple Clang") instead of iphonesimulator-clang and iphoneos-clang, as
the there is now only one compiler for all Apple platform targets, and
there is one entry of the Apple Clang compiler per supported
architecture.

The different to the end user is minimal except that the compilers are
named better. The number of kits and their configurations remain the
same, but this patch paves the way for tvOS and watchOS support.

Change-Id: I6e2b17f8c17d9dd504f0ad540e08782f291b73c0
Reviewed-by: Vikas Pachdha's avatarVikas Pachdha <vikas.pachdha@qt.io>
parent 232f6a10
......@@ -93,32 +93,18 @@ const char profileTeamIdTag[] = "TeamIdentifier";
static const QString xcodePlistPath = QDir::homePath() + "/Library/Preferences/com.apple.dt.Xcode.plist";
static const QString provisioningProfileDirPath = QDir::homePath() + "/Library/MobileDevice/Provisioning Profiles";
static Core::Id deviceId(const Platform &platform)
static Core::Id deviceId(const QString &sdkName)
{
if (platform.name.startsWith(QLatin1String("iphoneos-")))
if (sdkName.toLower().startsWith(QLatin1String("iphoneos")))
return Constants::IOS_DEVICE_TYPE;
else if (platform.name.startsWith(QLatin1String("iphonesimulator-")))
else if (sdkName.toLower().startsWith(QLatin1String("iphonesimulator")))
return Constants::IOS_SIMULATOR_TYPE;
return Core::Id();
}
static bool handledPlatform(const Platform &platform)
static bool isSimulatorDeviceId(const Core::Id &id)
{
// do not want platforms that
// - are not iphone (e.g. watchos)
// - are not base
// - are C++11
// - are not clang
return deviceId(platform).isValid()
&& (platform.platformKind & Platform::BasePlatform) != 0
&& (platform.platformKind & Platform::Cxx11Support) == 0
&& platform.type == Platform::CLang;
}
static QList<Platform> handledPlatforms()
{
QList<Platform> platforms = IosProbe::detectPlatforms().values();
return Utils::filtered(platforms, handledPlatform);
return id == Constants::IOS_SIMULATOR_TYPE;
}
static QList<ClangToolChain *> clangToolChains(const QList<ToolChain *> &toolChains)
......@@ -135,11 +121,14 @@ static QList<ClangToolChain *> autoDetectedIosToolChains()
const QList<ClangToolChain *> toolChains = clangToolChains(ToolChainManager::toolChains());
return Utils::filtered(toolChains, [](ClangToolChain *toolChain) {
return toolChain->isAutoDetected()
&& toolChain->displayName().startsWith(QLatin1String("iphone")); // TODO tool chains should be marked directly
&& (toolChain->displayName().startsWith(QLatin1String("iphone"))
|| toolChain->displayName().startsWith(QLatin1String("Apple Clang"))); // TODO tool chains should be marked directly
});
}
static ToolChainPair findToolChainForPlatform(const Platform &platform, const QList<ClangToolChain *> &toolChains)
static ToolChainPair findToolChainForPlatform(const XcodePlatform &platform,
const XcodePlatform::ToolchainTarget &target,
const QList<ClangToolChain *> &toolChains)
{
ToolChainPair platformToolChains;
auto toolchainMatch = [](ClangToolChain *toolChain, const Utils::FileName &compilerPath, const QStringList &flags) {
......@@ -149,48 +138,28 @@ static ToolChainPair findToolChainForPlatform(const Platform &platform, const QL
};
platformToolChains.first = Utils::findOrDefault(toolChains, std::bind(toolchainMatch, std::placeholders::_1,
platform.cCompilerPath,
platform.backendFlags));
target.backendFlags));
platformToolChains.second = Utils::findOrDefault(toolChains, std::bind(toolchainMatch, std::placeholders::_1,
platform.cxxCompilerPath,
platform.backendFlags));
target.backendFlags));
return platformToolChains;
}
static QHash<Platform, ToolChainPair> findToolChains(const QList<Platform> &platforms)
static QHash<XcodePlatform::ToolchainTarget, ToolChainPair> findToolChains(const QList<XcodePlatform> &platforms)
{
QHash<Platform, ToolChainPair> platformToolChainHash;
QHash<XcodePlatform::ToolchainTarget, ToolChainPair> platformToolChainHash;
const QList<ClangToolChain *> toolChains = autoDetectedIosToolChains();
foreach (const Platform &platform, platforms) {
ToolChainPair platformToolchains = findToolChainForPlatform(platform, toolChains);
if (platformToolchains.first || platformToolchains.second)
platformToolChainHash.insert(platform, platformToolchains);
for (const XcodePlatform &platform : platforms) {
for (const XcodePlatform::ToolchainTarget &target : platform.targets) {
ToolChainPair platformToolchains = findToolChainForPlatform(platform, target,
toolChains);
if (platformToolchains.first || platformToolchains.second)
platformToolChainHash.insert(target, platformToolchains);
}
}
return platformToolChainHash;
}
static QHash<Abi::Architecture, QSet<BaseQtVersion *>> iosQtVersions()
{
const QList<BaseQtVersion *> iosVersions
= QtVersionManager::versions([](const BaseQtVersion *v) {
return v->isValid() && v->type() == Constants::IOSQT;
});
QHash<Abi::Architecture, QSet<BaseQtVersion *>> versions;
foreach (BaseQtVersion *qtVersion, iosVersions) {
foreach (const Abi &abi, qtVersion->qtAbis())
versions[abi.architecture()].insert(qtVersion);
}
return versions;
}
static void printQtVersions(const QHash<Abi::Architecture, QSet<BaseQtVersion *> > &map)
{
foreach (const Abi::Architecture &arch, map.keys()) {
qCDebug(kitSetupLog) << "-" << Abi::toString(arch);
foreach (const BaseQtVersion *version, map.value(arch))
qCDebug(kitSetupLog) << " -" << version->displayName() << version;
}
}
static QSet<Kit *> existingAutoDetectedIosKits()
{
return Utils::filtered(KitManager::kits(), [](Kit *kit) -> bool {
......@@ -281,18 +250,17 @@ static QByteArray decodeProvisioningProfile(const QString &path)
void IosConfigurations::updateAutomaticKitList()
{
const QList<Platform> platforms = handledPlatforms();
qCDebug(kitSetupLog) << "Used platforms:" << platforms;
const QList<XcodePlatform> platforms = XcodeProbe::detectPlatforms().values();
if (!platforms.isEmpty())
setDeveloperPath(platforms.first().developerPath);
qCDebug(kitSetupLog) << "Developer path:" << developerPath();
// platform name -> tool chain
const QHash<Platform, ToolChainPair> platformToolChainHash = findToolChains(platforms);
// target -> tool chain
const auto targetToolChainHash = findToolChains(platforms);
const QHash<Abi::Architecture, QSet<BaseQtVersion *> > qtVersionsForArch = iosQtVersions();
qCDebug(kitSetupLog) << "iOS Qt versions:";
printQtVersions(qtVersionsForArch);
const auto qtVersions = QtVersionManager::versions([](const BaseQtVersion *v) {
return v->isValid() && v->type() == Constants::IOSQT;
}).toSet();
const DebuggerItem *possibleDebugger = DebuggerItemManager::findByEngineType(LldbEngineType);
const QVariant debuggerId = (possibleDebugger ? possibleDebugger->id() : QVariant());
......@@ -301,48 +269,56 @@ void IosConfigurations::updateAutomaticKitList()
qCDebug(kitSetupLog) << "Existing auto-detected iOS kits:";
printKits(existingKits);
QSet<Kit *> resultingKits;
// match existing kits and create missing kits
foreach (const Platform &platform, platforms) {
qCDebug(kitSetupLog) << "Guaranteeing kits for " << platform.name ;
const ToolChainPair &platformToolchains = platformToolChainHash.value(platform);
if (!platformToolchains.first && !platformToolchains.second) {
qCDebug(kitSetupLog) << " - No tool chain found";
continue;
}
Core::Id pDeviceType = deviceId(platform);
QTC_ASSERT(pDeviceType.isValid(), continue);
Abi::Architecture arch = platformToolchains.second ? platformToolchains.second->targetAbi().architecture() :
platformToolchains.first->targetAbi().architecture();
QSet<BaseQtVersion *> qtVersions = qtVersionsForArch.value(arch);
foreach (BaseQtVersion *qtVersion, qtVersions) {
qCDebug(kitSetupLog) << " - Qt version:" << qtVersion->displayName();
Kit *kit = Utils::findOrDefault(existingKits, [&pDeviceType, &platformToolchains, &qtVersion](const Kit *kit) {
// we do not compare the sdk (thus automatically upgrading it in place if a
// new Xcode is used). Change?
return DeviceTypeKitInformation::deviceTypeId(kit) == pDeviceType
&& ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID) == platformToolchains.second
&& ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::C_LANGUAGE_ID) == platformToolchains.first
&& QtKitInformation::qtVersion(kit) == qtVersion;
for (const XcodePlatform &platform : platforms) {
for (const auto &sdk : platform.sdks) {
const auto targets = Utils::filtered(platform.targets,
[&sdk](const XcodePlatform::ToolchainTarget &target) {
return sdk.architectures.first() == target.architecture;
});
QTC_ASSERT(!resultingKits.contains(kit), continue);
if (kit) {
qCDebug(kitSetupLog) << " - Kit matches:" << kit->displayName();
kit->blockNotification();
setupKit(kit, pDeviceType, platformToolchains, debuggerId, platform.sdkPath, qtVersion);
kit->unblockNotification();
} else {
qCDebug(kitSetupLog) << " - Setting up new kit";
kit = new Kit;
kit->blockNotification();
kit->setAutoDetected(true);
const QString baseDisplayName = tr("%1 %2").arg(platform.name, qtVersion->unexpandedDisplayName());
kit->setUnexpandedDisplayName(baseDisplayName);
setupKit(kit, pDeviceType, platformToolchains, debuggerId, platform.sdkPath, qtVersion);
kit->unblockNotification();
KitManager::registerKit(kit);
if (targets.empty())
continue;
const auto target = targets.front();
const ToolChainPair &platformToolchains = targetToolChainHash.value(target);
if (!platformToolchains.first && !platformToolchains.second) {
qCDebug(kitSetupLog) << " - No tool chain found";
continue;
}
Core::Id pDeviceType = deviceId(sdk.directoryName);
QTC_ASSERT(pDeviceType.isValid(), continue);
for (BaseQtVersion *qtVersion : qtVersions) {
qCDebug(kitSetupLog) << " - Qt version:" << qtVersion->displayName();
Kit *kit = Utils::findOrDefault(existingKits, [&pDeviceType, &platformToolchains, &qtVersion](const Kit *kit) {
// we do not compare the sdk (thus automatically upgrading it in place if a
// new Xcode is used). Change?
return DeviceTypeKitInformation::deviceTypeId(kit) == pDeviceType
&& ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID) == platformToolchains.second
&& ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::C_LANGUAGE_ID) == platformToolchains.first
&& QtKitInformation::qtVersion(kit) == qtVersion;
});
QTC_ASSERT(!resultingKits.contains(kit), continue);
if (kit) {
qCDebug(kitSetupLog) << " - Kit matches:" << kit->displayName();
kit->blockNotification();
setupKit(kit, pDeviceType, platformToolchains, debuggerId, sdk.path, qtVersion);
kit->unblockNotification();
} else {
qCDebug(kitSetupLog) << " - Setting up new kit";
kit = new Kit;
kit->blockNotification();
kit->setAutoDetected(true);
const QString baseDisplayName = isSimulatorDeviceId(pDeviceType)
? tr("%1 Simulator").arg(qtVersion->unexpandedDisplayName())
: qtVersion->unexpandedDisplayName();
kit->setUnexpandedDisplayName(baseDisplayName);
setupKit(kit, pDeviceType, platformToolchains, debuggerId, sdk.path, qtVersion);
kit->unblockNotification();
KitManager::registerKit(kit);
}
resultingKits.insert(kit);
}
resultingKits.insert(kit);
}
}
// remove unused kits
......@@ -574,7 +550,9 @@ ProvisioningProfilePtr IosConfigurations::provisioningProfile(const QString &pro
Utils::equal(&ProvisioningProfile::identifier, profileID));
}
static ClangToolChain *createToolChain(const Platform &platform, Core::Id l)
static ClangToolChain *createToolChain(const XcodePlatform &platform,
const XcodePlatform::ToolchainTarget &target,
Core::Id l)
{
if (!l.isValid())
return nullptr;
......@@ -585,37 +563,44 @@ static ClangToolChain *createToolChain(const Platform &platform, Core::Id l)
ClangToolChain *toolChain = new ClangToolChain(ToolChain::AutoDetection);
toolChain->setLanguage(l);
toolChain->setDisplayName(l == Core::Id(ProjectExplorer::Constants::CXX_LANGUAGE_ID) ? platform.name + "++" : platform.name);
toolChain->setPlatformCodeGenFlags(platform.backendFlags);
toolChain->setPlatformLinkerFlags(platform.backendFlags);
toolChain->setDisplayName(target.name);
toolChain->setPlatformCodeGenFlags(target.backendFlags);
toolChain->setPlatformLinkerFlags(target.backendFlags);
toolChain->resetToolChain(l == Core::Id(ProjectExplorer::Constants::CXX_LANGUAGE_ID) ?
platform.cxxCompilerPath : platform.cCompilerPath);
return toolChain;
}
QSet<Core::Id> IosToolChainFactory::supportedLanguages() const
{
return {ProjectExplorer::Constants::CXX_LANGUAGE_ID};
return {
ProjectExplorer::Constants::C_LANGUAGE_ID,
ProjectExplorer::Constants::CXX_LANGUAGE_ID
};
}
QList<ToolChain *> IosToolChainFactory::autoDetect(const QList<ToolChain *> &existingToolChains)
{
QList<ClangToolChain *> existingClangToolChains = clangToolChains(existingToolChains);
const QList<Platform> platforms = handledPlatforms();
const QList<XcodePlatform> platforms = XcodeProbe::detectPlatforms().values();
QList<ClangToolChain *> toolChains;
toolChains.reserve(platforms.size());
foreach (const Platform &platform, platforms) {
ToolChainPair platformToolchains = findToolChainForPlatform(platform, existingClangToolChains);
auto createOrAdd = [&](ClangToolChain* toolChain, Core::Id l) {
if (!toolChain) {
toolChain = createToolChain(platform, l);
existingClangToolChains.append(toolChain);
}
toolChains.append(toolChain);
};
foreach (const XcodePlatform &platform, platforms) {
for (const XcodePlatform::ToolchainTarget &target : platform.targets) {
ToolChainPair platformToolchains = findToolChainForPlatform(platform, target,
existingClangToolChains);
auto createOrAdd = [&](ClangToolChain* toolChain, Core::Id l) {
if (!toolChain) {
toolChain = createToolChain(platform, target, l);
existingClangToolChains.append(toolChain);
}
toolChains.append(toolChain);
};
createOrAdd(platformToolchains.first, ProjectExplorer::Constants::C_LANGUAGE_ID);
createOrAdd(platformToolchains.second, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
createOrAdd(platformToolchains.first, ProjectExplorer::Constants::C_LANGUAGE_ID);
createOrAdd(platformToolchains.second, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
}
}
return Utils::transform(toolChains, [](ClangToolChain *tc) -> ToolChain * { return tc; });
}
......
......@@ -37,50 +37,17 @@ static Q_LOGGING_CATEGORY(probeLog, "qtc.ios.probe")
namespace Ios {
static QString qsystem(const QString &exe, const QStringList &args = QStringList())
{
QProcess p;
p.setProcessChannelMode(QProcess::MergedChannels);
p.start(exe, args);
p.waitForFinished();
return QString::fromLocal8Bit(p.readAll());
}
static QString defaultDeveloperPath = QLatin1String("/Applications/Xcode.app/Contents/Developer");
QMap<QString, Platform> IosProbe::detectPlatforms(const QString &devPath)
QMap<QString, XcodePlatform> XcodeProbe::detectPlatforms(const QString &devPath)
{
IosProbe probe;
XcodeProbe probe;
probe.addDeveloperPath(devPath);
probe.detectFirst();
return probe.detectedPlatforms();
}
static int compareVersions(const QString &v1, const QString &v2)
{
QStringList v1L = v1.split(QLatin1Char('.'));
QStringList v2L = v2.split(QLatin1Char('.'));
int i = 0;
while (v1L.length() > i && v2L.length() > i) {
bool n1Ok, n2Ok;
int n1 = v1L.value(i).toInt(&n1Ok);
int n2 = v2L.value(i).toInt(&n2Ok);
if (!(n1Ok && n2Ok)) {
qCWarning(probeLog) << QString::fromLatin1("Failed to compare version %1 and %2").arg(v1, v2);
return 0;
}
if (n1 > n2)
return -1;
else if (n1 < n2)
return 1;
++i;
}
if (v1L.length() > v2L.length())
return -1;
if (v1L.length() < v2L.length())
return 1;
return 0;
}
void IosProbe::addDeveloperPath(const QString &path)
void XcodeProbe::addDeveloperPath(const QString &path)
{
if (path.isEmpty())
return;
......@@ -93,252 +60,116 @@ void IosProbe::addDeveloperPath(const QString &path)
qCDebug(probeLog) << QString::fromLatin1("Added developer path %1").arg(path);
}
void IosProbe::detectDeveloperPaths()
void XcodeProbe::detectDeveloperPaths()
{
QString program = QLatin1String("/usr/bin/xcode-select");
QStringList arguments(QLatin1String("--print-path"));
Utils::SynchronousProcess selectedXcode;
selectedXcode.setTimeoutS(5);
Utils::SynchronousProcessResponse response = selectedXcode.run(program, arguments);
if (response.result != Utils::SynchronousProcessResponse::Finished) {
qCWarning(probeLog) << QString::fromLatin1("Could not detect selected xcode with /usr/bin/xcode-select");
} else {
QString path = response.stdOut();
path.chop(1);
addDeveloperPath(path);
}
addDeveloperPath(QLatin1String("/Applications/Xcode.app/Contents/Developer"));
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);
}
void IosProbe::setupDefaultToolchains(const QString &devPath, const QString &xcodeName)
void XcodeProbe::setupDefaultToolchains(const QString &devPath)
{
qCDebug(probeLog) << QString::fromLatin1("Setting up platform \"%1\".").arg(xcodeName);
QString indent = QLatin1String(" ");
auto getClangInfo = [devPath, indent](const QString &compiler) {
auto getClangInfo = [devPath](const QString &compiler) {
QFileInfo compilerInfo(devPath
+ QLatin1String("/Toolchains/XcodeDefault.xctoolchain/usr/bin/")
+ compiler);
if (!compilerInfo.exists())
qCWarning(probeLog) << indent << QString::fromLatin1("Default toolchain %1 not found.")
qCWarning(probeLog) << QString::fromLatin1("Default toolchain %1 not found.")
.arg(compilerInfo.canonicalFilePath());
return compilerInfo;
};
// detect clang (default toolchain)
const QFileInfo clangCppInfo = getClangInfo("clang++");
const bool hasClangCpp = clangCppInfo.exists();
XcodePlatform clangProfile;
clangProfile.developerPath = Utils::FileName::fromString(devPath);
const QFileInfo clangCInfo = getClangInfo("clang");
const bool hasClangC = clangCInfo.exists();
// Platforms
const QDir platformsDir(devPath + QLatin1String("/Platforms"));
const QFileInfoList platforms = platformsDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
foreach (const QFileInfo &fInfo, platforms) {
if (fInfo.isDir() && fInfo.suffix() == QLatin1String("platform")) {
qCDebug(probeLog) << indent << QString::fromLatin1("Setting up %1").arg(fInfo.fileName());
QSettings infoSettings(fInfo.absoluteFilePath() + QLatin1String("/Info.plist"),
QSettings::NativeFormat);
if (!infoSettings.contains(QLatin1String("Name"))) {
qCWarning(probeLog) << indent << QString::fromLatin1("Missing platform name in Info.plist of %1")
.arg(fInfo.absoluteFilePath());
continue;
}
QString name = infoSettings.value(QLatin1String("Name")).toString();
if (name != QLatin1String("macosx") && name != QLatin1String("iphoneos")
&& name != QLatin1String("iphonesimulator"))
{
qCDebug(probeLog) << indent << QString::fromLatin1("Skipping unknown platform %1").arg(name);
continue;
}
const QString platformSdkVersion = infoSettings.value(QLatin1String("Version")).toString();
// prepare default platform properties
QVariantMap defaultProp = infoSettings.value(QLatin1String("DefaultProperties"))
.toMap();
QVariantMap overrideProp = infoSettings.value(QLatin1String("OverrideProperties"))
.toMap();
QMapIterator<QString, QVariant> i(overrideProp);
while (i.hasNext()) {
i.next();
// use unite? might lead to double insertions...
defaultProp[i.key()] = i.value();
}
const QString clangFullName = name + QLatin1String("-clang") + xcodeName;
const QString clang11FullName = name + QLatin1String("-clang11") + xcodeName;
// detect gcc
QFileInfo gccCppInfo(fInfo.absoluteFilePath() + QLatin1String("/Developer/usr/bin/g++"));
if (!gccCppInfo.exists())
gccCppInfo = QFileInfo(devPath + QLatin1String("/usr/bin/g++"));
const bool hasGccCppCompiler = gccCppInfo.exists();
if (clangCInfo.exists())
clangProfile.cCompilerPath = Utils::FileName(clangCInfo);
QFileInfo gccCInfo(fInfo.absoluteFilePath() + QLatin1String("/Developer/usr/bin/gcc"));
if (!gccCInfo.exists())
gccCInfo = QFileInfo(devPath + QLatin1String("/usr/bin/gcc"));
const bool hasGccCCompiler = gccCInfo.exists();
const QString gccFullName = name + QLatin1String("-gcc") + xcodeName;
QStringList extraFlags;
if (defaultProp.contains(QLatin1String("NATIVE_ARCH"))) {
QString arch = defaultProp.value(QLatin1String("NATIVE_ARCH")).toString();
if (!arch.startsWith(QLatin1String("arm")))
qCWarning(probeLog) << indent << QString::fromLatin1("Expected arm architecture, not %1").arg(arch);
extraFlags << QLatin1String("-arch") << arch;
} else if (name == QLatin1String("iphonesimulator")) {
// don't generate a toolchain for 64 bit (to fix when we support that)
extraFlags << QLatin1String("-arch") << QLatin1String("i386");
}
auto getArch = [extraFlags](const QFileInfo &compiler) {
QStringList flags = extraFlags;
flags << QLatin1String("-dumpmachine");
const QStringList compilerTriplet = qsystem(compiler.canonicalFilePath(), flags)
.simplified().split(QLatin1Char('-'));
return compilerTriplet.value(0);
};
if (hasClangCpp || hasClangC) {
Platform clangProfile;
clangProfile.type = Platform::CLang;
clangProfile.developerPath = Utils::FileName::fromString(devPath);
clangProfile.platformKind = 0;
clangProfile.platformPath = Utils::FileName(fInfo);
clangProfile.architecture = getArch(hasClangCpp ? clangCppInfo : clangCInfo);
clangProfile.backendFlags = extraFlags;
qCDebug(probeLog) << indent << QString::fromLatin1("* adding profile %1").arg(clangProfile.name);
clangProfile.name = clangFullName;
if (hasClangC) {
clangProfile.cCompilerPath = Utils::FileName(clangCInfo);
m_platforms[clangFullName] = clangProfile;
}
if (hasClangCpp) {
clangProfile.cxxCompilerPath = Utils::FileName(clangCppInfo);
m_platforms[clangFullName] = clangProfile;
clangProfile.platformKind |= Platform::Cxx11Support;
clangProfile.backendFlags.append(QLatin1String("-std=c++11"));
clangProfile.backendFlags.append(QLatin1String("-stdlib=libc++"));
clangProfile.name = clang11FullName;
m_platforms[clang11FullName] = clangProfile;
}
}
if (hasGccCppCompiler || hasGccCCompiler) {
Platform gccProfile;
gccProfile.type = Platform::GCC;
gccProfile.developerPath = Utils::FileName::fromString(devPath);
gccProfile.name = gccFullName;
gccProfile.platformKind = 0;
// use the arm-apple-darwin10-llvm-* variant and avoid the extraFlags if available???
gccProfile.platformPath = Utils::FileName(fInfo);
gccProfile.architecture = getArch(hasGccCppCompiler ? gccCppInfo : gccCInfo);
gccProfile.backendFlags = extraFlags;
qCDebug(probeLog) << indent << QString::fromLatin1("* adding profile %1").arg(gccProfile.name);
if (hasGccCppCompiler) {
gccProfile.cxxCompilerPath = Utils::FileName(gccCppInfo);
}
if (hasGccCCompiler) {
gccProfile.cCompilerPath = Utils::FileName(gccCInfo);
}
m_platforms[gccFullName] = gccProfile;
}
// set SDKs/sysroot
QString sysRoot;
{
QString sdkName;
if (defaultProp.contains(QLatin1String("SDKROOT")))
sdkName = defaultProp.value(QLatin1String("SDKROOT")).toString();
QString sdkPath;
QString sdkPathWithSameVersion;
QDir sdks(fInfo.absoluteFilePath() + QLatin1String("/Developer/SDKs"));
QString maxVersion;
foreach (const QFileInfo &sdkDirInfo, sdks.entryInfoList(QDir::Dirs
| QDir::NoDotAndDotDot)) {
indent = QLatin1String(" ");
QSettings sdkInfo(sdkDirInfo.absoluteFilePath()
+ QLatin1String("/SDKSettings.plist"),
QSettings::NativeFormat);
QString versionStr = sdkInfo.value(QLatin1String("Version")).toString();
QVariant currentSdkName = sdkInfo.value(QLatin1String("CanonicalName"));
bool isBaseSdk = sdkInfo.value((QLatin1String("isBaseSDK"))).toString()
.toLower() != QLatin1String("no");
if (!isBaseSdk) {
qCDebug(probeLog) << indent << QString::fromLatin1("Skipping non base Sdk %1")
.arg(currentSdkName.toString());
continue;
}
if (sdkName.isEmpty()) {
if (maxVersion.isEmpty() || compareVersions(maxVersion, versionStr) > 0) {
maxVersion = versionStr;
sdkPath = sdkDirInfo.canonicalFilePath();
}
} else if (currentSdkName == sdkName) {
sdkPath = sdkDirInfo.canonicalFilePath();
} else if (currentSdkName.toString().startsWith(sdkName) /*if sdkName doesn't contain version*/
&& compareVersions(platformSdkVersion, versionStr) == 0)
sdkPathWithSameVersion = sdkDirInfo.canonicalFilePath();
}
if (sdkPath.isEmpty())
sysRoot = sdkPathWithSameVersion;
else
sysRoot = sdkPath;
if (sysRoot.isEmpty() && !sdkName.isEmpty())
qCDebug(probeLog) << indent << QString::fromLatin1("Failed to find sysroot %1").arg(sdkName);
}
const QFileInfo clangCppInfo = getClangInfo("clang++");