PageRenderTime 532ms CodeModel.GetById 36ms RepoModel.GetById 3ms app.codeStats 0ms

/src/plugins/projectexplorer/gcctoolchain.cpp

https://bitbucket.org/kpozn/qt-creator-py-reborn
C++ | 1180 lines | 936 code | 170 blank | 74 comment | 272 complexity | 3b88862e8496904299ee2024d147f86a MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**************************************************************************
  2. **
  3. ** This file is part of Qt Creator
  4. **
  5. ** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
  6. **
  7. ** Contact: Nokia Corporation (qt-info@nokia.com)
  8. **
  9. **
  10. ** GNU Lesser General Public License Usage
  11. **
  12. ** This file may be used under the terms of the GNU Lesser General Public
  13. ** License version 2.1 as published by the Free Software Foundation and
  14. ** appearing in the file LICENSE.LGPL included in the packaging of this file.
  15. ** Please review the following information to ensure the GNU Lesser General
  16. ** Public License version 2.1 requirements will be met:
  17. ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
  18. **
  19. ** In addition, as a special exception, Nokia gives you certain additional
  20. ** rights. These rights are described in the Nokia Qt LGPL Exception
  21. ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
  22. **
  23. ** Other Usage
  24. **
  25. ** Alternatively, this file may be used in accordance with the terms and
  26. ** conditions contained in a signed written agreement between you and Nokia.
  27. **
  28. ** If you have questions regarding the use of this file, please contact
  29. ** Nokia at qt-info@nokia.com.
  30. **
  31. **************************************************************************/
  32. #include "gcctoolchain.h"
  33. #include "clangparser.h"
  34. #include "gcctoolchainfactories.h"
  35. #include "gccparser.h"
  36. #include "linuxiccparser.h"
  37. #include "projectexplorerconstants.h"
  38. #include "toolchainmanager.h"
  39. #include <utils/detailswidget.h>
  40. #include <utils/environment.h>
  41. #include <utils/synchronousprocess.h>
  42. #include <utils/qtcassert.h>
  43. #include <utils/pathchooser.h>
  44. #include <QBuffer>
  45. #include <QCoreApplication>
  46. #include <QFileInfo>
  47. #include <QProcess>
  48. #include <QScopedPointer>
  49. #include <QComboBox>
  50. #include <QFormLayout>
  51. #include <QLabel>
  52. namespace ProjectExplorer {
  53. // --------------------------------------------------------------------------
  54. // Helpers:
  55. // --------------------------------------------------------------------------
  56. static const char compilerCommandKeyC[] = "ProjectExplorer.GccToolChain.Path";
  57. static const char targetAbiKeyC[] = "ProjectExplorer.GccToolChain.TargetAbi";
  58. static const char supportedAbisKeyC[] = "ProjectExplorer.GccToolChain.SupportedAbis";
  59. static const char LEGACY_MAEMO_ID[] = "Qt4ProjectManager.ToolChain.Maemo:";
  60. static QByteArray runGcc(const Utils::FileName &gcc, const QStringList &arguments, const QStringList &env)
  61. {
  62. if (gcc.isEmpty() || !gcc.toFileInfo().isExecutable())
  63. return QByteArray();
  64. QProcess cpp;
  65. // Force locale: This function is used only to detect settings inside the tool chain, so this is save.
  66. QStringList environment(env);
  67. environment.append(QLatin1String("LC_ALL=C"));
  68. cpp.setEnvironment(environment);
  69. cpp.start(gcc.toString(), arguments);
  70. if (!cpp.waitForStarted()) {
  71. qWarning("%s: Cannot start '%s': %s", Q_FUNC_INFO, qPrintable(gcc.toUserOutput()),
  72. qPrintable(cpp.errorString()));
  73. return QByteArray();
  74. }
  75. cpp.closeWriteChannel();
  76. if (!cpp.waitForFinished()) {
  77. Utils::SynchronousProcess::stopProcess(cpp);
  78. qWarning("%s: Timeout running '%s'.", Q_FUNC_INFO, qPrintable(gcc.toUserOutput()));
  79. return QByteArray();
  80. }
  81. if (cpp.exitStatus() != QProcess::NormalExit) {
  82. qWarning("%s: '%s' crashed.", Q_FUNC_INFO, qPrintable(gcc.toUserOutput()));
  83. return QByteArray();
  84. }
  85. return cpp.readAllStandardOutput() + '\n' + cpp.readAllStandardError();
  86. }
  87. static QByteArray gccPredefinedMacros(const Utils::FileName &gcc, const QStringList &args, const QStringList &env)
  88. {
  89. QStringList arguments;
  90. arguments << QLatin1String("-xc++")
  91. << QLatin1String("-E")
  92. << QLatin1String("-dM");
  93. foreach (const QString &a, args) {
  94. if (a == QLatin1String("-m128bit-long-double") || a == QLatin1String("-m32")
  95. || a == QLatin1String("-m3dnow") || a == QLatin1String("-m3dnowa")
  96. || a == QLatin1String("-m64") || a == QLatin1String("-m96bit-long-double")
  97. || a == QLatin1String("-mabm") || a == QLatin1String("-maes")
  98. || a.startsWith(QLatin1String("-march=")) || a == QLatin1String("-mavx")
  99. || a.startsWith(QLatin1String("-masm=")) || a == QLatin1String("-mcx16")
  100. || a == QLatin1String("-mfma") || a == QLatin1String("-mfma4")
  101. || a == QLatin1String("-mlwp") || a == QLatin1String("-mpclmul")
  102. || a == QLatin1String("-mpopcnt") || a == QLatin1String("-msse")
  103. || a == QLatin1String("-msse2") || a == QLatin1String("-msse2avx")
  104. || a == QLatin1String("-msse3") || a == QLatin1String("-msse4")
  105. || a == QLatin1String("-msse4.1") || a == QLatin1String("-msse4.2")
  106. || a == QLatin1String("-msse4a") || a == QLatin1String("-mssse3")
  107. || a.startsWith(QLatin1String("-mtune=")) || a == QLatin1String("-mxop")
  108. || a == QLatin1String("-Os") || a == QLatin1String("-O0") || a == QLatin1String("-O1")
  109. || a == QLatin1String("-O2") || a == QLatin1String("-O3")
  110. || a == QLatin1String("-ffinite-math-only") || a == QLatin1String("-fshort-double")
  111. || a == QLatin1String("-fshort-wchar") || a == QLatin1String("-fsignaling-nans")
  112. || a.startsWith(QLatin1String("-std=")) || a.startsWith(QLatin1String("-specs="))
  113. || a == QLatin1String("-ansi")
  114. || a.startsWith(QLatin1String("-D")) || a.startsWith(QLatin1String("-U"))
  115. || a == QLatin1String("-undef"))
  116. arguments << a;
  117. }
  118. arguments << QLatin1String("-");
  119. QByteArray predefinedMacros = runGcc(gcc, arguments, env);
  120. #ifdef Q_OS_MAC
  121. // Turn off flag indicating Apple's blocks support
  122. const QByteArray blocksDefine("#define __BLOCKS__ 1");
  123. const QByteArray blocksUndefine("#undef __BLOCKS__");
  124. const int idx = predefinedMacros.indexOf(blocksDefine);
  125. if (idx != -1) {
  126. predefinedMacros.replace(idx, blocksDefine.length(), blocksUndefine);
  127. }
  128. // Define __strong and __weak (used for Apple's GC extension of C) to be empty
  129. predefinedMacros.append("#define __strong\n");
  130. predefinedMacros.append("#define __weak\n");
  131. #endif // Q_OS_MAC
  132. return predefinedMacros;
  133. }
  134. QList<HeaderPath> GccToolChain::gccHeaderPaths(const Utils::FileName &gcc, const QStringList &env, const QString &sysrootPath)
  135. {
  136. QList<HeaderPath> systemHeaderPaths;
  137. QStringList arguments;
  138. if (!sysrootPath.isEmpty())
  139. arguments.append(QString::fromLatin1("--sysroot=%1").arg(sysrootPath));
  140. arguments << QLatin1String("-xc++")
  141. << QLatin1String("-E")
  142. << QLatin1String("-v")
  143. << QLatin1String("-");
  144. QByteArray line;
  145. QByteArray data = runGcc(gcc, arguments, env);
  146. QBuffer cpp(&data);
  147. cpp.open(QIODevice::ReadOnly);
  148. while (cpp.canReadLine()) {
  149. line = cpp.readLine();
  150. if (line.startsWith("#include"))
  151. break;
  152. }
  153. if (!line.isEmpty() && line.startsWith("#include")) {
  154. HeaderPath::Kind kind = HeaderPath::UserHeaderPath;
  155. while (cpp.canReadLine()) {
  156. line = cpp.readLine();
  157. if (line.startsWith("#include")) {
  158. kind = HeaderPath::GlobalHeaderPath;
  159. } else if (! line.isEmpty() && QChar(QLatin1Char(line.at(0))).isSpace()) {
  160. HeaderPath::Kind thisHeaderKind = kind;
  161. line = line.trimmed();
  162. const int index = line.indexOf(" (framework directory)");
  163. if (index != -1) {
  164. line.truncate(index);
  165. thisHeaderKind = HeaderPath::FrameworkHeaderPath;
  166. }
  167. systemHeaderPaths.append(HeaderPath(QFile::decodeName(line), thisHeaderKind));
  168. } else if (line.startsWith("End of search list.")) {
  169. break;
  170. } else {
  171. qWarning("%s: Ignoring line: %s", __FUNCTION__, line.constData());
  172. }
  173. }
  174. }
  175. return systemHeaderPaths;
  176. }
  177. static QList<ProjectExplorer::Abi> guessGccAbi(const QString &m)
  178. {
  179. QList<ProjectExplorer::Abi> abiList;
  180. QString machine = m.toLower();
  181. if (machine.isEmpty())
  182. return abiList;
  183. QStringList parts = machine.split(QRegExp(QLatin1String("[ /-]")));
  184. ProjectExplorer::Abi::Architecture arch = ProjectExplorer::Abi::UnknownArchitecture;
  185. ProjectExplorer::Abi::OS os = ProjectExplorer::Abi::UnknownOS;
  186. ProjectExplorer::Abi::OSFlavor flavor = ProjectExplorer::Abi::UnknownFlavor;
  187. ProjectExplorer::Abi::BinaryFormat format = ProjectExplorer::Abi::UnknownFormat;
  188. int width = 0;
  189. int unknownCount = 0;
  190. foreach (const QString &p, parts) {
  191. if (p == QLatin1String("unknown") || p == QLatin1String("pc") || p == QLatin1String("none")
  192. || p == QLatin1String("gnu") || p == QLatin1String("uclibc")
  193. || p == QLatin1String("86_64") || p == QLatin1String("redhat") || p == QLatin1String("gnueabi")) {
  194. continue;
  195. } else if (p == QLatin1String("i386") || p == QLatin1String("i486") || p == QLatin1String("i586")
  196. || p == QLatin1String("i686") || p == QLatin1String("x86")) {
  197. arch = ProjectExplorer::Abi::X86Architecture;
  198. width = 32;
  199. } else if (p.startsWith(QLatin1String("arm"))) {
  200. arch = ProjectExplorer::Abi::ArmArchitecture;
  201. width = 32;
  202. } else if (p == QLatin1String("mipsel")) {
  203. arch = ProjectExplorer::Abi::MipsArchitecture;
  204. width = 32;
  205. } else if (p == QLatin1String("x86_64") || p == QLatin1String("amd64")) {
  206. arch = ProjectExplorer::Abi::X86Architecture;
  207. width = 64;
  208. } else if (p == QLatin1String("powerpc")) {
  209. arch = ProjectExplorer::Abi::PowerPCArchitecture;
  210. } else if (p == QLatin1String("w64")) {
  211. width = 64;
  212. } else if (p == QLatin1String("linux") || p == QLatin1String("linux6e")) {
  213. os = ProjectExplorer::Abi::LinuxOS;
  214. if (flavor == Abi::UnknownFlavor)
  215. flavor = ProjectExplorer::Abi::GenericLinuxFlavor;
  216. format = ProjectExplorer::Abi::ElfFormat;
  217. } else if (p.startsWith(QLatin1String("freebsd"))) {
  218. os = ProjectExplorer::Abi::BsdOS;
  219. if (flavor == Abi::UnknownFlavor)
  220. flavor = ProjectExplorer::Abi::FreeBsdFlavor;
  221. format = ProjectExplorer::Abi::ElfFormat;
  222. } else if (p == QLatin1String("meego")) {
  223. os = ProjectExplorer::Abi::LinuxOS;
  224. flavor = ProjectExplorer::Abi::MeegoLinuxFlavor;
  225. format = ProjectExplorer::Abi::ElfFormat;
  226. } else if (p == QLatin1String("symbianelf")) {
  227. os = ProjectExplorer::Abi::SymbianOS;
  228. flavor = ProjectExplorer::Abi::SymbianDeviceFlavor;
  229. format = ProjectExplorer::Abi::ElfFormat;
  230. width = 32;
  231. } else if (p == QLatin1String("mingw32") || p == QLatin1String("win32") || p == QLatin1String("mingw32msvc")) {
  232. arch = ProjectExplorer::Abi::X86Architecture;
  233. os = ProjectExplorer::Abi::WindowsOS;
  234. flavor = ProjectExplorer::Abi::WindowsMSysFlavor;
  235. format = ProjectExplorer::Abi::PEFormat;
  236. if (width == 0)
  237. width = 32;
  238. } else if (p == QLatin1String("apple")) {
  239. os = ProjectExplorer::Abi::MacOS;
  240. flavor = ProjectExplorer::Abi::GenericMacFlavor;
  241. format = ProjectExplorer::Abi::MachOFormat;
  242. } else if (p == QLatin1String("darwin10")) {
  243. width = 64;
  244. } else if (p == QLatin1String("darwin9")) {
  245. width = 32;
  246. } else if (p == QLatin1String("gnueabi")) {
  247. format = ProjectExplorer::Abi::ElfFormat;
  248. } else {
  249. ++unknownCount;
  250. }
  251. }
  252. if (unknownCount == parts.count())
  253. return abiList;
  254. if (os == Abi::MacOS && arch != Abi::ArmArchitecture) {
  255. // Apple does PPC and x86!
  256. abiList << ProjectExplorer::Abi(arch, os, flavor, format, width);
  257. abiList << ProjectExplorer::Abi(arch, os, flavor, format, width == 64 ? 32 : 64);
  258. abiList << ProjectExplorer::Abi(arch == Abi::X86Architecture ? Abi::PowerPCArchitecture : Abi::X86Architecture, os, flavor, format, width);
  259. abiList << ProjectExplorer::Abi(arch == Abi::X86Architecture ? Abi::PowerPCArchitecture : Abi::X86Architecture, os, flavor, format, width == 64 ? 32 : 64);
  260. } else if (width == 64) {
  261. abiList << ProjectExplorer::Abi(arch, os, flavor, format, width);
  262. abiList << ProjectExplorer::Abi(arch, os, flavor, format, 32);
  263. } else {
  264. abiList << ProjectExplorer::Abi(arch, os, flavor, format, width);
  265. }
  266. return abiList;
  267. }
  268. static QList<ProjectExplorer::Abi> guessGccAbi(const Utils::FileName &path, const QStringList &env)
  269. {
  270. if (path.isEmpty())
  271. return QList<ProjectExplorer::Abi>();
  272. QStringList arguments(QLatin1String("-dumpmachine"));
  273. QString machine = QString::fromLocal8Bit(runGcc(path, arguments, env)).trimmed();
  274. return guessGccAbi(machine);
  275. }
  276. static QString gccVersion(const Utils::FileName &path, const QStringList &env)
  277. {
  278. QStringList arguments(QLatin1String("-dumpversion"));
  279. return QString::fromLocal8Bit(runGcc(path, arguments, env)).trimmed();
  280. }
  281. // --------------------------------------------------------------------------
  282. // GccToolChain
  283. // --------------------------------------------------------------------------
  284. GccToolChain::GccToolChain(bool autodetect) :
  285. ToolChain(QLatin1String(Constants::GCC_TOOLCHAIN_ID), autodetect)
  286. { }
  287. GccToolChain::GccToolChain(const QString &id, bool autodetect) :
  288. ToolChain(id, autodetect)
  289. { }
  290. GccToolChain::GccToolChain(const GccToolChain &tc) :
  291. ToolChain(tc),
  292. m_predefinedMacros(tc.predefinedMacros(QStringList())),
  293. m_compilerCommand(tc.compilerCommand()),
  294. m_targetAbi(tc.m_targetAbi),
  295. m_supportedAbis(tc.m_supportedAbis),
  296. m_headerPaths(tc.m_headerPaths),
  297. m_version(tc.m_version)
  298. { }
  299. QString GccToolChain::defaultDisplayName() const
  300. {
  301. if (!m_targetAbi.isValid())
  302. return typeDisplayName();
  303. return QString::fromLatin1("%1 (%2 %3)").arg(typeDisplayName(),
  304. ProjectExplorer::Abi::toString(m_targetAbi.architecture()),
  305. ProjectExplorer::Abi::toString(m_targetAbi.wordWidth()));
  306. }
  307. QString GccToolChain::type() const
  308. {
  309. return QLatin1String("gcc");
  310. }
  311. QString GccToolChain::typeDisplayName() const
  312. {
  313. return Internal::GccToolChainFactory::tr("GCC");
  314. }
  315. Abi GccToolChain::targetAbi() const
  316. {
  317. return m_targetAbi;
  318. }
  319. QString GccToolChain::version() const
  320. {
  321. if (m_version.isEmpty())
  322. m_version = detectVersion();
  323. return m_version;
  324. }
  325. void GccToolChain::setTargetAbi(const Abi &abi)
  326. {
  327. if (abi == m_targetAbi)
  328. return;
  329. m_targetAbi = abi;
  330. toolChainUpdated();
  331. }
  332. QList<Abi> GccToolChain::supportedAbis() const
  333. {
  334. return m_supportedAbis;
  335. }
  336. bool GccToolChain::isValid() const
  337. {
  338. return !m_compilerCommand.isNull();
  339. }
  340. QByteArray GccToolChain::predefinedMacros(const QStringList &cxxflags) const
  341. {
  342. if (m_predefinedMacros.isEmpty()) {
  343. // Using a clean environment breaks ccache/distcc/etc.
  344. Utils::Environment env = Utils::Environment::systemEnvironment();
  345. addToEnvironment(env);
  346. m_predefinedMacros = gccPredefinedMacros(m_compilerCommand, cxxflags, env.toStringList());
  347. }
  348. return m_predefinedMacros;
  349. }
  350. ProjectExplorer::ToolChain::CompilerFlags GccToolChain::compilerFlags(const QStringList &cxxflags) const
  351. {
  352. if (cxxflags.contains("-std=c++0x") || cxxflags.contains("-std=gnu++0x"))
  353. return STD_CXX11;
  354. return NO_FLAGS;
  355. }
  356. QList<HeaderPath> GccToolChain::systemHeaderPaths() const
  357. {
  358. if (m_headerPaths.isEmpty()) {
  359. // Using a clean environment breaks ccache/distcc/etc.
  360. Utils::Environment env = Utils::Environment::systemEnvironment();
  361. addToEnvironment(env);
  362. m_headerPaths = gccHeaderPaths(m_compilerCommand, env.toStringList());
  363. }
  364. return m_headerPaths;
  365. }
  366. void GccToolChain::addToEnvironment(Utils::Environment &env) const
  367. {
  368. if (!m_compilerCommand.isEmpty()) {
  369. Utils::FileName path = m_compilerCommand.parentDir();
  370. env.prependOrSetPath(path.toString());
  371. }
  372. }
  373. QList<Utils::FileName> GccToolChain::suggestedMkspecList() const
  374. {
  375. Abi abi = targetAbi();
  376. Abi host = Abi::hostAbi();
  377. // Cross compile: Leave the mkspec alone!
  378. if (abi.architecture() != host.architecture()
  379. || abi.os() != host.os()
  380. || abi.osFlavor() != host.osFlavor()) // Note: This can fail:-(
  381. return QList<Utils::FileName>();
  382. if (abi.os() == Abi::MacOS) {
  383. QString v = version();
  384. // prefer versioned g++ on mac. This is required to enable building for older Mac OS versions
  385. if (v.startsWith(QLatin1String("4.0")) && m_compilerCommand.endsWith(QLatin1String("-4.0")))
  386. return QList<Utils::FileName>() << Utils::FileName::fromString(QLatin1String("macx-g++40"));
  387. if (v.startsWith(QLatin1String("4.2")) && m_compilerCommand.endsWith(QLatin1String("-4.2")))
  388. return QList<Utils::FileName>() << Utils::FileName::fromString(QLatin1String("macx-g++42"));
  389. return QList<Utils::FileName>() << Utils::FileName::fromString(QLatin1String("macx-g++"));
  390. }
  391. if (abi.os() == Abi::LinuxOS) {
  392. if (abi.osFlavor() != Abi::GenericLinuxFlavor)
  393. return QList<Utils::FileName>(); // most likely not a desktop, so leave the mkspec alone.
  394. if (abi.wordWidth() == host.wordWidth())
  395. return QList<Utils::FileName>() << Utils::FileName::fromString(QLatin1String("linux-g++")); // no need to explicitly set the word width
  396. return QList<Utils::FileName>() << Utils::FileName::fromString(QLatin1String("linux-g++-") + QString::number(m_targetAbi.wordWidth()));
  397. }
  398. if (abi.os() == Abi::BsdOS && abi.osFlavor() == Abi::FreeBsdFlavor)
  399. return QList<Utils::FileName>() << Utils::FileName::fromString(QLatin1String("freebsd-g++"));
  400. return QList<Utils::FileName>();
  401. }
  402. QString GccToolChain::makeCommand() const
  403. {
  404. return QLatin1String("make");
  405. }
  406. IOutputParser *GccToolChain::outputParser() const
  407. {
  408. return new GccParser;
  409. }
  410. void GccToolChain::setCompilerCommand(const Utils::FileName &path)
  411. {
  412. if (path == m_compilerCommand)
  413. return;
  414. bool resetDisplayName = displayName() == defaultDisplayName();
  415. m_compilerCommand = path;
  416. Abi currentAbi = m_targetAbi;
  417. m_supportedAbis = detectSupportedAbis();
  418. m_targetAbi = Abi();
  419. if (!m_supportedAbis.isEmpty()) {
  420. if (m_supportedAbis.contains(currentAbi))
  421. m_targetAbi = currentAbi;
  422. else
  423. m_targetAbi = m_supportedAbis.at(0);
  424. }
  425. if (resetDisplayName)
  426. setDisplayName(defaultDisplayName()); // calls toolChainUpdated()!
  427. else
  428. toolChainUpdated();
  429. }
  430. Utils::FileName GccToolChain::compilerCommand() const
  431. {
  432. return m_compilerCommand;
  433. }
  434. ToolChain *GccToolChain::clone() const
  435. {
  436. return new GccToolChain(*this);
  437. }
  438. QVariantMap GccToolChain::toMap() const
  439. {
  440. QVariantMap data = ToolChain::toMap();
  441. data.insert(QLatin1String(compilerCommandKeyC), m_compilerCommand.toString());
  442. data.insert(QLatin1String(targetAbiKeyC), m_targetAbi.toString());
  443. QStringList abiList;
  444. foreach (const ProjectExplorer::Abi &a, m_supportedAbis)
  445. abiList.append(a.toString());
  446. data.insert(QLatin1String(supportedAbisKeyC), abiList);
  447. return data;
  448. }
  449. bool GccToolChain::fromMap(const QVariantMap &data)
  450. {
  451. if (!ToolChain::fromMap(data))
  452. return false;
  453. m_compilerCommand = Utils::FileName::fromString(data.value(QLatin1String(compilerCommandKeyC)).toString());
  454. m_targetAbi = Abi(data.value(QLatin1String(targetAbiKeyC)).toString());
  455. QStringList abiList = data.value(QLatin1String(supportedAbisKeyC)).toStringList();
  456. m_supportedAbis.clear();
  457. foreach (const QString &a, abiList) {
  458. ProjectExplorer::Abi abi(a);
  459. if (!abi.isValid())
  460. continue;
  461. m_supportedAbis.append(abi);
  462. }
  463. return true;
  464. }
  465. bool GccToolChain::operator ==(const ToolChain &other) const
  466. {
  467. if (!ToolChain::operator ==(other))
  468. return false;
  469. const GccToolChain *gccTc = static_cast<const GccToolChain *>(&other);
  470. return m_compilerCommand == gccTc->m_compilerCommand && m_targetAbi == gccTc->m_targetAbi;
  471. }
  472. ToolChainConfigWidget *GccToolChain::configurationWidget()
  473. {
  474. return new Internal::GccToolChainConfigWidget(this);
  475. }
  476. void GccToolChain::updateSupportedAbis() const
  477. {
  478. if (m_supportedAbis.isEmpty())
  479. m_supportedAbis = detectSupportedAbis();
  480. }
  481. QList<Abi> GccToolChain::detectSupportedAbis() const
  482. {
  483. Utils::Environment env = Utils::Environment::systemEnvironment();
  484. addToEnvironment(env);
  485. return guessGccAbi(m_compilerCommand, env.toStringList());
  486. }
  487. QString GccToolChain::detectVersion() const
  488. {
  489. Utils::Environment env = Utils::Environment::systemEnvironment();
  490. addToEnvironment(env);
  491. return gccVersion(m_compilerCommand, env.toStringList());
  492. }
  493. // --------------------------------------------------------------------------
  494. // GccToolChainFactory
  495. // --------------------------------------------------------------------------
  496. QString Internal::GccToolChainFactory::displayName() const
  497. {
  498. return tr("GCC");
  499. }
  500. QString Internal::GccToolChainFactory::id() const
  501. {
  502. return QLatin1String(Constants::GCC_TOOLCHAIN_ID);
  503. }
  504. bool Internal::GccToolChainFactory::canCreate()
  505. {
  506. return true;
  507. }
  508. ToolChain *Internal::GccToolChainFactory::create()
  509. {
  510. return createToolChain(false);
  511. }
  512. QList<ToolChain *> Internal::GccToolChainFactory::autoDetect()
  513. {
  514. QList<ToolChain *> tcs;
  515. #ifdef Q_OS_MAC
  516. // Old mac compilers needed to support macx-gccXY mkspecs:
  517. tcs.append(autoDetectToolchains(QLatin1String("g++-4.0"), Abi::hostAbi()));
  518. tcs.append(autoDetectToolchains(QLatin1String("g++-4.2"), Abi::hostAbi()));
  519. #endif
  520. tcs.append(autoDetectToolchains(QLatin1String("g++"), Abi::hostAbi()));
  521. return tcs;
  522. }
  523. // Used by the ToolChainManager to restore user-generated tool chains
  524. bool Internal::GccToolChainFactory::canRestore(const QVariantMap &data)
  525. {
  526. const QString id = idFromMap(data);
  527. return id.startsWith(QLatin1String(Constants::GCC_TOOLCHAIN_ID) + QLatin1Char(':'))
  528. || id.startsWith(QLatin1String(LEGACY_MAEMO_ID));
  529. }
  530. ToolChain *Internal::GccToolChainFactory::restore(const QVariantMap &data)
  531. {
  532. GccToolChain *tc = new GccToolChain(false);
  533. // Updating from 2.5:
  534. QVariantMap updated = data;
  535. QString id = idFromMap(updated);
  536. if (id.startsWith(LEGACY_MAEMO_ID)) {
  537. id = QString::fromLatin1(Constants::GCC_TOOLCHAIN_ID).append(id.mid(id.indexOf(QLatin1Char(':'))));
  538. idToMap(updated, id);
  539. autoDetectionToMap(updated, false);
  540. }
  541. if (tc->fromMap(updated))
  542. return tc;
  543. delete tc;
  544. return 0;
  545. }
  546. GccToolChain *Internal::GccToolChainFactory::createToolChain(bool autoDetect)
  547. {
  548. return new GccToolChain(autoDetect);
  549. }
  550. QList<ToolChain *> Internal::GccToolChainFactory::autoDetectToolchains(const QString &compiler,
  551. const Abi &requiredAbi)
  552. {
  553. QList<ToolChain *> result;
  554. const Utils::Environment systemEnvironment = Utils::Environment::systemEnvironment();
  555. const Utils::FileName compilerPath = Utils::FileName::fromString(systemEnvironment.searchInPath(compiler));
  556. if (compilerPath.isEmpty())
  557. return result;
  558. QList<Abi> abiList = guessGccAbi(compilerPath, systemEnvironment.toStringList());
  559. if (!abiList.contains(requiredAbi)) {
  560. if (requiredAbi.wordWidth() != 64
  561. || !abiList.contains(Abi(requiredAbi.architecture(), requiredAbi.os(), requiredAbi.osFlavor(),
  562. requiredAbi.binaryFormat(), 32)))
  563. return result;
  564. }
  565. foreach (const Abi &abi, abiList) {
  566. QScopedPointer<GccToolChain> tc(createToolChain(true));
  567. if (tc.isNull())
  568. return result;
  569. tc->setCompilerCommand(compilerPath);
  570. tc->setTargetAbi(abi);
  571. tc->setDisplayName(tc->defaultDisplayName()); // reset displayname
  572. result.append(tc.take());
  573. }
  574. return result;
  575. }
  576. // --------------------------------------------------------------------------
  577. // GccToolChainConfigWidget
  578. // --------------------------------------------------------------------------
  579. Internal::GccToolChainConfigWidget::GccToolChainConfigWidget(GccToolChain *tc) :
  580. ToolChainConfigWidget(tc),
  581. m_compilerCommand(new Utils::PathChooser),
  582. m_abiWidget(new AbiWidget),
  583. m_isReadOnly(false)
  584. {
  585. Q_ASSERT(tc);
  586. Utils::DetailsWidget *details = new Utils::DetailsWidget(this);
  587. details->setState(Utils::DetailsWidget::NoSummary);
  588. QVBoxLayout *box = new QVBoxLayout(this);
  589. box->setMargin(0);
  590. box->addWidget(details);
  591. QWidget *widget = new QWidget(details);
  592. details->setWidget(widget);
  593. QFormLayout *layout = new QFormLayout(widget);
  594. const QStringList gnuVersionArgs = QStringList(QLatin1String("--version"));
  595. m_compilerCommand->setExpectedKind(Utils::PathChooser::ExistingCommand);
  596. m_compilerCommand->setCommandVersionArguments(gnuVersionArgs);
  597. layout->addRow(tr("&Compiler path:"), m_compilerCommand);
  598. layout->addRow(tr("&ABI:"), m_abiWidget);
  599. m_abiWidget->setEnabled(false);
  600. addErrorLabel(layout);
  601. setFromToolchain();
  602. connect(m_compilerCommand, SIGNAL(changed(QString)), this, SLOT(handleCompilerCommandChange()));
  603. connect(m_abiWidget, SIGNAL(abiChanged()), this, SIGNAL(dirty()));
  604. }
  605. void Internal::GccToolChainConfigWidget::apply()
  606. {
  607. if (toolChain()->isAutoDetected())
  608. return;
  609. GccToolChain *tc = static_cast<GccToolChain *>(toolChain());
  610. Q_ASSERT(tc);
  611. QString displayName = tc->displayName();
  612. tc->setCompilerCommand(m_compilerCommand->fileName());
  613. tc->setTargetAbi(m_abiWidget->currentAbi());
  614. tc->setDisplayName(displayName); // reset display name
  615. }
  616. void Internal::GccToolChainConfigWidget::setFromToolchain()
  617. {
  618. // subwidgets are not yet connected!
  619. bool blocked = blockSignals(true);
  620. GccToolChain *tc = static_cast<GccToolChain *>(toolChain());
  621. m_compilerCommand->setFileName(tc->compilerCommand());
  622. m_abiWidget->setAbis(tc->supportedAbis(), tc->targetAbi());
  623. if (!m_isReadOnly && !m_compilerCommand->path().isEmpty())
  624. m_abiWidget->setEnabled(true);
  625. blockSignals(blocked);
  626. }
  627. bool Internal::GccToolChainConfigWidget::isDirty() const
  628. {
  629. GccToolChain *tc = static_cast<GccToolChain *>(toolChain());
  630. Q_ASSERT(tc);
  631. return m_compilerCommand->fileName() != tc->compilerCommand()
  632. || m_abiWidget->currentAbi() != tc->targetAbi();
  633. }
  634. void Internal::GccToolChainConfigWidget::makeReadOnly()
  635. {
  636. m_compilerCommand->setEnabled(false);
  637. m_abiWidget->setEnabled(false);
  638. m_isReadOnly = true;
  639. ToolChainConfigWidget::makeReadOnly();
  640. }
  641. void Internal::GccToolChainConfigWidget::handleCompilerCommandChange()
  642. {
  643. Utils::FileName path = m_compilerCommand->fileName();
  644. QList<Abi> abiList;
  645. bool haveCompiler = false;
  646. if (!path.isEmpty()) {
  647. QFileInfo fi(path.toFileInfo());
  648. haveCompiler = fi.isExecutable() && fi.isFile();
  649. }
  650. if (haveCompiler)
  651. abiList = guessGccAbi(path, Utils::Environment::systemEnvironment().toStringList());
  652. m_abiWidget->setEnabled(haveCompiler);
  653. Abi currentAbi = m_abiWidget->currentAbi();
  654. m_abiWidget->setAbis(abiList, abiList.contains(currentAbi) ? currentAbi : Abi());
  655. emit dirty();
  656. }
  657. // --------------------------------------------------------------------------
  658. // ClangToolChain
  659. // --------------------------------------------------------------------------
  660. ClangToolChain::ClangToolChain(bool autodetect) :
  661. GccToolChain(QLatin1String(Constants::CLANG_TOOLCHAIN_ID), autodetect)
  662. { }
  663. QString ClangToolChain::type() const
  664. {
  665. return QLatin1String("clang");
  666. }
  667. QString ClangToolChain::typeDisplayName() const
  668. {
  669. return Internal::ClangToolChainFactory::tr("Clang");
  670. }
  671. QString ClangToolChain::makeCommand() const
  672. {
  673. #if defined(Q_OS_WIN)
  674. return QLatin1String("mingw32-make.exe");
  675. #else
  676. return QLatin1String("make");
  677. #endif
  678. }
  679. QList<Utils::FileName> ClangToolChain::suggestedMkspecList() const
  680. {
  681. Abi abi = targetAbi();
  682. if (abi.os() == Abi::MacOS)
  683. return QList<Utils::FileName>()
  684. << Utils::FileName::fromString(QLatin1String("macx-clang"))
  685. << Utils::FileName::fromString(QLatin1String("unsupported/macx-clang"));
  686. else if (abi.os() == Abi::LinuxOS)
  687. return QList<Utils::FileName>()
  688. << Utils::FileName::fromString(QLatin1String("linux-clang"))
  689. << Utils::FileName::fromString(QLatin1String("unsupported/linux-clang"));
  690. return QList<Utils::FileName>(); // Note: Not supported by Qt yet, so default to the mkspec the Qt was build with
  691. }
  692. IOutputParser *ClangToolChain::outputParser() const
  693. {
  694. return new ClangParser;
  695. }
  696. ToolChain *ClangToolChain::clone() const
  697. {
  698. return new ClangToolChain(*this);
  699. }
  700. // --------------------------------------------------------------------------
  701. // ClangToolChainFactory
  702. // --------------------------------------------------------------------------
  703. QString Internal::ClangToolChainFactory::displayName() const
  704. {
  705. return tr("Clang");
  706. }
  707. QString Internal::ClangToolChainFactory::id() const
  708. {
  709. return QLatin1String(Constants::CLANG_TOOLCHAIN_ID);
  710. }
  711. QList<ToolChain *> Internal::ClangToolChainFactory::autoDetect()
  712. {
  713. Abi ha = Abi::hostAbi();
  714. return autoDetectToolchains(QLatin1String("clang++"), ha);
  715. }
  716. bool Internal::ClangToolChainFactory::canCreate()
  717. {
  718. return true;
  719. }
  720. ToolChain *Internal::ClangToolChainFactory::create()
  721. {
  722. return createToolChain(false);
  723. }
  724. bool Internal::ClangToolChainFactory::canRestore(const QVariantMap &data)
  725. {
  726. return idFromMap(data).startsWith(QLatin1String(Constants::CLANG_TOOLCHAIN_ID) + QLatin1Char(':'));
  727. }
  728. ToolChain *Internal::ClangToolChainFactory::restore(const QVariantMap &data)
  729. {
  730. ClangToolChain *tc = new ClangToolChain(false);
  731. if (tc->fromMap(data))
  732. return tc;
  733. delete tc;
  734. return 0;
  735. }
  736. GccToolChain *Internal::ClangToolChainFactory::createToolChain(bool autoDetect)
  737. {
  738. return new ClangToolChain(autoDetect);
  739. }
  740. // --------------------------------------------------------------------------
  741. // MingwToolChain
  742. // --------------------------------------------------------------------------
  743. MingwToolChain::MingwToolChain(bool autodetect) :
  744. GccToolChain(QLatin1String(Constants::MINGW_TOOLCHAIN_ID), autodetect)
  745. { }
  746. QString MingwToolChain::type() const
  747. {
  748. return QLatin1String("mingw");
  749. }
  750. QString MingwToolChain::typeDisplayName() const
  751. {
  752. return Internal::MingwToolChainFactory::tr("MinGW");
  753. }
  754. QList<Utils::FileName> MingwToolChain::suggestedMkspecList() const
  755. {
  756. #if defined(Q_OS_WIN)
  757. return QList<Utils::FileName>() << Utils::FileName::fromString(QLatin1String("win32-g++"));
  758. #elif defined(Q_OS_LINUX)
  759. if (version().startsWith("4.6."))
  760. return QList<Utils::FileName>()
  761. << Utils::FileName::fromString(QLatin1String("win32-g++-4.6-cross"))
  762. << Utils::FileName::fromString(QLatin1String("unsupported/win32-g++-4.6-cross"));
  763. else
  764. return QList<Utils::FileName>()
  765. << Utils::FileName::fromString(QLatin1String("win32-g++-cross"))
  766. << Utils::FileName::fromString(QLatin1String("unsupported/win32-g++-cross"));
  767. #else
  768. return QList<Utils::FileName>();
  769. #endif
  770. }
  771. QString MingwToolChain::makeCommand() const
  772. {
  773. #ifdef Q_OS_WIN
  774. return QLatin1String("mingw32-make.exe");
  775. #else
  776. return QLatin1String("make");
  777. #endif
  778. }
  779. ToolChain *MingwToolChain::clone() const
  780. {
  781. return new MingwToolChain(*this);
  782. }
  783. // --------------------------------------------------------------------------
  784. // MingwToolChainFactory
  785. // --------------------------------------------------------------------------
  786. QString Internal::MingwToolChainFactory::displayName() const
  787. {
  788. return tr("MinGW");
  789. }
  790. QString Internal::MingwToolChainFactory::id() const
  791. {
  792. return QLatin1String(Constants::MINGW_TOOLCHAIN_ID);
  793. }
  794. QList<ToolChain *> Internal::MingwToolChainFactory::autoDetect()
  795. {
  796. Abi ha = Abi::hostAbi();
  797. return autoDetectToolchains(QLatin1String("g++"),
  798. Abi(ha.architecture(), Abi::WindowsOS, Abi::WindowsMSysFlavor, Abi::PEFormat, ha.wordWidth()));
  799. }
  800. bool Internal::MingwToolChainFactory::canCreate()
  801. {
  802. return true;
  803. }
  804. ToolChain *Internal::MingwToolChainFactory::create()
  805. {
  806. return createToolChain(false);
  807. }
  808. bool Internal::MingwToolChainFactory::canRestore(const QVariantMap &data)
  809. {
  810. return idFromMap(data).startsWith(QLatin1String(Constants::MINGW_TOOLCHAIN_ID) + QLatin1Char(':'));
  811. }
  812. ToolChain *Internal::MingwToolChainFactory::restore(const QVariantMap &data)
  813. {
  814. MingwToolChain *tc = new MingwToolChain(false);
  815. if (tc->fromMap(data))
  816. return tc;
  817. delete tc;
  818. return 0;
  819. }
  820. GccToolChain *Internal::MingwToolChainFactory::createToolChain(bool autoDetect)
  821. {
  822. return new MingwToolChain(autoDetect);
  823. }
  824. // --------------------------------------------------------------------------
  825. // LinuxIccToolChain
  826. // --------------------------------------------------------------------------
  827. LinuxIccToolChain::LinuxIccToolChain(bool autodetect) :
  828. GccToolChain(QLatin1String(Constants::LINUXICC_TOOLCHAIN_ID), autodetect)
  829. { }
  830. QString LinuxIccToolChain::type() const
  831. {
  832. return QLatin1String("icc");
  833. }
  834. QString LinuxIccToolChain::typeDisplayName() const
  835. {
  836. return Internal::LinuxIccToolChainFactory::tr("Linux ICC");
  837. }
  838. IOutputParser *LinuxIccToolChain::outputParser() const
  839. {
  840. return new LinuxIccParser;
  841. }
  842. QList<Utils::FileName> LinuxIccToolChain::suggestedMkspecList() const
  843. {
  844. return QList<Utils::FileName>()
  845. << Utils::FileName::fromString(QLatin1String("linux-icc-") + QString::number(targetAbi().wordWidth()));
  846. }
  847. ToolChain *LinuxIccToolChain::clone() const
  848. {
  849. return new LinuxIccToolChain(*this);
  850. }
  851. // --------------------------------------------------------------------------
  852. // LinuxIccToolChainFactory
  853. // --------------------------------------------------------------------------
  854. QString Internal::LinuxIccToolChainFactory::displayName() const
  855. {
  856. return tr("Linux ICC");
  857. }
  858. QString Internal::LinuxIccToolChainFactory::id() const
  859. {
  860. return QLatin1String(Constants::LINUXICC_TOOLCHAIN_ID);
  861. }
  862. QList<ToolChain *> Internal::LinuxIccToolChainFactory::autoDetect()
  863. {
  864. return autoDetectToolchains(QLatin1String("icpc"), Abi::hostAbi());
  865. }
  866. ToolChain *Internal::LinuxIccToolChainFactory::create()
  867. {
  868. return createToolChain(false);
  869. }
  870. bool Internal::LinuxIccToolChainFactory::canRestore(const QVariantMap &data)
  871. {
  872. return idFromMap(data).startsWith(QLatin1String(Constants::LINUXICC_TOOLCHAIN_ID) + QLatin1Char(':'));
  873. }
  874. ToolChain *Internal::LinuxIccToolChainFactory::restore(const QVariantMap &data)
  875. {
  876. LinuxIccToolChain *tc = new LinuxIccToolChain(false);
  877. if (tc->fromMap(data))
  878. return tc;
  879. delete tc;
  880. return 0;
  881. }
  882. GccToolChain *Internal::LinuxIccToolChainFactory::createToolChain(bool autoDetect)
  883. {
  884. return new LinuxIccToolChain(autoDetect);
  885. }
  886. } // namespace ProjectExplorer
  887. // Unit tests:
  888. #ifdef WITH_TESTS
  889. # include "projectexplorer.h"
  890. # include <QTest>
  891. # include <QUrl>
  892. namespace ProjectExplorer {
  893. void ProjectExplorerPlugin::testGccAbiGuessing_data()
  894. {
  895. QTest::addColumn<QString>("input");
  896. QTest::addColumn<QStringList>("abiList");
  897. QTest::newRow("invalid input")
  898. << QString::fromLatin1("Some text")
  899. << (QStringList());
  900. QTest::newRow("empty input")
  901. << QString::fromLatin1("")
  902. << (QStringList());
  903. QTest::newRow("broken input")
  904. << QString::fromLatin1("arm-none-foo-gnueabi")
  905. << (QStringList() << QLatin1String("arm-unknown-unknown-unknown-32bit"));
  906. QTest::newRow("totally broken input")
  907. << QString::fromLatin1("foo-bar-foo")
  908. << (QStringList());
  909. QTest::newRow("Maemo 1")
  910. << QString::fromLatin1("arm-none-linux-gnueabi")
  911. << (QStringList() << QLatin1String("arm-linux-generic-elf-32bit"));
  912. QTest::newRow("Linux 1")
  913. << QString::fromLatin1("i686-linux-gnu")
  914. << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"));
  915. QTest::newRow("Linux 2")
  916. << QString::fromLatin1("i486-linux-gnu")
  917. << (QStringList() << QLatin1String("x86-linux-generic-elf-32bit"));
  918. QTest::newRow("Linux 3")
  919. << QString::fromLatin1("x86_64-linux-gnu")
  920. << (QStringList() << QLatin1String("x86-linux-generic-elf-64bit")
  921. << QLatin1String("x86-linux-generic-elf-32bit"));
  922. QTest::newRow("Linux 4")
  923. << QString::fromLatin1("mipsel-linux-uclibc")
  924. << (QStringList() << QLatin1String("mips-linux-generic-elf-32bit"));
  925. QTest::newRow("Linux 5") // from QTCREATORBUG-4690
  926. << QString::fromLatin1("x86_64-redhat-linux6E")
  927. << (QStringList() << QLatin1String("x86-linux-generic-elf-64bit")
  928. << QLatin1String("x86-linux-generic-elf-32bit"));
  929. QTest::newRow("Linux 6") // from QTCREATORBUG-4690
  930. << QString::fromLatin1("x86_64-redhat-linux")
  931. << (QStringList() << QLatin1String("x86-linux-generic-elf-64bit")
  932. << QLatin1String("x86-linux-generic-elf-32bit"));
  933. QTest::newRow("Linux 7") // Meego
  934. << QString::fromLatin1("armv5tel-meego-linux-gnueabi")
  935. << (QStringList() << QLatin1String("arm-linux-meego-elf-32bit"));
  936. QTest::newRow("Linux 8")
  937. << QString::fromLatin1("armv5tl-montavista-linux-gnueabi")
  938. << (QStringList() << QLatin1String("arm-linux-generic-elf-32bit"));
  939. QTest::newRow("Linux 9")
  940. << QString::fromLatin1("arm-angstrom-linux-gnueabi")
  941. << (QStringList() << QLatin1String("arm-linux-generic-elf-32bit"));
  942. QTest::newRow("Mingw 1")
  943. << QString::fromLatin1("i686-w64-mingw32")
  944. << (QStringList() << QLatin1String("x86-windows-msys-pe-64bit")
  945. << QLatin1String("x86-windows-msys-pe-32bit"));
  946. QTest::newRow("Mingw 2")
  947. << QString::fromLatin1("mingw32")
  948. << (QStringList() << QLatin1String("x86-windows-msys-pe-32bit"));
  949. QTest::newRow("Cross Mingw 1")
  950. << QString::fromLatin1("amd64-mingw32msvc")
  951. << (QStringList() << QLatin1String("x86-windows-msys-pe-64bit")
  952. << QLatin1String("x86-windows-msys-pe-32bit"));
  953. QTest::newRow("Cross Mingw 2")
  954. << QString::fromLatin1("i586-mingw32msvc")
  955. << (QStringList() << QLatin1String("x86-windows-msys-pe-32bit"));
  956. QTest::newRow("Clang 1: windows")
  957. << QString::fromLatin1("x86_64-pc-win32")
  958. << (QStringList() << QLatin1String("x86-windows-msys-pe-64bit")
  959. << QLatin1String("x86-windows-msys-pe-32bit"));
  960. QTest::newRow("Clang 1: linux")
  961. << QString::fromLatin1("x86_64-unknown-linux-gnu")
  962. << (QStringList() << QLatin1String("x86-linux-generic-elf-64bit")
  963. << QLatin1String("x86-linux-generic-elf-32bit"));
  964. QTest::newRow("Mac 1")
  965. << QString::fromLatin1("i686-apple-darwin10")
  966. << (QStringList() << QLatin1String("x86-macos-generic-mach_o-64bit")
  967. << QLatin1String("x86-macos-generic-mach_o-32bit")
  968. << QLatin1String("ppc-macos-generic-mach_o-64bit")
  969. << QLatin1String("ppc-macos-generic-mach_o-32bit"));
  970. QTest::newRow("Mac 2")
  971. << QString::fromLatin1("powerpc-apple-darwin10")
  972. << (QStringList() << QLatin1String("ppc-macos-generic-mach_o-64bit")
  973. << QLatin1String("ppc-macos-generic-mach_o-32bit")
  974. << QLatin1String("x86-macos-generic-mach_o-64bit")
  975. << QLatin1String("x86-macos-generic-mach_o-32bit"));
  976. QTest::newRow("Mac 3")
  977. << QString::fromLatin1("i686-apple-darwin9")
  978. << (QStringList() << QLatin1String("x86-macos-generic-mach_o-32bit")
  979. << QLatin1String("x86-macos-generic-mach_o-64bit")
  980. << QLatin1String("ppc-macos-generic-mach_o-32bit")
  981. << QLatin1String("ppc-macos-generic-mach_o-64bit"));
  982. QTest::newRow("Mac IOS")
  983. << QString::fromLatin1("arm-apple-darwin9")
  984. << (QStringList() << QLatin1String("arm-macos-generic-mach_o-32bit"));
  985. QTest::newRow("Intel 1")
  986. << QString::fromLatin1("86_64 x86_64 GNU/Linux")
  987. << (QStringList() << QLatin1String("x86-linux-generic-elf-64bit")
  988. << QLatin1String("x86-linux-generic-elf-32bit"));
  989. QTest::newRow("Symbian 1")
  990. << QString::fromLatin1("arm-none-symbianelf")
  991. << (QStringList() << QLatin1String("arm-symbian-device-elf-32bit"));
  992. QTest::newRow("FreeBSD 1")
  993. << QString::fromLatin1("i386-portbld-freebsd9.0")
  994. << (QStringList() << QLatin1String("x86-bsd-freebsd-elf-32bit"));
  995. QTest::newRow("FreeBSD 2")
  996. << QString::fromLatin1("i386-undermydesk-freebsd")
  997. << (QStringList() << QLatin1String("x86-bsd-freebsd-elf-32bit"));
  998. }
  999. void ProjectExplorerPlugin::testGccAbiGuessing()
  1000. {
  1001. QFETCH(QString, input);
  1002. QFETCH(QStringList, abiList);
  1003. QList<ProjectExplorer::Abi> al = guessGccAbi(input);
  1004. QCOMPARE(al.count(), abiList.count());
  1005. for (int i = 0; i < al.count(); ++i) {
  1006. QCOMPARE(al.at(i).toString(), abiList.at(i));
  1007. }
  1008. }
  1009. } // namespace ProjectExplorer
  1010. #endif