PageRenderTime 53ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/src/plugins/projectexplorer/wincetoolchain.cpp

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