PageRenderTime 50ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/src/plugins/projectexplorer/wincetoolchain.cpp

https://bitbucket.org/kyanha/qt-creator
C++ | 476 lines | 326 code | 78 blank | 72 comment | 70 complexity | 4805a65bc86ea5410c709c2bdfcbdb78 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 "wincetoolchain.h"
  30. #include "msvcparser.h"
  31. #include "projectexplorerconstants.h"
  32. #include "headerpath.h"
  33. #include <projectexplorer/projectexplorer.h>
  34. #include <projectexplorer/projectexplorersettings.h>
  35. #include <utils/qtcassert.h>
  36. #include <QDir>
  37. #include <QFileInfo>
  38. #include <QSettings>
  39. #include <QFormLayout>
  40. #include <QLabel>
  41. #include <QXmlStreamReader>
  42. #define KEY_ROOT "ProjectExplorer.WinCEToolChain."
  43. static const char msvcVerKeyC[] = KEY_ROOT"MSVCVer";
  44. static const char ceVerKeyC[] = KEY_ROOT"CEVer";
  45. static const char binPathKeyC[] = KEY_ROOT"BinPath";
  46. static const char includePathKeyC[] = KEY_ROOT"IncludePath";
  47. static const char libPathKeyC[] = KEY_ROOT"LibPath";
  48. static const char supportedAbiKeyC[] = KEY_ROOT"SupportedAbi";
  49. static const char vcVarsKeyC[] = KEY_ROOT"VCVars";
  50. enum { debug = 0 };
  51. namespace ProjectExplorer {
  52. namespace Internal {
  53. // --------------------------------------------------------------------------
  54. // Helpers:
  55. // --------------------------------------------------------------------------
  56. // Just decodes from the integer version to the string used in Qt mkspecs
  57. static QString findMsvcVer(int version)
  58. {
  59. if (version == 10)
  60. return QLatin1String("msvc2010");
  61. if (version == 9)
  62. return QLatin1String("msvc2008");;
  63. return QLatin1String("msvc2005");
  64. }
  65. // Windows: Expand the delayed evaluation references returned by the
  66. // SDK setup scripts: "PATH=$(Path);foo". Some values might expand
  67. // to empty and should not be added
  68. static QString winExpandDelayedEnvReferences(QString in, const Utils::Environment &env)
  69. {
  70. const QString firstDelimit = QLatin1String("$(");
  71. const QChar secondDelimit = QLatin1Char(')');
  72. for (int pos = 0; pos < in.size(); ) {
  73. // Replace "$(REF)" by its value in process environment
  74. pos = in.indexOf(firstDelimit, pos);
  75. if (pos == -1)
  76. break;
  77. const int replaceStart = pos + firstDelimit.size();
  78. const int nextPos = in.indexOf(secondDelimit, replaceStart);
  79. if (nextPos == -1)
  80. break;
  81. const QString var = in.mid(replaceStart, nextPos - replaceStart);
  82. QString replacement = env.value(var.toUpper());
  83. if (replacement.isEmpty()) {
  84. qWarning() << "No replacement for var: " << var;
  85. pos = nextPos;
  86. }
  87. else {
  88. // Not sure about this, but we need to account for the case where
  89. // the end of the replacement doesn't have the directory seperator and
  90. // neither does the start of the insert. This solution assumes:
  91. // 1) Having \\ in a path is valid (it is on WinXP)
  92. // 2) We're only replacing in paths. This will cause problems if there's
  93. // a replace of a string
  94. if (!replacement.endsWith(QLatin1Char('\\')))
  95. replacement += QLatin1Char('\\');
  96. in.replace(pos, nextPos + 1 - pos, replacement);
  97. pos += replacement.size();
  98. }
  99. }
  100. return in;
  101. }
  102. // This is pretty much the same as the ReadEnvironmentSetting in the msvctoolchain.cpp, but
  103. // this takes account of the library, binary and include paths to replace the vcvars versions
  104. // with the ones for this toolchain.
  105. Utils::Environment WinCEToolChain::readEnvironmentSetting(Utils::Environment &env) const
  106. {
  107. Utils::Environment result = env;
  108. if (!QFileInfo(m_vcvarsBat).exists())
  109. return result;
  110. // Get the env pairs
  111. QMap<QString, QString> envPairs;
  112. if (!generateEnvironmentSettings(env, m_vcvarsBat, QString(), envPairs))
  113. return result;
  114. QMap<QString,QString>::const_iterator envPairIter;
  115. for (envPairIter = envPairs.begin(); envPairIter!=envPairs.end(); ++envPairIter) {
  116. // Replace the env values with those from the WinCE SDK
  117. QString varValue = envPairIter.value();
  118. if (envPairIter.key() == QLatin1String("PATH"))
  119. varValue = m_binPath + QLatin1Char(';') + varValue;
  120. else if (envPairIter.key() == QLatin1String("INCLUDE"))
  121. varValue = m_includePath;
  122. else if (envPairIter.key() == QLatin1String("LIB"))
  123. varValue = m_libPath;
  124. if (!varValue.isEmpty())
  125. result.set(envPairIter.key(), varValue);
  126. }
  127. // Now loop round and do the delayed expansion
  128. Utils::Environment::const_iterator envIter = result.constBegin();
  129. while (envIter != result.constEnd()) {
  130. const QString key = result.key(envIter);
  131. const QString unexpandedValue = result.value(envIter);
  132. const QString expandedValue = winExpandDelayedEnvReferences(unexpandedValue, result);
  133. result.set(key, expandedValue);
  134. ++envIter;
  135. }
  136. if (debug) {
  137. const QStringList newVars = result.toStringList();
  138. const QStringList oldVars = env.toStringList();
  139. QDebug nsp = qDebug().nospace();
  140. foreach (const QString &n, newVars) {
  141. if (!oldVars.contains(n))
  142. nsp << n << '\n';
  143. }
  144. }
  145. return result;
  146. }
  147. // Used to parse an SDK entry in the config file and extract information about this SDK
  148. static bool parseSDK(QXmlStreamReader& theReader,
  149. Abi::Architecture& sdkArch,
  150. QString& sdkName,
  151. QString& ceVer,
  152. QString& binPath,
  153. QString& includePath,
  154. QString& libPath)
  155. {
  156. sdkArch = Abi::UnknownArchitecture;
  157. sdkName.clear();
  158. // Loop through until either the end of the file or until is gets to the next
  159. // end element.
  160. while (!theReader.atEnd()) {
  161. theReader.readNext();
  162. if (theReader.isEndElement()) {
  163. // Got to the end element so return...
  164. if (theReader.name() == QLatin1String("Platform"))
  165. return (sdkArch!=Abi::UnknownArchitecture && !sdkName.isEmpty());
  166. } else if (theReader.isStartElement()) {
  167. const QStringRef elemName = theReader.name();
  168. if (elemName == QLatin1String("PlatformName")) {
  169. sdkName = theReader.readElementText();
  170. } else if (elemName == QLatin1String("Directories")) {
  171. // Populate the paths from this element. Note: we remove the
  172. // $(PATH) from the binPath as this will be pre-pended in code
  173. binPath = theReader.attributes().value(QLatin1String("Path")).toString();
  174. binPath.remove(QLatin1String("$(PATH)"));
  175. includePath = theReader.attributes().value(QLatin1String("Include")).toString();
  176. libPath = theReader.attributes().value(QLatin1String("Library")).toString();
  177. } else if (elemName == QLatin1String("OSMajorVersion")) {
  178. // Qt only supports CE5 and higher so drop out here if this version is
  179. // invalid
  180. ceVer = theReader.readElementText();
  181. if (ceVer.toInt() < 5) {
  182. if (debug)
  183. qDebug("Ignoring SDK '%s'. Windows CE version %d is unsupported.", qPrintable(sdkName), ceVer.toInt());
  184. return false;
  185. }
  186. } else if (elemName == QLatin1String("Macro")) {
  187. // Pull out the architecture from the macro values.
  188. if (theReader.attributes().value(QLatin1String("Name")) == QLatin1String("ARCHFAM")) {
  189. const QStringRef archFam = theReader.attributes().value(QLatin1String("Value"));
  190. if (archFam == QLatin1String("ARM"))
  191. sdkArch = Abi::ArmArchitecture;
  192. else if (archFam == QLatin1String("x86"))
  193. sdkArch = Abi::X86Architecture;
  194. else if (archFam == QLatin1String("MIPS"))
  195. sdkArch = Abi::MipsArchitecture;
  196. }
  197. }
  198. }
  199. }
  200. // If we've got to here then the end of the file has been reached before the
  201. // end of element tag, so return error.
  202. return false;
  203. }
  204. // --------------------------------------------------------------------------
  205. // WinCEToolChain
  206. // --------------------------------------------------------------------------
  207. WinCEToolChain::WinCEToolChain(const QString &name,
  208. const Abi &abi,
  209. const QString &vcvarsBat,
  210. const QString &msvcVer,
  211. const QString &ceVer,
  212. const QString &binPath,
  213. const QString &includePath,
  214. const QString &libPath,
  215. bool autodetect) :
  216. AbstractMsvcToolChain(QLatin1String(Constants::WINCE_TOOLCHAIN_ID), autodetect, abi, vcvarsBat),
  217. m_msvcVer(msvcVer),
  218. m_ceVer(ceVer),
  219. m_binPath(binPath),
  220. m_includePath(includePath),
  221. m_libPath(libPath)
  222. {
  223. Q_ASSERT(!name.isEmpty());
  224. Q_ASSERT(!m_binPath.isEmpty());
  225. Q_ASSERT(!m_includePath.isEmpty());
  226. Q_ASSERT(!m_libPath.isEmpty());
  227. setDisplayName(name);
  228. }
  229. WinCEToolChain::WinCEToolChain() :
  230. AbstractMsvcToolChain(QLatin1String(Constants::WINCE_TOOLCHAIN_ID), false)
  231. {
  232. }
  233. WinCEToolChain *WinCEToolChain::readFromMap(const QVariantMap &data)
  234. {
  235. WinCEToolChain *tc = new WinCEToolChain;
  236. if (tc->fromMap(data))
  237. return tc;
  238. delete tc;
  239. return 0;
  240. }
  241. QString WinCEToolChain::type() const
  242. {
  243. return QLatin1String("wince");
  244. }
  245. QString WinCEToolChain::typeDisplayName() const
  246. {
  247. return WinCEToolChainFactory::tr("WinCE");
  248. }
  249. QList<Utils::FileName> WinCEToolChain::suggestedMkspecList() const
  250. {
  251. const QChar specSeperator(QLatin1Char('-'));
  252. QString specString = QLatin1String("wince");
  253. specString += m_ceVer;
  254. specString += specSeperator;
  255. specString += Abi::toString(m_abi.architecture());
  256. specString += specSeperator;
  257. specString += m_msvcVer;
  258. return QList<Utils::FileName>() << Utils::FileName::fromString(specString);
  259. }
  260. QString WinCEToolChain::ceVer() const
  261. {
  262. return m_ceVer;
  263. }
  264. QVariantMap WinCEToolChain::toMap() const
  265. {
  266. QVariantMap data = ToolChain::toMap();
  267. data.insert(QLatin1String(msvcVerKeyC), m_msvcVer);
  268. data.insert(QLatin1String(ceVerKeyC), m_ceVer);
  269. data.insert(QLatin1String(binPathKeyC), m_binPath);
  270. data.insert(QLatin1String(includePathKeyC), m_includePath);
  271. data.insert(QLatin1String(libPathKeyC), m_libPath);
  272. data.insert(QLatin1String(vcVarsKeyC), m_vcvarsBat);
  273. data.insert(QLatin1String(supportedAbiKeyC), m_abi.toString());
  274. return data;
  275. }
  276. bool WinCEToolChain::fromMap(const QVariantMap &data)
  277. {
  278. if (!ToolChain::fromMap(data))
  279. return false;
  280. m_msvcVer = data.value(QLatin1String(msvcVerKeyC)).toString();
  281. m_ceVer = data.value(QLatin1String(ceVerKeyC)).toString();
  282. m_binPath = data.value(QLatin1String(binPathKeyC)).toString();
  283. m_includePath = data.value(QLatin1String(includePathKeyC)).toString();
  284. m_libPath = data.value(QLatin1String(libPathKeyC)).toString();
  285. m_vcvarsBat = data.value(QLatin1String(vcVarsKeyC)).toString();
  286. const QString abiString = data.value(QLatin1String(supportedAbiKeyC)).toString();
  287. m_abi = Abi(abiString);
  288. return isValid();
  289. }
  290. ToolChainConfigWidget *WinCEToolChain::configurationWidget()
  291. {
  292. return new WinCEToolChainConfigWidget(this);
  293. }
  294. ToolChain *WinCEToolChain::clone() const
  295. {
  296. return new WinCEToolChain(*this);
  297. }
  298. // --------------------------------------------------------------------------
  299. // WinCEToolChainFactory
  300. // --------------------------------------------------------------------------
  301. QString WinCEToolChainFactory::displayName() const
  302. {
  303. return tr("WinCE");
  304. }
  305. QString WinCEToolChainFactory::id() const
  306. {
  307. return QLatin1String(Constants::WINCE_TOOLCHAIN_ID);
  308. }
  309. QList<ToolChain *> WinCEToolChainFactory::autoDetect()
  310. {
  311. QList<ToolChain *> results;
  312. // 1) Installed WinCEs
  313. const QSettings vsRegistry(
  314. #ifdef Q_OS_WIN64
  315. QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7"),
  316. #else
  317. QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VC7"),
  318. #endif
  319. QSettings::NativeFormat);
  320. foreach (const QString &vsName, vsRegistry.allKeys()) {
  321. // Scan for version major.minor
  322. const int dotPos = vsName.indexOf(QLatin1Char('.'));
  323. if (dotPos == -1)
  324. continue;
  325. const QString path = QDir::fromNativeSeparators(vsRegistry.value(vsName).toString());
  326. const int version = vsName.left(dotPos).toInt();
  327. // Check existence of various install scripts
  328. const QString vcvars32bat = path + QLatin1String("bin/vcvars32.bat");
  329. QFile cePlatforms(path + QLatin1String("vcpackages/WCE.VCPlatform.config"));
  330. if (cePlatforms.exists()) {
  331. const QString msvcVer = findMsvcVer(version);
  332. cePlatforms.open(QIODevice::ReadOnly);
  333. QXmlStreamReader platformReader(&cePlatforms);
  334. // Rip through the config file getting all of the installed platforms.
  335. while (!platformReader.atEnd()) {
  336. platformReader.readNext();
  337. if (platformReader.isStartElement()) {
  338. if (platformReader.name() == QLatin1String("Platform")) {
  339. Abi::Architecture theArch;
  340. QString thePlat;
  341. QString binPath;
  342. QString includePath;
  343. QString libPath;
  344. QString ceVer;
  345. if (parseSDK(platformReader, theArch, thePlat, ceVer, binPath, includePath, libPath)) {
  346. WinCEToolChain *pChain = new WinCEToolChain(thePlat,
  347. Abi(theArch, Abi::WindowsOS, Abi::WindowsCEFlavor, Abi::PEFormat, 32),
  348. vcvars32bat,
  349. msvcVer,
  350. ceVer,
  351. binPath,
  352. includePath,
  353. libPath,
  354. true);
  355. results.append(pChain);
  356. }
  357. }
  358. }
  359. }
  360. }
  361. }
  362. return results;
  363. }
  364. QString WinCEToolChain::autoDetectCdbDebugger(QStringList *checkedDirectories /* = 0 */)
  365. {
  366. Q_UNUSED(checkedDirectories);
  367. return QString();
  368. }
  369. bool WinCEToolChainFactory::canRestore(const QVariantMap &data)
  370. {
  371. return idFromMap(data).startsWith(QLatin1String(Constants::WINCE_TOOLCHAIN_ID) + QLatin1Char(':'));
  372. }
  373. bool WinCEToolChain::operator ==(const ToolChain &other) const
  374. {
  375. if (!AbstractMsvcToolChain::operator ==(other))
  376. return false;
  377. const WinCEToolChain *ceTc = static_cast<const WinCEToolChain *>(&other);
  378. return m_ceVer == ceTc->m_ceVer;
  379. }
  380. ToolChain *WinCEToolChainFactory::restore(const QVariantMap &data)
  381. {
  382. return WinCEToolChain::readFromMap(data);
  383. }
  384. // --------------------------------------------------------------------------
  385. // WinCEToolChainConfigWidget
  386. // --------------------------------------------------------------------------
  387. WinCEToolChainConfigWidget::WinCEToolChainConfigWidget(ToolChain *tc) :
  388. ToolChainConfigWidget(tc)
  389. {
  390. WinCEToolChain *toolChain = static_cast<WinCEToolChain *>(tc);
  391. QTC_ASSERT(tc, return);
  392. m_mainLayout->addRow(tr("SDK:"), new QLabel(toolChain->displayName()));
  393. m_mainLayout->addRow(tr("WinCE Version:"), new QLabel(toolChain->ceVer()));
  394. m_mainLayout->addRow(tr("ABI:"), new QLabel(toolChain->targetAbi().toString()));
  395. addErrorLabel();
  396. }
  397. } // namespace Internal
  398. } // namespace ProjectExplorer