PageRenderTime 52ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/src/plugins/projectexplorer/gcctoolchain.cpp

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