2011-02-01 18:36:00 +01:00
|
|
|
/**************************************************************************
|
|
|
|
|
**
|
|
|
|
|
** This file is part of Qt Creator
|
|
|
|
|
**
|
|
|
|
|
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
|
|
|
|
**
|
|
|
|
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
|
|
|
**
|
|
|
|
|
** No Commercial Usage
|
|
|
|
|
**
|
|
|
|
|
** This file contains pre-release code and may not be distributed.
|
|
|
|
|
** You may use this file in accordance with the terms and conditions
|
|
|
|
|
** contained in the Technology Preview License Agreement accompanying
|
|
|
|
|
** this package.
|
|
|
|
|
**
|
|
|
|
|
** GNU Lesser General Public License Usage
|
|
|
|
|
**
|
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
|
|
|
** General Public License version 2.1 as published by the Free Software
|
|
|
|
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
|
|
|
** packaging of this file. Please review the following information to
|
|
|
|
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
|
|
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
|
|
|
**
|
|
|
|
|
** In addition, as a special exception, Nokia gives you certain additional
|
|
|
|
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
|
**
|
|
|
|
|
** If you have questions regarding the use of this file, please contact
|
|
|
|
|
** Nokia at qt-info@nokia.com.
|
|
|
|
|
**
|
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "abi.h"
|
|
|
|
|
|
|
|
|
|
#include <QtCore/QCoreApplication>
|
2011-03-03 11:29:07 +01:00
|
|
|
#include <QtCore/QDebug>
|
2011-02-01 18:36:00 +01:00
|
|
|
#include <QtCore/QFile>
|
|
|
|
|
#include <QtCore/QString>
|
|
|
|
|
#include <QtCore/QStringList>
|
|
|
|
|
#include <QtCore/QSysInfo>
|
|
|
|
|
|
|
|
|
|
namespace ProjectExplorer {
|
|
|
|
|
|
2011-03-02 14:09:18 +01:00
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
// Helpers
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
static Abi macAbiForCpu(quint32 type) {
|
|
|
|
|
switch (type) {
|
|
|
|
|
case 7: // CPU_TYPE_X86, CPU_TYPE_I386
|
|
|
|
|
return Abi(Abi::X86Architecture, Abi::MacOS, Abi::GenericMacFlavor, Abi::MachOFormat, 32);
|
|
|
|
|
case 0x01000000 + 7: // CPU_TYPE_X86_64
|
|
|
|
|
return Abi(Abi::X86Architecture, Abi::MacOS, Abi::GenericMacFlavor, Abi::MachOFormat, 64);
|
|
|
|
|
case 18: // CPU_TYPE_POWERPC
|
|
|
|
|
return Abi(Abi::PowerPCArchitecture, Abi::MacOS, Abi::GenericMacFlavor, Abi::MachOFormat, 32);
|
|
|
|
|
case 0x01000000 + 18: // CPU_TYPE_POWERPC64
|
|
|
|
|
return Abi(Abi::PowerPCArchitecture, Abi::MacOS, Abi::GenericMacFlavor, Abi::MachOFormat, 32);
|
|
|
|
|
case 12: // CPU_TYPE_ARM
|
|
|
|
|
return Abi(Abi::ArmArchitecture, Abi::MacOS, Abi::GenericMacFlavor, Abi::MachOFormat, 32);
|
|
|
|
|
default:
|
|
|
|
|
return Abi();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-03 11:29:07 +01:00
|
|
|
static QList<Abi> parseCoffHeader(const QByteArray &data)
|
|
|
|
|
{
|
|
|
|
|
QList<Abi> result;
|
|
|
|
|
if (data.size() < 20)
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
|
|
Abi::Architecture arch = Abi::UnknownArchitecture;
|
|
|
|
|
Abi::OSFlavor flavor = Abi::UnknownFlavor;
|
|
|
|
|
int width = 0;
|
|
|
|
|
|
|
|
|
|
// Get machine field from COFF file header
|
|
|
|
|
quint16 machine = (data.at(1) << 8) + data.at(0);
|
|
|
|
|
switch (machine) {
|
|
|
|
|
case 0x8664: // x86_64
|
|
|
|
|
arch = Abi::X86Architecture;
|
|
|
|
|
width = 64;
|
|
|
|
|
break;
|
|
|
|
|
case 0x014c: // i386
|
|
|
|
|
arch = Abi::X86Architecture;
|
|
|
|
|
width = 32;
|
|
|
|
|
break;
|
|
|
|
|
case 0x0200: // ia64
|
|
|
|
|
arch = Abi::ItaniumArchitecture;
|
|
|
|
|
width = 64;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (data.size() >= 68) {
|
|
|
|
|
// Get Major and Minor Image Version from optional header fields
|
|
|
|
|
quint32 image = (data.at(67) << 24) + (data.at(66) << 16) + (data.at(65) << 8) + data.at(64);
|
2011-03-18 09:54:35 +01:00
|
|
|
if (image == 1) { // Image is 1 for mingw and higher for MSVC (4.something in some encoding)
|
2011-03-03 11:29:07 +01:00
|
|
|
flavor = Abi::WindowsMSysFlavor;
|
2011-03-18 09:54:35 +01:00
|
|
|
} else {
|
|
|
|
|
switch (data.at(22)) {
|
|
|
|
|
case 8:
|
|
|
|
|
flavor = Abi::WindowsMsvc2005Flavor;
|
|
|
|
|
break;
|
|
|
|
|
case 9:
|
|
|
|
|
flavor = Abi::WindowsMsvc2008Flavor;
|
|
|
|
|
break;
|
|
|
|
|
case 10:
|
|
|
|
|
flavor = Abi::WindowsMsvc2010Flavor;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
// Keep unknown flavor
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-03-03 11:29:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (arch != Abi::UnknownArchitecture && width != 0)
|
|
|
|
|
result.append(Abi(arch, Abi::WindowsOS, flavor, Abi::PEFormat, width));
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-02 14:09:18 +01:00
|
|
|
static QList<Abi> abiOf(const QByteArray &data)
|
|
|
|
|
{
|
|
|
|
|
QList<Abi> result;
|
|
|
|
|
|
|
|
|
|
if (data.size() >= 20
|
|
|
|
|
&& static_cast<unsigned char>(data.at(0)) == 0x7f && static_cast<unsigned char>(data.at(1)) == 'E'
|
|
|
|
|
&& static_cast<unsigned char>(data.at(2)) == 'L' && static_cast<unsigned char>(data.at(3)) == 'F') {
|
|
|
|
|
// ELF format:
|
|
|
|
|
quint16 machine = (data.at(19) << 8) + data.at(18);
|
|
|
|
|
switch (machine) {
|
|
|
|
|
case 3: // EM_386
|
|
|
|
|
result.append(Abi(Abi::X86Architecture, Abi::LinuxOS, Abi::GenericLinuxFlavor, Abi::ElfFormat, 32));
|
|
|
|
|
break;
|
|
|
|
|
case 8: // EM_MIPS
|
|
|
|
|
result.append(Abi(Abi::MipsArcitecture, Abi::LinuxOS, Abi::GenericLinuxFlavor, Abi::ElfFormat, 32));
|
|
|
|
|
break;
|
|
|
|
|
case 20: // EM_PPC
|
|
|
|
|
result.append(Abi(Abi::PowerPCArchitecture, Abi::LinuxOS, Abi::GenericLinuxFlavor, Abi::ElfFormat, 32));
|
|
|
|
|
break;
|
|
|
|
|
case 21: // EM_PPC64
|
|
|
|
|
result.append(Abi(Abi::PowerPCArchitecture, Abi::LinuxOS, Abi::GenericLinuxFlavor, Abi::ElfFormat, 64));
|
|
|
|
|
break;
|
2011-03-21 18:04:24 +01:00
|
|
|
case 40: // EM_ARM
|
|
|
|
|
result.append(Abi(Abi::ArmArchitecture, Abi::LinuxOS, Abi::GenericLinuxFlavor, Abi::ElfFormat, 32));
|
|
|
|
|
break;
|
2011-03-02 14:09:18 +01:00
|
|
|
case 62: // EM_X86_64
|
|
|
|
|
result.append(Abi(Abi::X86Architecture, Abi::LinuxOS, Abi::GenericLinuxFlavor, Abi::ElfFormat, 64));
|
|
|
|
|
break;
|
|
|
|
|
case 50: // EM_IA_64
|
|
|
|
|
result.append(Abi(Abi::ItaniumArchitecture, Abi::LinuxOS, Abi::GenericLinuxFlavor, Abi::ElfFormat, 64));
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
;;
|
|
|
|
|
}
|
|
|
|
|
} else if (data.size() >= 8
|
|
|
|
|
&& (static_cast<unsigned char>(data.at(0)) == 0xce || static_cast<unsigned char>(data.at(0)) == 0xcf)
|
|
|
|
|
&& static_cast<unsigned char>(data.at(1)) == 0xfa
|
|
|
|
|
&& static_cast<unsigned char>(data.at(2)) == 0xed && static_cast<unsigned char>(data.at(3)) == 0xfe) {
|
|
|
|
|
// Mach-O format (Mac non-fat binary, 32 and 64bit magic)
|
|
|
|
|
quint32 type = (data.at(7) << 24) + (data.at(6) << 16) + (data.at(5) << 8) + data.at(4);
|
|
|
|
|
result.append(macAbiForCpu(type));
|
|
|
|
|
} else if (data.size() >= 8
|
|
|
|
|
&& static_cast<unsigned char>(data.at(0)) == 0xca && static_cast<unsigned char>(data.at(1)) == 0xfe
|
|
|
|
|
&& static_cast<unsigned char>(data.at(2)) == 0xba && static_cast<unsigned char>(data.at(3)) == 0xbe) {
|
|
|
|
|
// Mac fat binary:
|
|
|
|
|
quint32 count = (data.at(4) << 24) + (data.at(5) << 16) + (data.at(6) << 8) + data.at(7);
|
|
|
|
|
int pos = 8;
|
|
|
|
|
for (quint32 i = 0; i < count; ++i) {
|
|
|
|
|
if (data.size() <= pos + 4)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
quint32 type = (data.at(pos) << 24) + (data.at(pos + 1) << 16) + (data.at(pos + 2) << 8) + data.at(pos + 3);
|
|
|
|
|
result.append(macAbiForCpu(type));
|
|
|
|
|
pos += 20;
|
|
|
|
|
}
|
2011-03-21 18:04:24 +01:00
|
|
|
} else if (data.size() >= 20
|
|
|
|
|
&& static_cast<unsigned char>(data.at(16)) == 'E' && static_cast<unsigned char>(data.at(17)) == 'P'
|
|
|
|
|
&& static_cast<unsigned char>(data.at(18)) == 'O' && static_cast<unsigned char>(data.at(19)) == 'C') {
|
|
|
|
|
result.append(Abi(Abi::ArmArchitecture, Abi::SymbianOS, Abi::SymbianDeviceFlavor, Abi::ElfFormat, 32));
|
2011-03-02 14:09:18 +01:00
|
|
|
} else {
|
|
|
|
|
// Windows PE
|
|
|
|
|
// Windows can have its magic bytes everywhere...
|
2011-03-02 17:17:07 +01:00
|
|
|
int pePos = data.indexOf(QByteArray("PE\0\0", 4));
|
2011-03-03 11:29:07 +01:00
|
|
|
if (pePos >= 0)
|
|
|
|
|
result = parseCoffHeader(data.mid(pePos + 4));
|
2011-03-02 14:09:18 +01:00
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
// Abi
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
|
|
|
2011-02-01 18:36:00 +01:00
|
|
|
Abi::Abi(const Architecture &a, const OS &o,
|
2011-02-23 16:47:08 +01:00
|
|
|
const OSFlavor &of, const BinaryFormat &f, unsigned char w) :
|
2011-02-01 18:36:00 +01:00
|
|
|
m_architecture(a), m_os(o), m_osFlavor(of), m_binaryFormat(f), m_wordWidth(w)
|
|
|
|
|
{
|
|
|
|
|
switch (m_os) {
|
2011-02-23 16:47:08 +01:00
|
|
|
case ProjectExplorer::Abi::UnknownOS:
|
|
|
|
|
m_osFlavor = UnknownFlavor;
|
2011-02-01 18:36:00 +01:00
|
|
|
break;
|
2011-02-23 16:47:08 +01:00
|
|
|
case ProjectExplorer::Abi::LinuxOS:
|
|
|
|
|
if (m_osFlavor < GenericLinuxFlavor || m_osFlavor > MeegoLinuxFlavor)
|
|
|
|
|
m_osFlavor = UnknownFlavor;
|
2011-02-01 18:36:00 +01:00
|
|
|
break;
|
2011-02-23 16:47:08 +01:00
|
|
|
case ProjectExplorer::Abi::MacOS:
|
|
|
|
|
if (m_osFlavor < GenericMacFlavor || m_osFlavor > GenericMacFlavor)
|
|
|
|
|
m_osFlavor = UnknownFlavor;
|
2011-02-01 18:36:00 +01:00
|
|
|
break;
|
2011-02-23 16:47:08 +01:00
|
|
|
case ProjectExplorer::Abi::SymbianOS:
|
|
|
|
|
if (m_osFlavor < SymbianDeviceFlavor || m_osFlavor > SymbianEmulatorFlavor)
|
|
|
|
|
m_osFlavor = UnknownFlavor;
|
2011-02-01 18:36:00 +01:00
|
|
|
break;
|
2011-02-23 16:47:08 +01:00
|
|
|
case ProjectExplorer::Abi::UnixOS:
|
|
|
|
|
if (m_osFlavor < GenericUnixFlavor || m_osFlavor > GenericUnixFlavor)
|
|
|
|
|
m_osFlavor = UnknownFlavor;
|
2011-02-01 18:36:00 +01:00
|
|
|
break;
|
2011-02-23 16:47:08 +01:00
|
|
|
case ProjectExplorer::Abi::WindowsOS:
|
2011-03-18 09:54:35 +01:00
|
|
|
if (m_osFlavor < WindowsMsvc2005Flavor || m_osFlavor > WindowsCEFlavor)
|
2011-02-23 16:47:08 +01:00
|
|
|
m_osFlavor = UnknownFlavor;
|
2011-02-01 18:36:00 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Abi::Abi(const QString &abiString) :
|
2011-02-23 16:47:08 +01:00
|
|
|
m_architecture(UnknownArchitecture), m_os(UnknownOS),
|
|
|
|
|
m_osFlavor(UnknownFlavor), m_binaryFormat(UnknownFormat), m_wordWidth(0)
|
2011-02-01 18:36:00 +01:00
|
|
|
{
|
|
|
|
|
QStringList abiParts = abiString.split(QLatin1Char('-'));
|
|
|
|
|
if (abiParts.count() >= 1) {
|
|
|
|
|
if (abiParts.at(0) == QLatin1String("unknown"))
|
2011-02-23 16:47:08 +01:00
|
|
|
m_architecture = UnknownArchitecture;
|
2011-02-01 18:36:00 +01:00
|
|
|
else if (abiParts.at(0) == QLatin1String("arm"))
|
2011-02-23 16:47:08 +01:00
|
|
|
m_architecture = ArmArchitecture;
|
2011-02-01 18:36:00 +01:00
|
|
|
else if (abiParts.at(0) == QLatin1String("x86"))
|
2011-02-23 16:47:08 +01:00
|
|
|
m_architecture = X86Architecture;
|
2011-02-01 18:36:00 +01:00
|
|
|
else if (abiParts.at(0) == QLatin1String("mips"))
|
2011-02-23 16:47:08 +01:00
|
|
|
m_architecture = MipsArcitecture;
|
2011-02-01 18:36:00 +01:00
|
|
|
else if (abiParts.at(0) == QLatin1String("ppc"))
|
2011-02-23 16:47:08 +01:00
|
|
|
m_architecture = PowerPCArchitecture;
|
2011-02-01 18:36:00 +01:00
|
|
|
else if (abiParts.at(0) == QLatin1String("itanium"))
|
2011-02-23 16:47:08 +01:00
|
|
|
m_architecture = ItaniumArchitecture;
|
2011-02-01 18:36:00 +01:00
|
|
|
else
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (abiParts.count() >= 2) {
|
|
|
|
|
if (abiParts.at(1) == QLatin1String("unknown"))
|
2011-02-23 16:47:08 +01:00
|
|
|
m_os = UnknownOS;
|
2011-02-01 18:36:00 +01:00
|
|
|
else if (abiParts.at(1) == QLatin1String("linux"))
|
2011-02-23 16:47:08 +01:00
|
|
|
m_os = LinuxOS;
|
2011-02-01 18:36:00 +01:00
|
|
|
else if (abiParts.at(1) == QLatin1String("macos"))
|
2011-02-23 16:47:08 +01:00
|
|
|
m_os = MacOS;
|
2011-02-01 18:36:00 +01:00
|
|
|
else if (abiParts.at(1) == QLatin1String("symbian"))
|
2011-02-23 16:47:08 +01:00
|
|
|
m_os = SymbianOS;
|
2011-02-01 18:36:00 +01:00
|
|
|
else if (abiParts.at(1) == QLatin1String("unix"))
|
2011-02-23 16:47:08 +01:00
|
|
|
m_os = UnixOS;
|
2011-02-01 18:36:00 +01:00
|
|
|
else if (abiParts.at(1) == QLatin1String("windows"))
|
2011-02-23 16:47:08 +01:00
|
|
|
m_os = WindowsOS;
|
2011-02-01 18:36:00 +01:00
|
|
|
else
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (abiParts.count() >= 3) {
|
|
|
|
|
if (abiParts.at(2) == QLatin1String("unknown"))
|
2011-02-23 16:47:08 +01:00
|
|
|
m_osFlavor = UnknownFlavor;
|
|
|
|
|
else if (abiParts.at(2) == QLatin1String("generic") && m_os == LinuxOS)
|
|
|
|
|
m_osFlavor = GenericLinuxFlavor;
|
|
|
|
|
else if (abiParts.at(2) == QLatin1String("maemo") && m_os == LinuxOS)
|
|
|
|
|
m_osFlavor = MaemoLinuxFlavor;
|
|
|
|
|
else if (abiParts.at(2) == QLatin1String("meego") && m_os == LinuxOS)
|
|
|
|
|
m_osFlavor = MeegoLinuxFlavor;
|
|
|
|
|
else if (abiParts.at(2) == QLatin1String("generic") && m_os == MacOS)
|
|
|
|
|
m_osFlavor = GenericMacFlavor;
|
|
|
|
|
else if (abiParts.at(2) == QLatin1String("device") && m_os == SymbianOS)
|
|
|
|
|
m_osFlavor = SymbianDeviceFlavor;
|
|
|
|
|
else if (abiParts.at(2) == QLatin1String("emulator") && m_os == SymbianOS)
|
|
|
|
|
m_osFlavor = SymbianEmulatorFlavor;
|
|
|
|
|
else if (abiParts.at(2) == QLatin1String("generic") && m_os == UnixOS)
|
|
|
|
|
m_osFlavor = GenericUnixFlavor;
|
2011-03-18 09:54:35 +01:00
|
|
|
else if (abiParts.at(2) == QLatin1String("msvc2005") && m_os == WindowsOS)
|
|
|
|
|
m_osFlavor = WindowsMsvc2005Flavor;
|
|
|
|
|
else if (abiParts.at(2) == QLatin1String("msvc2008") && m_os == WindowsOS)
|
|
|
|
|
m_osFlavor = WindowsMsvc2008Flavor;
|
|
|
|
|
else if (abiParts.at(2) == QLatin1String("msvc2010") && m_os == WindowsOS)
|
|
|
|
|
m_osFlavor = WindowsMsvc2010Flavor;
|
2011-02-23 16:47:08 +01:00
|
|
|
else if (abiParts.at(2) == QLatin1String("msys") && m_os == WindowsOS)
|
|
|
|
|
m_osFlavor = WindowsMSysFlavor;
|
|
|
|
|
else if (abiParts.at(2) == QLatin1String("ce") && m_os == WindowsOS)
|
|
|
|
|
m_osFlavor = WindowsCEFlavor;
|
2011-02-01 18:36:00 +01:00
|
|
|
else
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (abiParts.count() >= 4) {
|
|
|
|
|
if (abiParts.at(3) == QLatin1String("unknown"))
|
2011-02-23 16:47:08 +01:00
|
|
|
m_binaryFormat = UnknownFormat;
|
2011-02-01 18:36:00 +01:00
|
|
|
else if (abiParts.at(3) == QLatin1String("elf"))
|
2011-02-23 16:47:08 +01:00
|
|
|
m_binaryFormat = ElfFormat;
|
2011-02-01 18:36:00 +01:00
|
|
|
else if (abiParts.at(3) == QLatin1String("pe"))
|
2011-02-23 16:47:08 +01:00
|
|
|
m_binaryFormat = PEFormat;
|
2011-02-01 18:36:00 +01:00
|
|
|
else if (abiParts.at(3) == QLatin1String("mach_o"))
|
2011-02-23 16:47:08 +01:00
|
|
|
m_binaryFormat = MachOFormat;
|
2011-02-01 18:36:00 +01:00
|
|
|
else if (abiParts.at(3) == QLatin1String("qml_rt"))
|
2011-02-23 16:47:08 +01:00
|
|
|
m_binaryFormat = RuntimeQmlFormat;
|
2011-02-01 18:36:00 +01:00
|
|
|
else
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (abiParts.count() >= 5) {
|
|
|
|
|
const QString &bits = abiParts.at(4);
|
|
|
|
|
if (!bits.endsWith(QLatin1String("bit")))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
bool ok = false;
|
|
|
|
|
int bitCount = bits.left(bits.count() - 3).toInt(&ok);
|
|
|
|
|
if (!ok)
|
|
|
|
|
return;
|
|
|
|
|
if (bitCount != 8 && bitCount != 16 && bitCount != 32 && bitCount != 64)
|
|
|
|
|
return;
|
|
|
|
|
m_wordWidth = bitCount;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Abi::toString() const
|
|
|
|
|
{
|
|
|
|
|
QStringList dn;
|
|
|
|
|
dn << toString(m_architecture);
|
|
|
|
|
dn << toString(m_os);
|
|
|
|
|
dn << toString(m_osFlavor);
|
|
|
|
|
dn << toString(m_binaryFormat);
|
|
|
|
|
dn << toString(m_wordWidth);
|
|
|
|
|
|
|
|
|
|
return dn.join(QLatin1String("-"));
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-10 14:43:44 +01:00
|
|
|
bool Abi::operator != (const Abi &other) const
|
|
|
|
|
{
|
|
|
|
|
return !operator ==(other);
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-01 18:36:00 +01:00
|
|
|
bool Abi::operator == (const Abi &other) const
|
|
|
|
|
{
|
|
|
|
|
return m_architecture == other.m_architecture
|
|
|
|
|
&& m_os == other.m_os
|
|
|
|
|
&& m_osFlavor == other.m_osFlavor
|
|
|
|
|
&& m_binaryFormat == other.m_binaryFormat
|
|
|
|
|
&& m_wordWidth == other.m_wordWidth;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Abi::isCompatibleWith(const Abi &other) const
|
|
|
|
|
{
|
2011-03-28 15:25:50 +02:00
|
|
|
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-*:
|
|
|
|
|
if (!isCompat && architecture() == other.architecture()
|
|
|
|
|
&& os() == other.os()
|
|
|
|
|
&& osFlavor() == GenericLinuxFlavor
|
|
|
|
|
&& other.os() == LinuxOS
|
|
|
|
|
&& binaryFormat() == other.binaryFormat()
|
|
|
|
|
&& wordWidth() == other.wordWidth())
|
|
|
|
|
isCompat = true;
|
|
|
|
|
return isCompat;
|
2011-02-01 18:36:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Abi::isValid() const
|
|
|
|
|
{
|
2011-02-23 16:47:08 +01:00
|
|
|
return m_architecture != UnknownArchitecture
|
|
|
|
|
&& m_os != UnknownOS
|
|
|
|
|
&& m_osFlavor != UnknownFlavor
|
|
|
|
|
&& m_binaryFormat != UnknownFormat
|
2011-02-01 18:36:00 +01:00
|
|
|
&& m_wordWidth != 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Abi::toString(const Architecture &a)
|
|
|
|
|
{
|
|
|
|
|
switch (a) {
|
2011-02-23 16:47:08 +01:00
|
|
|
case ArmArchitecture:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("arm");
|
2011-02-23 16:47:08 +01:00
|
|
|
case X86Architecture:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("x86");
|
2011-02-23 16:47:08 +01:00
|
|
|
case MipsArcitecture:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("mips");
|
2011-02-23 16:47:08 +01:00
|
|
|
case PowerPCArchitecture:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("ppc");
|
2011-02-23 16:47:08 +01:00
|
|
|
case ItaniumArchitecture:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("itanium");
|
2011-02-23 16:47:08 +01:00
|
|
|
case UnknownArchitecture: // fall through!
|
2011-02-01 18:36:00 +01:00
|
|
|
default:
|
|
|
|
|
return QLatin1String("unknown");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Abi::toString(const OS &o)
|
|
|
|
|
{
|
|
|
|
|
switch (o) {
|
2011-02-23 16:47:08 +01:00
|
|
|
case LinuxOS:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("linux");
|
2011-02-23 16:47:08 +01:00
|
|
|
case MacOS:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("macos");
|
2011-02-23 16:47:08 +01:00
|
|
|
case SymbianOS:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("symbian");
|
2011-02-23 16:47:08 +01:00
|
|
|
case UnixOS:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("unix");
|
2011-02-23 16:47:08 +01:00
|
|
|
case WindowsOS:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("windows");
|
2011-02-23 16:47:08 +01:00
|
|
|
case UnknownOS: // fall through!
|
2011-02-01 18:36:00 +01:00
|
|
|
default:
|
|
|
|
|
return QLatin1String("unknown");
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-23 16:47:08 +01:00
|
|
|
QString Abi::toString(const OSFlavor &of)
|
2011-02-01 18:36:00 +01:00
|
|
|
{
|
|
|
|
|
switch (of) {
|
2011-02-23 16:47:08 +01:00
|
|
|
case ProjectExplorer::Abi::GenericLinuxFlavor:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("generic");
|
2011-02-23 16:47:08 +01:00
|
|
|
case ProjectExplorer::Abi::MaemoLinuxFlavor:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("maemo");
|
2011-02-23 16:47:08 +01:00
|
|
|
case ProjectExplorer::Abi::HarmattanLinuxFlavor:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("harmattan");
|
2011-02-23 16:47:08 +01:00
|
|
|
case ProjectExplorer::Abi::MeegoLinuxFlavor:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("meego");
|
2011-02-23 16:47:08 +01:00
|
|
|
case ProjectExplorer::Abi::GenericMacFlavor:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("generic");
|
2011-02-23 16:47:08 +01:00
|
|
|
case ProjectExplorer::Abi::SymbianDeviceFlavor:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("device");
|
2011-02-23 16:47:08 +01:00
|
|
|
case ProjectExplorer::Abi::SymbianEmulatorFlavor:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("emulator");
|
2011-02-23 16:47:08 +01:00
|
|
|
case ProjectExplorer::Abi::GenericUnixFlavor:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("generic");
|
2011-03-18 09:54:35 +01:00
|
|
|
case ProjectExplorer::Abi::WindowsMsvc2005Flavor:
|
|
|
|
|
return QLatin1String("msvc2005");
|
|
|
|
|
case ProjectExplorer::Abi::WindowsMsvc2008Flavor:
|
|
|
|
|
return QLatin1String("msvc2008");
|
|
|
|
|
case ProjectExplorer::Abi::WindowsMsvc2010Flavor:
|
|
|
|
|
return QLatin1String("msvc2010");
|
2011-02-23 16:47:08 +01:00
|
|
|
case ProjectExplorer::Abi::WindowsMSysFlavor:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("msys");
|
2011-02-23 16:47:08 +01:00
|
|
|
case ProjectExplorer::Abi::WindowsCEFlavor:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("ce");
|
2011-02-25 15:27:13 +01:00
|
|
|
case ProjectExplorer::Abi::UnknownFlavor: // fall through!
|
2011-02-01 18:36:00 +01:00
|
|
|
default:
|
|
|
|
|
return QLatin1String("unknown");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Abi::toString(const BinaryFormat &bf)
|
|
|
|
|
{
|
|
|
|
|
switch (bf) {
|
2011-02-23 16:47:08 +01:00
|
|
|
case ElfFormat:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("elf");
|
2011-02-23 16:47:08 +01:00
|
|
|
case PEFormat:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("pe");
|
2011-02-23 16:47:08 +01:00
|
|
|
case MachOFormat:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("mach_o");
|
2011-02-23 16:47:08 +01:00
|
|
|
case RuntimeQmlFormat:
|
2011-02-01 18:36:00 +01:00
|
|
|
return QLatin1String("qml_rt");
|
2011-02-23 16:47:08 +01:00
|
|
|
case UnknownFormat: // fall through!
|
2011-02-01 18:36:00 +01:00
|
|
|
default:
|
|
|
|
|
return QLatin1String("unknown");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Abi::toString(int w)
|
|
|
|
|
{
|
|
|
|
|
if (w == 0)
|
|
|
|
|
return QLatin1String("unknown");
|
|
|
|
|
return QString::fromLatin1("%1bit").arg(w);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Abi Abi::hostAbi()
|
|
|
|
|
{
|
|
|
|
|
Architecture arch = QTC_CPU; // define set by qmake
|
2011-02-23 16:47:08 +01:00
|
|
|
OS os = UnknownOS;
|
|
|
|
|
OSFlavor subos = UnknownFlavor;
|
|
|
|
|
BinaryFormat format = UnknownFormat;
|
2011-02-01 18:36:00 +01:00
|
|
|
|
|
|
|
|
#if defined (Q_OS_WIN)
|
2011-02-23 16:47:08 +01:00
|
|
|
os = WindowsOS;
|
2011-03-18 09:54:35 +01:00
|
|
|
#if _MSC_VER == 1600
|
|
|
|
|
subos = WindowsMsvc2010Flavor;
|
|
|
|
|
#elif _MSC_VER == 1500
|
|
|
|
|
subos = WindowsMsvc2008Flavor;
|
|
|
|
|
#elif _MSC_VER == 1400
|
|
|
|
|
subos = WindowsMsvc2005Flavor;
|
|
|
|
|
#elif defined (mingw32)
|
|
|
|
|
subos = WindowsMSysFlavor;
|
|
|
|
|
#endif
|
2011-02-23 16:47:08 +01:00
|
|
|
format = PEFormat;
|
2011-02-01 18:36:00 +01:00
|
|
|
#elif defined (Q_OS_LINUX)
|
2011-02-23 16:47:08 +01:00
|
|
|
os = LinuxOS;
|
|
|
|
|
subos = GenericLinuxFlavor;
|
|
|
|
|
format = ElfFormat;
|
2011-02-01 18:36:00 +01:00
|
|
|
#elif defined (Q_OS_MAC)
|
2011-02-23 16:47:08 +01:00
|
|
|
os = MacOS;
|
|
|
|
|
subos = GenericMacFlavor;
|
|
|
|
|
format = MachOFormat;
|
2011-02-01 18:36:00 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return Abi(arch, os, subos, format, QSysInfo::WordSize);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QList<Abi> Abi::abisOfBinary(const QString &path)
|
|
|
|
|
{
|
2011-03-21 18:04:24 +01:00
|
|
|
QList<Abi> tmp;
|
2011-02-01 18:36:00 +01:00
|
|
|
if (path.isEmpty())
|
2011-03-21 18:04:24 +01:00
|
|
|
return tmp;
|
2011-02-01 18:36:00 +01:00
|
|
|
|
|
|
|
|
QFile f(path);
|
|
|
|
|
if (!f.exists())
|
2011-03-21 18:04:24 +01:00
|
|
|
return tmp;
|
2011-02-01 18:36:00 +01:00
|
|
|
|
2011-03-03 11:29:07 +01:00
|
|
|
bool windowsStatic = path.endsWith(QLatin1String(".lib"));
|
|
|
|
|
|
2011-02-01 18:36:00 +01:00
|
|
|
f.open(QFile::ReadOnly);
|
|
|
|
|
QByteArray data = f.read(1024);
|
2011-03-02 14:09:18 +01:00
|
|
|
if (data.size() >= 67
|
|
|
|
|
&& static_cast<unsigned char>(data.at(0)) == '!' && static_cast<unsigned char>(data.at(1)) == '<'
|
|
|
|
|
&& static_cast<unsigned char>(data.at(2)) == 'a' && static_cast<unsigned char>(data.at(3)) == 'r'
|
|
|
|
|
&& static_cast<unsigned char>(data.at(4)) == 'c' && static_cast<unsigned char>(data.at(5)) == 'h'
|
|
|
|
|
&& static_cast<unsigned char>(data.at(6)) == '>' && static_cast<unsigned char>(data.at(7)) == 0x0a) {
|
2011-03-21 18:04:24 +01:00
|
|
|
// We got an ar file: possibly a static lib for ELF, PE or Mach-O
|
2011-03-02 14:09:18 +01:00
|
|
|
|
|
|
|
|
data = data.mid(8); // Cut of ar file magic
|
|
|
|
|
quint64 offset = 8;
|
|
|
|
|
|
|
|
|
|
while (!data.isEmpty()) {
|
2011-03-03 11:29:07 +01:00
|
|
|
if ((data.at(58) != 0x60 || data.at(59) != 0x0a)) {
|
2011-03-02 14:09:18 +01:00
|
|
|
qWarning() << path << ": Thought it was an ar-file, but it is not!";
|
2011-02-01 18:36:00 +01:00
|
|
|
break;
|
2011-03-02 14:09:18 +01:00
|
|
|
}
|
2011-02-01 18:36:00 +01:00
|
|
|
|
2011-03-02 14:09:18 +01:00
|
|
|
const QString fileName = QString::fromLocal8Bit(data.mid(0, 16));
|
|
|
|
|
quint64 fileNameOffset = 0;
|
|
|
|
|
if (fileName.startsWith(QLatin1String("#1/")))
|
|
|
|
|
fileNameOffset = fileName.mid(3).toInt();
|
|
|
|
|
const QString fileLength = QString::fromAscii(data.mid(48, 10));
|
2011-03-01 18:04:16 +01:00
|
|
|
|
2011-03-03 11:29:07 +01:00
|
|
|
int toSkip = 60 + fileNameOffset;
|
2011-03-02 14:09:18 +01:00
|
|
|
offset += fileLength.toInt() + 60 /* header */;
|
2011-03-03 11:29:07 +01:00
|
|
|
if (windowsStatic) {
|
|
|
|
|
if (fileName == QLatin1String("/0 "))
|
2011-03-21 18:04:24 +01:00
|
|
|
tmp = parseCoffHeader(data.mid(toSkip, 20));
|
2011-03-03 11:29:07 +01:00
|
|
|
} else {
|
2011-03-21 18:04:24 +01:00
|
|
|
tmp.append(abiOf(data.mid(toSkip)));
|
2011-03-03 11:29:07 +01:00
|
|
|
}
|
2011-03-21 18:04:24 +01:00
|
|
|
if (!tmp.isEmpty()
|
|
|
|
|
&& tmp.at(0).binaryFormat() != Abi::MachOFormat)
|
2011-02-01 18:36:00 +01:00
|
|
|
break;
|
2011-03-01 18:04:16 +01:00
|
|
|
|
2011-03-03 11:29:07 +01:00
|
|
|
f.seek(offset + (offset % 2)); // ar is 2 byte alligned
|
2011-03-02 14:09:18 +01:00
|
|
|
data = f.read(1024);
|
2011-02-01 18:36:00 +01:00
|
|
|
}
|
2011-03-02 14:09:18 +01:00
|
|
|
} else {
|
2011-03-21 18:04:24 +01:00
|
|
|
tmp = abiOf(data);
|
2011-02-01 18:36:00 +01:00
|
|
|
}
|
2011-03-02 14:09:18 +01:00
|
|
|
f.close();
|
|
|
|
|
|
2011-03-21 18:04:24 +01:00
|
|
|
// Remove duplicates:
|
|
|
|
|
QList<Abi> result;
|
|
|
|
|
foreach (const Abi &a, tmp) {
|
|
|
|
|
if (!result.contains(a))
|
|
|
|
|
result.append(a);
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-01 18:36:00 +01:00
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace ProjectExplorer
|
2011-03-21 18:04:24 +01:00
|
|
|
|
|
|
|
|
// Unit tests:
|
|
|
|
|
#ifdef WITH_TESTS
|
|
|
|
|
# include <QTest>
|
|
|
|
|
# include <QtCore/QFileInfo>
|
|
|
|
|
|
|
|
|
|
# include "projectexplorer.h"
|
|
|
|
|
|
|
|
|
|
void ProjectExplorer::ProjectExplorerPlugin::testAbiOfBinary_data()
|
|
|
|
|
{
|
|
|
|
|
QTest::addColumn<QString>("file");
|
|
|
|
|
QTest::addColumn<QStringList>("abis");
|
|
|
|
|
|
|
|
|
|
QTest::newRow("no file")
|
|
|
|
|
<< QString()
|
|
|
|
|
<< (QStringList());
|
|
|
|
|
QTest::newRow("non existing file")
|
|
|
|
|
<< QString::fromLatin1("/does/not/exist")
|
|
|
|
|
<< (QStringList());
|
|
|
|
|
|
|
|
|
|
// Set up prefix for test data now that we can be sure to have some tests to run:
|
|
|
|
|
QString prefix = qgetenv("QTC_TEST_EXTRADATALOCATION");
|
|
|
|
|
if (prefix.isEmpty())
|
|
|
|
|
return;
|
|
|
|
|
QFileInfo fi(prefix);
|
|
|
|
|
if (!fi.exists() || !fi.isDir())
|
|
|
|
|
return;
|
|
|
|
|
prefix = fi.absoluteFilePath();
|
|
|
|
|
|
|
|
|
|
QTest::newRow("text file")
|
|
|
|
|
<< QString::fromLatin1("%1/broken/text.txt").arg(prefix)
|
|
|
|
|
<< (QStringList());
|
|
|
|
|
|
|
|
|
|
QTest::newRow("static QtCore: win msvc2008")
|
|
|
|
|
<< QString::fromLatin1("%1/abi/static/win_msvc2008_release.lib").arg(prefix)
|
|
|
|
|
<< (QStringList() << QString::fromLatin1("x86-windows-unknown-pe-32bit"));
|
|
|
|
|
QTest::newRow("static QtCore: win msvc2008 (debug)")
|
|
|
|
|
<< QString::fromLatin1("%1/abi/static/win_msvc2008_debug.lib").arg(prefix)
|
|
|
|
|
<< (QStringList() << QString::fromLatin1("x86-windows-unknown-pe-32bit"));
|
|
|
|
|
QTest::newRow("static QtCore: mac (debug)")
|
|
|
|
|
<< QString::fromLatin1("%1/abi/static/mac-32bit-debug.a").arg(prefix)
|
|
|
|
|
<< (QStringList() << QString::fromLatin1("x86-macos-generic-mach_o-32bit"));
|
|
|
|
|
QTest::newRow("static QtCore: linux 32bit")
|
|
|
|
|
<< QString::fromLatin1("%1/abi/static/linux-32bit-release.a").arg(prefix)
|
|
|
|
|
<< (QStringList() << QString::fromLatin1("x86-linux-generic-elf-32bit"));
|
|
|
|
|
QTest::newRow("static QtCore: linux 64bit")
|
|
|
|
|
<< QString::fromLatin1("%1/abi/static/linux-64bit-release.a").arg(prefix)
|
|
|
|
|
<< (QStringList() << QString::fromLatin1("x86-linux-generic-elf-64bit"));
|
|
|
|
|
|
|
|
|
|
QTest::newRow("static stdc++: mac fat")
|
|
|
|
|
<< QString::fromLatin1("%1/abi/static/mac-fat.a").arg(prefix)
|
|
|
|
|
<< (QStringList() << QString::fromLatin1("x86-macos-generic-mach_o-32bit")
|
|
|
|
|
<< QString::fromLatin1("ppc-macos-generic-mach_o-32bit")
|
|
|
|
|
<< QString::fromLatin1("x86-macos-generic-mach_o-64bit"));
|
|
|
|
|
|
|
|
|
|
QTest::newRow("dynamic QtCore: symbian")
|
|
|
|
|
<< QString::fromLatin1("%1/abi/dynamic/symbian.dll").arg(prefix)
|
|
|
|
|
<< (QStringList() << QString::fromLatin1("arm-symbian-device-elf-32bit"));
|
|
|
|
|
QTest::newRow("dynamic QtCore: win msvc2010 64bit")
|
|
|
|
|
<< QString::fromLatin1("%1/abi/dynamic/win-msvc2010-64bit.dll").arg(prefix)
|
|
|
|
|
<< (QStringList() << QString::fromLatin1("x86-windows-msvc2010-pe-64bit"));
|
|
|
|
|
QTest::newRow("dynamic QtCore: win msvc2008 32bit")
|
|
|
|
|
<< QString::fromLatin1("%1/abi/dynamic/win-msvc2008-32bit.dll").arg(prefix)
|
|
|
|
|
<< (QStringList() << QString::fromLatin1("x86-windows-msvc2008-pe-32bit"));
|
|
|
|
|
QTest::newRow("dynamic QtCore: win msvc2005 32bit")
|
|
|
|
|
<< QString::fromLatin1("%1/abi/dynamic/win-msvc2005-32bit.dll").arg(prefix)
|
|
|
|
|
<< (QStringList() << QString::fromLatin1("x86-windows-msvc2005-pe-32bit"));
|
|
|
|
|
QTest::newRow("dynamic QtCore: win msys 32bit")
|
|
|
|
|
<< QString::fromLatin1("%1/abi/dynamic/win-mingw-32bit.dll").arg(prefix)
|
|
|
|
|
<< (QStringList() << QString::fromLatin1("x86-windows-msys-pe-32bit"));
|
|
|
|
|
QTest::newRow("dynamic QtCore: win msys 32bit")
|
|
|
|
|
<< QString::fromLatin1("%1/abi/dynamic/win-mingw-32bit.dll").arg(prefix)
|
|
|
|
|
<< (QStringList() << QString::fromLatin1("x86-windows-msys-pe-32bit"));
|
2011-03-23 15:25:38 +01:00
|
|
|
QTest::newRow("dynamic stdc++: mac fat")
|
2011-03-21 18:04:24 +01:00
|
|
|
<< QString::fromLatin1("%1/abi/dynamic/mac-fat.dylib").arg(prefix)
|
|
|
|
|
<< (QStringList() << QString::fromLatin1("x86-macos-generic-mach_o-32bit")
|
|
|
|
|
<< QString::fromLatin1("ppc-macos-generic-mach_o-32bit")
|
|
|
|
|
<< QString::fromLatin1("x86-macos-generic-mach_o-64bit"));
|
2011-03-23 15:25:38 +01:00
|
|
|
QTest::newRow("dynamic QtCore: arm linux 32bit")
|
|
|
|
|
<< QString::fromLatin1("%1/abi/dynamic/arm-linux.so").arg(prefix)
|
|
|
|
|
<< (QStringList() << QString::fromLatin1("arm-linux-generic-elf-32bit"));
|
2011-03-21 18:04:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ProjectExplorer::ProjectExplorerPlugin::testAbiOfBinary()
|
|
|
|
|
{
|
|
|
|
|
QFETCH(QString, file);
|
|
|
|
|
QFETCH(QStringList, abis);
|
|
|
|
|
|
|
|
|
|
QList<ProjectExplorer::Abi> result = Abi::abisOfBinary(file);
|
|
|
|
|
QCOMPARE(result.count(), abis.count());
|
|
|
|
|
for (int i = 0; i < abis.count(); ++i)
|
|
|
|
|
QCOMPARE(result.at(i).toString(), abis.at(i));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|