示例#1
0
// Detect Clang-cl on top of MSVC2015 or MSVC2013.
static void detectClangClToolChain(QList<ToolChain *> *list)
{
#ifdef Q_OS_WIN64
    const char registryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\LLVM\\LLVM";
#else
    const char registryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\LLVM\\LLVM";
#endif

    const QSettings registry(QLatin1String(registryNode), QSettings::NativeFormat);
    if (registry.status() != QSettings::NoError)
        return;
    const QString path = QDir::cleanPath(registry.value(QStringLiteral(".")).toString());
    if (path.isEmpty())
        return;
    const unsigned char wordWidth = Utils::is64BitWindowsBinary(path + QStringLiteral("/bin/") + QLatin1String(clangClBinary))
        ? 64 : 32;
    const ToolChain *toolChain = findMsvcToolChain(*list, wordWidth, Abi::WindowsMsvc2015Flavor);
    if (!toolChain)
        toolChain = findMsvcToolChain(*list, wordWidth, Abi::WindowsMsvc2013Flavor);
    if (!toolChain) {
        qWarning("Unable to find a suitable MSVC version for \"%s\".", qPrintable(QDir::toNativeSeparators(path)));
        return;
    }
    const MsvcToolChain *msvcToolChain = static_cast<const MsvcToolChain *>(toolChain);
    const Abi targetAbi = msvcToolChain->targetAbi();
    const QString name = QStringLiteral("LLVM ") + QString::number(wordWidth)
        + QStringLiteral("bit based on ")
        + Abi::toString(targetAbi.osFlavor()).toUpper();
    list->append(new ClangClToolChain(name, path, targetAbi,
                                      msvcToolChain->varsBat(), msvcToolChain->varsBatArg(),
                                      ToolChain::AutoDetection));
}
void ProfileChooser::init(bool hostAbiOnly)
{
    const Abi hostAbi = Abi::hostAbi();
    foreach (const Profile *st, ProfileManager::instance()->profiles()) {
        if (!st->isValid())
            continue;
        ToolChain *tc = ToolChainProfileInformation::toolChain(st);
        if (!tc)
            continue;
        const Abi abi = tc->targetAbi();
        if (hostAbiOnly && hostAbi.os() != abi.os())
            continue;

        const QString debuggerCommand = DebuggerProfileInformation::debuggerCommand(st).toString();
        if (debuggerCommand.isEmpty())
            continue;

        const QString completeBase = QFileInfo(debuggerCommand).completeBaseName();
        const QString name = tr("%1 (%2)").arg(st->displayName(), completeBase);
        addItem(name, qVariantFromValue(st->id()));
        QString debugger = QDir::toNativeSeparators(debuggerCommand);
        debugger.replace(QString(QLatin1Char(' ')), QLatin1String("&nbsp;"));
        QString toolTip = tr("<html><head/><body><table>"
            "<tr><td>ABI:</td><td><i>%1</i></td></tr>"
            "<tr><td>Debugger:</td><td>%2</td></tr>")
                .arg(st->displayName(), QDir::toNativeSeparators(debugger));
        setItemData(count() - 1, toolTip, Qt::ToolTipRole);
    }
    setEnabled(count() > 1);
}
示例#3
0
// Return the set of physical registers implicitly accessed (used or defined)
// TODO: t4779515: replace this, and other switches, with logic using
// attributes, instead of hardcoded opcode names.
void getEffects(const Abi& abi, const Vinstr& i, RegSet& uses, RegSet& defs) {
  uses = defs = RegSet();
  switch (i.op) {
    case Vinstr::mccall:
    case Vinstr::call:
    case Vinstr::callm:
    case Vinstr::callr:
      defs = abi.all() - abi.calleeSaved;
      break;
    case Vinstr::callstub:
      defs = i.callstub_.kills;
      break;
    case Vinstr::bindcall:
    case Vinstr::contenter:
      defs = abi.all();
      break;
    case Vinstr::cqo:
      uses = RegSet(rax);
      defs = RegSet(rdx);
      break;
    case Vinstr::idiv:
      uses = defs = RegSet(rax).add(rdx);
      break;
    case Vinstr::shlq:
    case Vinstr::sarq:
      uses = RegSet(rcx);
      break;
    default:
      break;
  }
}
示例#4
0
static ToolChain *findMsvcToolChain(const QList<ToolChain *> &list,
                                    unsigned char wordWidth, Abi::OSFlavor flavor)
{
    return Utils::findOrDefault(list, [wordWidth, flavor] (const ToolChain *tc)
        { const Abi abi = tc->targetAbi();
          return abi.osFlavor() == flavor
              && wordWidth == abi.wordWidth();} );
}
示例#5
0
void getEffects(const Abi& abi, const Vinstr& i,
                RegSet& uses, RegSet& across, RegSet& defs) {
  uses = defs = across = RegSet();
  switch (i.op) {
    case Vinstr::mccall:
    case Vinstr::call:
    case Vinstr::callm:
    case Vinstr::callr:
      defs = abi.all() - abi.calleeSaved;
      switch (arch()) {
        case Arch::ARM:
          defs.add(PhysReg(arm::rLinkReg));
          defs.remove(PhysReg(arm::rVmFp));
          break;
        case Arch::X64:
          defs.remove(reg::rbp);
          break;
      }
      break;
    case Vinstr::bindcall:
      defs = abi.all();
      switch (arch()) {
      case Arch::ARM: break;
      case Arch::X64: defs.remove(x64::rVmTl); break;
      }
      break;
    case Vinstr::contenter:
    case Vinstr::callstub:
      defs = abi.all();
      switch (arch()) {
      case Arch::ARM: defs.remove(PhysReg(arm::rVmFp)); break;
      case Arch::X64: defs -= reg::rbp | x64::rVmTl; break;
      }
      break;
    case Vinstr::cqo:
      uses = RegSet(reg::rax);
      defs = reg::rax | reg::rdx;
      break;
    case Vinstr::idiv:
      uses = defs = reg::rax | reg::rdx;
      break;
    case Vinstr::shlq:
    case Vinstr::sarq:
      across = RegSet(reg::rcx);
      break;
    // arm instrs
    case Vinstr::hostcall:
      defs = (abi.all() - abi.calleeSaved) |
             RegSet(PhysReg(arm::rHostCallReg));
      break;
    case Vinstr::vcall:
    case Vinstr::vinvoke:
    case Vinstr::vcallstub:
      always_assert(false && "Unsupported instruction in vxls");
    default:
      break;
  }
}
示例#6
0
QList<ToolChain *>
AndroidToolChainFactory::autodetectToolChainsForNdk(const FileName &ndkPath,
                                                    const QList<ToolChain *> &alreadyKnown)
{
    QList<ToolChain *> result;
    if (ndkPath.isEmpty())
        return result;

    QRegExp versionRegExp(NDKGccVersionRegExp);
    FileName path = ndkPath;
    QDirIterator it(path.appendPath(QLatin1String("toolchains")).toString(),
                    QStringList() << QLatin1String("*"), QDir::Dirs);
    QHash<Abi, QList<AndroidToolChain *>> newestToolChainForArch;

    while (it.hasNext()) {
        const QString &fileName = FileName::fromString(it.next()).fileName();
        int idx = versionRegExp.indexIn(fileName);
        if (idx == -1)
            continue;
        QString version = fileName.mid(idx + 1);
        QString platform = fileName.left(idx);
        Abi abi = AndroidConfig::abiForToolChainPrefix(platform);
        if (abi.architecture() == Abi::UnknownArchitecture) // e.g. mipsel which is not yet supported
            continue;
        QList<AndroidToolChain *> toolChainBundle;
        for (ToolChain::Language lang : { ToolChain::Language::Cxx, ToolChain::Language::C }) {
            FileName compilerPath = AndroidConfigurations::currentConfig().gccPath(abi, lang, version);

            AndroidToolChain *tc = findToolChain(compilerPath, lang, alreadyKnown);
            if (!tc) {
                tc = new AndroidToolChain(abi, version, lang,
                                          ToolChain::AutoDetection);
                tc->resetToolChain(compilerPath);
            }
            result.append(tc);
            toolChainBundle.append(tc);
        }

        auto it = newestToolChainForArch.constFind(abi);
        if (it == newestToolChainForArch.constEnd())
            newestToolChainForArch.insert(abi, toolChainBundle);
        else if (versionCompareLess(it.value(), toolChainBundle))
            newestToolChainForArch[abi] = toolChainBundle;
    }

    foreach (ToolChain *tc, result) {
        AndroidToolChain *atc = static_cast<AndroidToolChain *>(tc);
        atc->setSecondaryToolChain(!newestToolChainForArch.value(atc->targetAbi()).contains(atc));
    }
示例#7
0
QList<ToolChain *>
AndroidToolChainFactory::autodetectToolChainsForNdk(const FileName &ndkPath,
                                                    const QList<ToolChain *> &alreadyKnown)
{
    QList<ToolChain *> result;
    if (ndkPath.isEmpty())
        return result;

    QRegExp versionRegExp(NDKGccVersionRegExp);
    FileName path = ndkPath;
    QDirIterator it(path.appendPath(QLatin1String("toolchains")).toString(),
                    QStringList("*"), QDir::Dirs);
    QHash<Abi, QList<AndroidToolChain *>> newestToolChainForArch;

    while (it.hasNext()) {
        const QString &fileName = FileName::fromString(it.next()).fileName();
        int idx = versionRegExp.indexIn(fileName);
        if (idx == -1)
            continue;
        QString version = fileName.mid(idx + 1);
        QString platform = fileName.left(idx);
        Abi abi = AndroidConfig::abiForToolChainPrefix(platform);
        if (abi.architecture() == Abi::UnknownArchitecture)
            continue;
        QList<AndroidToolChain *> toolChainBundle;
        for (Core::Id lang : {ProjectExplorer::Constants::CXX_LANGUAGE_ID, ProjectExplorer::Constants::C_LANGUAGE_ID}) {
            FileName compilerPath = AndroidConfigurations::currentConfig().gccPath(abi, lang, version);

            AndroidToolChain *tc = findToolChain(compilerPath, lang, alreadyKnown);
            if (!tc || tc->originalTargetTriple().isEmpty()) {
                tc = new AndroidToolChain(abi, version, lang,
                                          ToolChain::AutoDetection);
                tc->resetToolChain(compilerPath);
                QTC_ASSERT(!tc->originalTargetTriple().isEmpty(),
                           delete tc; continue);
            }
            result.append(tc);
            toolChainBundle.append(tc);
        }

        QTC_ASSERT(!toolChainBundle.isEmpty(), continue);

        auto it = newestToolChainForArch.constFind(abi);
        if (it == newestToolChainForArch.constEnd())
            newestToolChainForArch.insert(abi, toolChainBundle);
        else if (versionCompareLess(it.value(), toolChainBundle))
            newestToolChainForArch[abi] = toolChainBundle;
    }
示例#8
0
QList<Task> BaseQtVersion::validateKit(const Kit *k)
{
    QList<Task> result;

    BaseQtVersion *version = QtKitInformation::qtVersion(k);
    Q_ASSERT(version == this);

    const QList<Abi> qtAbis = version->qtAbis();
    if (qtAbis.isEmpty()) // No need to test if Qt does not know anyway...
        return result;

    ToolChain *tc = ToolChainKitInformation::toolChain(k);
    if (tc) {
        Abi targetAbi = tc->targetAbi();
        bool fuzzyMatch = false;
        bool fullMatch = false;

        QString qtAbiString;
        foreach (const Abi &qtAbi, qtAbis) {
            if (!qtAbiString.isEmpty())
                qtAbiString.append(QLatin1Char(' '));
            qtAbiString.append(qtAbi.toString());

            if (!fullMatch)
                fullMatch = (targetAbi == qtAbi);
            if (!fuzzyMatch)
                fuzzyMatch = targetAbi.isCompatibleWith(qtAbi);
        }

        QString message;
        if (!fullMatch) {
            if (!fuzzyMatch)
                message = QCoreApplication::translate("BaseQtVersion",
                                                      "The compiler '%1' (%2) cannot produce code for the Qt version '%3' (%4).");
            else
                message = QCoreApplication::translate("BaseQtVersion",
                                                      "The compiler '%1' (%2) may not produce code compatible with the Qt version '%3' (%4).");
            message = message.arg(tc->displayName(), targetAbi.toString(),
                                  version->displayName(), qtAbiString);
            result << Task(fuzzyMatch ? Task::Warning : Task::Error, message, FileName(), -1,
                           ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
        }
    }
    return result;
}
示例#9
0
void AbiWidget::setCustomAbi(const Abi &current)
{
    d->m_architectureComboBox->setCurrentIndex(static_cast<int>(current.architecture()));
    d->m_osComboBox->setCurrentIndex(static_cast<int>(current.os()));
    osChanged();
    for (int i = 0; i < d->m_osFlavorComboBox->count(); ++i) {
        if (d->m_osFlavorComboBox->itemData(i).toInt() == current.osFlavor()) {
            d->m_osFlavorComboBox->setCurrentIndex(i);
            break;
        }
    }
    d->m_binaryFormatComboBox->setCurrentIndex(static_cast<int>(current.binaryFormat()));
    for (int i = 0; i < d->m_wordWidthComboBox->count(); ++i) {
        if (d->m_wordWidthComboBox->itemData(i).toInt() == current.wordWidth()) {
            d->m_wordWidthComboBox->setCurrentIndex(i);
            break;
        }
    }
}
示例#10
0
MsvcToolChain::MsvcToolChain(const QString &name, const Abi &abi,
                             const QString &varsBat, const QString &varsBatArg, bool autodetect) :
    ToolChain(QLatin1String(Constants::MSVC_TOOLCHAIN_ID), autodetect),
    m_varsBat(varsBat),
    m_varsBatArg(varsBatArg),
    m_lastEnvironment(Utils::Environment::systemEnvironment()),
    m_abi(abi)
{
    Q_ASSERT(!name.isEmpty());
    Q_ASSERT(!m_varsBat.isEmpty());
    Q_ASSERT(QFileInfo(m_varsBat).exists());
    Q_ASSERT(abi.os() == Abi::WindowsOS);
    Q_ASSERT(abi.binaryFormat() == Abi::PEFormat);
    Q_ASSERT(abi.osFlavor() != Abi::WindowsMSysFlavor);

    setId(QString::fromLatin1("%1:%2.%3.%4").arg(Constants::MSVC_TOOLCHAIN_ID).arg(m_varsBat)
            .arg(m_varsBatArg).arg(m_debuggerCommand));

    setDisplayName(name);
}
示例#11
0
void AbiWidget::setCustomAbi(const Abi &current)
{
    bool blocked = blockSignals(true);
    d->m_architectureComboBox->setCurrentIndex(static_cast<int>(current.architecture()));
    d->m_osComboBox->setCurrentIndex(static_cast<int>(current.os()));
    osChanged();
    for (int i = 0; i < d->m_osFlavorComboBox->count(); ++i) {
        if (d->m_osFlavorComboBox->itemData(i).toInt() == current.osFlavor()) {
            d->m_osFlavorComboBox->setCurrentIndex(i);
            break;
        }
    }
    d->m_binaryFormatComboBox->setCurrentIndex(static_cast<int>(current.binaryFormat()));
    for (int i = 0; i < d->m_wordWidthComboBox->count(); ++i) {
        if (d->m_wordWidthComboBox->itemData(i).toInt() == current.wordWidth()) {
            d->m_wordWidthComboBox->setCurrentIndex(i);
            break;
        }
    }
    if (d->isCustom())
        d->m_abi->setItemData(0, current.toString());
    blockSignals(blocked);

    emit abiChanged();
}
示例#12
0
bool Abi::isCompatibleWith(const Abi &other) const
{
    bool isCompat = (architecture() == other.architecture() || other.architecture() == Abi::UnknownArchitecture)
                     && (os() == other.os() || other.os() == Abi::UnknownOS)
                     && (osFlavor() == other.osFlavor() || other.osFlavor() == Abi::UnknownFlavor)
                     && (binaryFormat() == other.binaryFormat() || other.binaryFormat() == Abi::UnknownFormat)
                     && ((wordWidth() == other.wordWidth() && wordWidth() != 0) || other.wordWidth() == 0);
    // *-linux-generic-* is compatible with *-linux-* (both ways): This is for the benefit of
    // people building Qt themselves using e.g. a meego toolchain.
    //
    // We leave it to the specific targets to catch filter out the tool chains that do not
    // work for them.
    if (!isCompat && (architecture() == other.architecture() || other.architecture() == Abi::UnknownArchitecture)
                  && ((os() == other.os()) && (os() == LinuxOS))
                  && (osFlavor() == GenericLinuxFlavor || other.osFlavor() == GenericLinuxFlavor)
                  && (binaryFormat() == other.binaryFormat() || other.binaryFormat() == Abi::UnknownFormat)
                  && ((wordWidth() == other.wordWidth() && wordWidth() != 0) || other.wordWidth() == 0))
        isCompat = true;
    if (osFlavor() == AndroidLinuxFlavor || other.osFlavor() == AndroidLinuxFlavor)
        isCompat = (osFlavor() == other.osFlavor() && architecture() == other.architecture());
    return isCompat;
}
Abi QmlProjectRunConfiguration::abi() const
{
    Abi hostAbi = Abi::hostAbi();
    return Abi(hostAbi.architecture(), hostAbi.os(), hostAbi.osFlavor(),
               Abi::RuntimeQmlFormat, hostAbi.wordWidth());
}
示例#14
0
void getEffects(const Abi& abi, const Vinstr& i,
                RegSet& uses, RegSet& across, RegSet& defs) {
  uses = defs = across = RegSet();
  switch (i.op) {
    case Vinstr::mccall:
    case Vinstr::call:
    case Vinstr::callm:
    case Vinstr::callr:
      defs = abi.all() - (abi.calleeSaved | rvmfp());

      switch (arch()) {
      case Arch::ARM: defs.add(PhysReg(arm::rLinkReg)); break;
      case Arch::X64: break;
      case Arch::PPC64: not_implemented(); break;
      }
      break;

    case Vinstr::bindcall:
      defs = abi.all();
      switch (arch()) {
      case Arch::ARM: break;
      case Arch::X64: defs.remove(rvmtl()); break;
      case Arch::PPC64: not_implemented(); break;
      }
      break;
    case Vinstr::contenter:
    case Vinstr::callarray:
      defs = abi.all() - RegSet(rvmfp());
      switch (arch()) {
      case Arch::ARM: break;
      case Arch::X64: defs.remove(rvmtl()); break;
      case Arch::PPC64: not_implemented(); break;
      }
      break;
    case Vinstr::callfaststub:
      defs = abi.all() - abi.calleeSaved - abi.gpUnreserved;
      break;
    case Vinstr::cqo:
      uses = RegSet(reg::rax);
      defs = reg::rax | reg::rdx;
      break;
    case Vinstr::idiv:
      uses = defs = reg::rax | reg::rdx;
      break;
    case Vinstr::shlq:
    case Vinstr::sarq:
      across = RegSet(reg::rcx);
      break;
    // arm instrs
    case Vinstr::hostcall:
      defs = (abi.all() - abi.calleeSaved) |
             RegSet(PhysReg(arm::rHostCallReg));
      break;
    case Vinstr::vcall:
    case Vinstr::vinvoke:
    case Vinstr::vcallarray:
      always_assert(false && "Unsupported instruction in vxls");
    default:
      break;
  }
}
示例#15
0
QList<Utils::FileName> GccToolChain::suggestedMkspecList() const
{
    Abi abi = targetAbi();
    Abi host = Abi::hostAbi();

    // Cross compile: Leave the mkspec alone!
    if (abi.architecture() != host.architecture()
            || abi.os() != host.os()
            || abi.osFlavor() != host.osFlavor()) // Note: This can fail:-(
        return QList<Utils::FileName>();

    if (abi.os() == Abi::MacOS) {
        QString v = version();
        // prefer versioned g++ on mac. This is required to enable building for older Mac OS versions
        if (v.startsWith(QLatin1String("4.0")) && m_compilerCommand.endsWith(QLatin1String("-4.0")))
            return QList<Utils::FileName>() << Utils::FileName::fromString(QLatin1String("macx-g++40"));
        if (v.startsWith(QLatin1String("4.2")) && m_compilerCommand.endsWith(QLatin1String("-4.2")))
            return QList<Utils::FileName>() << Utils::FileName::fromString(QLatin1String("macx-g++42"));
        return QList<Utils::FileName>() << Utils::FileName::fromString(QLatin1String("macx-g++"));
    }

    if (abi.os() == Abi::LinuxOS) {
        if (abi.osFlavor() != Abi::GenericLinuxFlavor)
            return QList<Utils::FileName>(); // most likely not a desktop, so leave the mkspec alone.
        if (abi.wordWidth() == host.wordWidth())
            return QList<Utils::FileName>() << Utils::FileName::fromString(QLatin1String("linux-g++")); // no need to explicitly set the word width
        return QList<Utils::FileName>() << Utils::FileName::fromString(QLatin1String("linux-g++-") + QString::number(m_targetAbi.wordWidth()));
    }

    if (abi.os() == Abi::BsdOS && abi.osFlavor() == Abi::FreeBsdFlavor)
        return QList<Utils::FileName>() << Utils::FileName::fromString(QLatin1String("freebsd-g++"));

    return QList<Utils::FileName>();
}