diff options
author | Vikas Pachdha <vikas.pachdha@qt.io> | 2016-11-16 14:59:10 +0100 |
---|---|---|
committer | Vikas Pachdha <vikas.pachdha@qt.io> | 2016-11-25 12:37:53 +0000 |
commit | 9f0bb3c93a1c4f69e2d523206fa31dbc779e2e9b (patch) | |
tree | b1fcc5258cca3486a263c93c137b41c309f0b423 /src/plugins | |
parent | 38753d06a2badf6e33e34ed4c0b494aea5e41a64 (diff) | |
download | qt-creator-9f0bb3c93a1c4f69e2d523206fa31dbc779e2e9b.tar.gz |
iOS: Add C toolchain
To fix kits complaining about incorrect C compiler and ABI
incompatibility
Task-number: QTCREATORBUG-17135
Change-Id: I69ece613453463b97d193bb1740044d16f62172f
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/ios/iosconfigurations.cpp | 85 | ||||
-rw-r--r-- | src/plugins/ios/iosprobe.cpp | 132 | ||||
-rw-r--r-- | src/plugins/ios/iosprobe.h | 9 |
3 files changed, 143 insertions, 83 deletions
diff --git a/src/plugins/ios/iosconfigurations.cpp b/src/plugins/ios/iosconfigurations.cpp index 0f0bf50502..0a8f45f2db 100644 --- a/src/plugins/ios/iosconfigurations.cpp +++ b/src/plugins/ios/iosconfigurations.cpp @@ -64,6 +64,7 @@ namespace { Q_LOGGING_CATEGORY(kitSetupLog, "qtc.ios.kitSetup") } +using ToolChainPair = std::pair<ClangToolChain *, ClangToolChain *>; namespace Ios { namespace Internal { @@ -89,7 +90,7 @@ static bool handledPlatform(const Platform &platform) return deviceId(platform).isValid() && (platform.platformKind & Platform::BasePlatform) != 0 && (platform.platformKind & Platform::Cxx11Support) == 0 - && platform.compilerPath.toString().contains(QLatin1String("clang")); + && platform.type == Platform::CLang; } static QList<Platform> handledPlatforms() @@ -116,23 +117,31 @@ static QList<ClangToolChain *> autoDetectedIosToolChains() }); } -static ClangToolChain *findToolChainForPlatform(const Platform &platform, const QList<ClangToolChain *> &toolChains) +static ToolChainPair findToolChainForPlatform(const Platform &platform, const QList<ClangToolChain *> &toolChains) { - return Utils::findOrDefault(toolChains, [&platform](ClangToolChain *toolChain) { - return platform.compilerPath == toolChain->compilerCommand() - && platform.backendFlags == toolChain->platformCodeGenFlags() - && platform.backendFlags == toolChain->platformLinkerFlags(); - }); + ToolChainPair platformToolChains; + auto toolchainMatch = [](ClangToolChain *toolChain, const Utils::FileName &compilerPath, const QStringList &flags) { + return compilerPath == toolChain->compilerCommand() + && flags == toolChain->platformCodeGenFlags() + && flags == toolChain->platformLinkerFlags(); + }; + platformToolChains.first = Utils::findOrDefault(toolChains, std::bind(toolchainMatch, std::placeholders::_1, + platform.cCompilerPath, + platform.backendFlags)); + platformToolChains.second = Utils::findOrDefault(toolChains, std::bind(toolchainMatch, std::placeholders::_1, + platform.cxxCompilerPath, + platform.backendFlags)); + return platformToolChains; } -static QHash<Platform, ClangToolChain *> findToolChains(const QList<Platform> &platforms) +static QHash<Platform, ToolChainPair> findToolChains(const QList<Platform> &platforms) { - QHash<Platform, ClangToolChain *> platformToolChainHash; + QHash<Platform, ToolChainPair> platformToolChainHash; const QList<ClangToolChain *> toolChains = autoDetectedIosToolChains(); foreach (const Platform &platform, platforms) { - ClangToolChain *toolChain = findToolChainForPlatform(platform, toolChains); - if (toolChain) - platformToolChainHash.insert(platform, toolChain); + ToolChainPair platformToolchains = findToolChainForPlatform(platform, toolChains); + if (platformToolchains.first || platformToolchains.second) + platformToolChainHash.insert(platform, platformToolchains); } return platformToolChainHash; } @@ -173,11 +182,12 @@ static void printKits(const QSet<Kit *> &kits) qCDebug(kitSetupLog) << " -" << kit->displayName(); } -static void setupKit(Kit *kit, Core::Id pDeviceType, ClangToolChain *pToolchain, +static void setupKit(Kit *kit, Core::Id pDeviceType, const ToolChainPair& toolChains, const QVariant &debuggerId, const Utils::FileName &sdkPath, BaseQtVersion *qtVersion) { DeviceTypeKitInformation::setDeviceTypeId(kit, pDeviceType); - ToolChainKitInformation::setToolChain(kit, pToolchain); + ToolChainKitInformation::setToolChain(kit, ToolChain::Language::C, toolChains.first); + ToolChainKitInformation::setToolChain(kit, ToolChain::Language::Cxx, toolChains.second); QtKitInformation::setQtVersion(kit, qtVersion); // only replace debugger with the default one if we find an unusable one here // (since the user could have changed it) @@ -206,7 +216,7 @@ void IosConfigurations::updateAutomaticKitList() qCDebug(kitSetupLog) << "Developer path:" << developerPath(); // platform name -> tool chain - const QHash<Platform, ClangToolChain *> platformToolChainHash = findToolChains(platforms); + const QHash<Platform, ToolChainPair> platformToolChainHash = findToolChains(platforms); const QHash<Abi::Architecture, QSet<BaseQtVersion *> > qtVersionsForArch = iosQtVersions(); qCDebug(kitSetupLog) << "iOS Qt versions:"; @@ -222,30 +232,32 @@ void IosConfigurations::updateAutomaticKitList() // match existing kits and create missing kits foreach (const Platform &platform, platforms) { qCDebug(kitSetupLog) << "Guaranteeing kits for " << platform.name ; - ClangToolChain *pToolchain = platformToolChainHash.value(platform); - if (!pToolchain) { + 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 = pToolchain->targetAbi().architecture(); + 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, &pToolchain, &qtVersion](const Kit *kit) { + 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, ToolChain::Language::Cxx) == pToolchain + && ToolChainKitInformation::toolChain(kit, ToolChain::Language::Cxx) == platformToolchains.second + && ToolChainKitInformation::toolChain(kit, ToolChain::Language::C) == 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, pToolchain, debuggerId, platform.sdkPath, qtVersion); + setupKit(kit, pDeviceType, platformToolchains, debuggerId, platform.sdkPath, qtVersion); kit->unblockNotification(); } else { qCDebug(kitSetupLog) << " - Setting up new kit"; @@ -254,7 +266,7 @@ void IosConfigurations::updateAutomaticKitList() kit->setAutoDetected(true); const QString baseDisplayName = tr("%1 %2").arg(platform.name, qtVersion->unexpandedDisplayName()); kit->setUnexpandedDisplayName(baseDisplayName); - setupKit(kit, pDeviceType, pToolchain, debuggerId, platform.sdkPath, qtVersion); + setupKit(kit, pDeviceType, platformToolchains, debuggerId, platform.sdkPath, qtVersion); kit->unblockNotification(); KitManager::registerKit(kit); } @@ -350,14 +362,18 @@ void IosConfigurations::setDeveloperPath(const FileName &devPath) } } -static ClangToolChain *createToolChain(const Platform &platform) +static ClangToolChain *createToolChain(const Platform &platform, ToolChain::Language l) { + if (l == ToolChain::Language::None) + return nullptr; + ClangToolChain *toolChain = new ClangToolChain(ToolChain::AutoDetection); - toolChain->setLanguage(ToolChain::Language::Cxx); - toolChain->setDisplayName(platform.name); + toolChain->setLanguage(l); + toolChain->setDisplayName(l == ToolChain::Language::Cxx ? platform.name + "++" : platform.name); toolChain->setPlatformCodeGenFlags(platform.backendFlags); toolChain->setPlatformLinkerFlags(platform.backendFlags); - toolChain->resetToolChain(platform.compilerPath); + toolChain->resetToolChain(l == ToolChain::Language::Cxx ? + platform.cxxCompilerPath : platform.cCompilerPath); return toolChain; } @@ -373,12 +389,17 @@ QList<ToolChain *> IosToolChainFactory::autoDetect(const QList<ToolChain *> &exi QList<ClangToolChain *> toolChains; toolChains.reserve(platforms.size()); foreach (const Platform &platform, platforms) { - ClangToolChain *toolChain = findToolChainForPlatform(platform, existingClangToolChains); - if (!toolChain) { - toolChain = createToolChain(platform); - existingClangToolChains.append(toolChain); - } - toolChains.append(toolChain); + ToolChainPair platformToolchains = findToolChainForPlatform(platform, existingClangToolChains); + auto createOrAdd = [&](ClangToolChain* toolChain, ToolChain::Language l) { + if (!toolChain) { + toolChain = createToolChain(platform, l); + existingClangToolChains.append(toolChain); + } + toolChains.append(toolChain); + }; + + createOrAdd(platformToolchains.first, ToolChain::Language::C); + createOrAdd(platformToolchains.second, ToolChain::Language::Cxx); } return Utils::transform(toolChains, [](ClangToolChain *tc) -> ToolChain * { return tc; }); } diff --git a/src/plugins/ios/iosprobe.cpp b/src/plugins/ios/iosprobe.cpp index a8be1f7b2a..291b43d550 100644 --- a/src/plugins/ios/iosprobe.cpp +++ b/src/plugins/ios/iosprobe.cpp @@ -116,17 +116,26 @@ void IosProbe::setupDefaultToolchains(const QString &devPath, const QString &xco qCDebug(probeLog) << QString::fromLatin1("Setting up platform \"%1\".").arg(xcodeName); QString indent = QLatin1String(" "); + auto getClangInfo = [devPath, indent](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.") + .arg(compilerInfo.canonicalFilePath()); + return compilerInfo; + }; + // detect clang (default toolchain) - QFileInfo clangFileInfo(devPath - + QLatin1String("/Toolchains/XcodeDefault.xctoolchain/usr/bin") - + QLatin1String("/clang++")); - bool hasClang = clangFileInfo.exists(); - if (!hasClang) - qCWarning(probeLog) << indent << QString::fromLatin1("Default toolchain %1 not found.") - .arg(clangFileInfo.canonicalFilePath()); + const QFileInfo clangCppInfo = getClangInfo("clang++"); + const bool hasClangCpp = clangCppInfo.exists(); + + const QFileInfo clangCInfo = getClangInfo("clang"); + const bool hasClangC = clangCInfo.exists(); + // Platforms - QDir platformsDir(devPath + QLatin1String("/Platforms")); - QFileInfoList platforms = platformsDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot); + 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()); @@ -159,14 +168,20 @@ void IosProbe::setupDefaultToolchains(const QString &devPath, const QString &xco defaultProp[i.key()] = i.value(); } - QString clangFullName = name + QLatin1String("-clang") + xcodeName; - QString clang11FullName = name + QLatin1String("-clang11") + xcodeName; + const QString clangFullName = name + QLatin1String("-clang") + xcodeName; + const QString clang11FullName = name + QLatin1String("-clang11") + xcodeName; // detect gcc - QFileInfo gccFileInfo(fInfo.absoluteFilePath() + QLatin1String("/Developer/usr/bin/g++")); - QString gccFullName = name + QLatin1String("-gcc") + xcodeName; - if (!gccFileInfo.exists()) - gccFileInfo = QFileInfo(devPath + QLatin1String("/usr/bin/g++")); - bool hasGcc = gccFileInfo.exists(); + QFileInfo gccCppInfo(fInfo.absoluteFilePath() + QLatin1String("/Developer/usr/bin/g++")); + if (!gccCppInfo.exists()) + gccCppInfo = QFileInfo(devPath + QLatin1String("/usr/bin/g++")); + const bool hasGccCppCompiler = gccCppInfo.exists(); + + 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"))) { @@ -178,45 +193,58 @@ void IosProbe::setupDefaultToolchains(const QString &devPath, const QString &xco // don't generate a toolchain for 64 bit (to fix when we support that) extraFlags << QLatin1String("-arch") << QLatin1String("i386"); } - if (hasClang) { + + 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.name = clangFullName; clangProfile.platformPath = Utils::FileName(fInfo); - clangProfile.compilerPath = Utils::FileName(clangFileInfo); - QStringList flags = extraFlags; - flags << QLatin1String("-dumpmachine"); - QString compilerTriplet = qsystem(clangFileInfo.canonicalFilePath(), flags) - .simplified(); - QStringList compilerTripletl = compilerTriplet.split(QLatin1Char('-')); - clangProfile.architecture = compilerTripletl.value(0); + clangProfile.architecture = getArch(hasClangCpp ? clangCppInfo : clangCInfo); clangProfile.backendFlags = extraFlags; qCDebug(probeLog) << indent << QString::fromLatin1("* adding profile %1").arg(clangProfile.name); - m_platforms[clangProfile.name] = clangProfile; - clangProfile.platformKind |= Platform::Cxx11Support; - clangProfile.backendFlags.append(QLatin1String("-std=c++11")); - clangProfile.backendFlags.append(QLatin1String("-stdlib=libc++")); - clangProfile.name = clang11FullName; - m_platforms[clangProfile.name] = clangProfile; + 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 (hasGcc) { + + 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.compilerPath = Utils::FileName(gccFileInfo); - QStringList flags = extraFlags; - flags << QLatin1String("-dumpmachine"); - QString compilerTriplet = qsystem(gccFileInfo.canonicalFilePath(), flags) - .simplified(); - QStringList compilerTripletl = compilerTriplet.split(QLatin1Char('-')); - gccProfile.architecture = compilerTripletl.value(0); + gccProfile.architecture = getArch(hasGccCppCompiler ? gccCppInfo : gccCInfo); gccProfile.backendFlags = extraFlags; qCDebug(probeLog) << indent << QString::fromLatin1("* adding profile %1").arg(gccProfile.name); - m_platforms[gccProfile.name] = gccProfile; + if (hasGccCppCompiler) { + gccProfile.cxxCompilerPath = Utils::FileName(gccCppInfo); + } + if (hasGccCCompiler) { + gccProfile.cCompilerPath = Utils::FileName(gccCInfo); + } + m_platforms[gccFullName] = gccProfile; } // set SDKs/sysroot @@ -262,15 +290,18 @@ void IosProbe::setupDefaultToolchains(const QString &devPath, const QString &xco if (sysRoot.isEmpty() && !sdkName.isEmpty()) qCDebug(probeLog) << indent << QString::fromLatin1("Failed to find sysroot %1").arg(sdkName); } - if (hasClang && !sysRoot.isEmpty()) { - m_platforms[clangFullName].platformKind |= Platform::BasePlatform; - m_platforms[clangFullName].sdkPath = Utils::FileName::fromString(sysRoot); - m_platforms[clang11FullName].platformKind |= Platform::BasePlatform; - m_platforms[clang11FullName].sdkPath = Utils::FileName::fromString(sysRoot); - } - if (hasGcc && !sysRoot.isEmpty()) { - m_platforms[gccFullName].platformKind |= Platform::BasePlatform; - m_platforms[gccFullName].sdkPath = Utils::FileName::fromString(sysRoot); + + if (!sysRoot.isEmpty()) { + auto itr = m_platforms.begin(); + while (itr != m_platforms.end()) { + if (itr.key() == clangFullName || + itr.key() == clang11FullName || + itr.key() == gccFullName) { + itr.value().platformKind |= Platform::BasePlatform; + itr.value().sdkPath = Utils::FileName::fromString(sysRoot); + } + ++itr; + } } } indent = QLatin1String(" "); @@ -293,7 +324,8 @@ QDebug operator<<(QDebug debug, const Platform &platform) { QDebugStateSaver saver(debug); Q_UNUSED(saver) debug.nospace() << "(name=" << platform.name - << ", compiler=" << platform.compilerPath.toString() + << ", C++ compiler=" << platform.cxxCompilerPath.toString() + << ", C compiler=" << platform.cCompilerPath.toString() << ", flags=" << platform.backendFlags << ")"; return debug; diff --git a/src/plugins/ios/iosprobe.h b/src/plugins/ios/iosprobe.h index 8d192b9611..be4110e676 100644 --- a/src/plugins/ios/iosprobe.h +++ b/src/plugins/ios/iosprobe.h @@ -40,13 +40,20 @@ public: Cxx11Support = 1 << 1 }; + enum CompilerType { + CLang, + GCC + }; + quint32 platformKind; + CompilerType type; QString name; Utils::FileName developerPath; Utils::FileName platformPath; Utils::FileName sdkPath; Utils::FileName defaultToolchainPath; - Utils::FileName compilerPath; + Utils::FileName cxxCompilerPath; + Utils::FileName cCompilerPath; QString architecture; QStringList backendFlags; |