source: trunk/qmake/generators/symbian/initprojectdeploy_symbian.cpp@ 1023

Last change on this file since 1023 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 16.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the qmake application of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "initprojectdeploy_symbian.h"
43#include <QDirIterator>
44#include <project.h>
45#include <qxmlstream.h>
46#include <qsettings.h>
47#include <qdebug.h>
48
49// Included from tools/shared
50#include <symbian/epocroot_p.h>
51
52#define SYSBIN_DIR "/sys/bin"
53#define HW_Z_DIR "epoc32/data/z"
54
55#define SUFFIX_DLL "dll"
56#define SUFFIX_EXE "exe"
57#define SUFFIX_QTPLUGIN "qtplugin"
58
59static QString fixPathToEpocOS(const QString &src)
60{
61 QString ret = Option::fixPathToTargetOS(src);
62
63 bool pathHasDriveLetter = false;
64 if (ret.size() > 1)
65 pathHasDriveLetter = (ret.at(1) == QLatin1Char(':'));
66
67 return pathHasDriveLetter ? ret.replace('/', '\\') : QDir::toNativeSeparators(ret);
68}
69
70static bool isPlugin(const QFileInfo& info, const QString& devicePath)
71{
72 // Libraries are plugins if deployment path is something else than
73 // SYSBIN_DIR with or without drive letter
74 if (0 == info.suffix().compare(QLatin1String(SUFFIX_DLL), Qt::CaseInsensitive)
75 && (devicePath.size() < 8
76 || (0 != devicePath.compare(QLatin1String(SYSBIN_DIR), Qt::CaseInsensitive)
77 && 0 != devicePath.mid(1).compare(QLatin1String(":" SYSBIN_DIR), Qt::CaseInsensitive)
78 && 0 != devicePath.compare(qt_epocRoot() + QLatin1String(HW_Z_DIR SYSBIN_DIR))))) {
79 return true;
80 } else {
81 return false;
82 }
83}
84
85static bool isBinary(const QFileInfo& info)
86{
87 if (0 == info.suffix().compare(QLatin1String(SUFFIX_DLL), Qt::CaseInsensitive) ||
88 0 == info.suffix().compare(QLatin1String(SUFFIX_EXE), Qt::CaseInsensitive)) {
89 return true;
90 } else {
91 return false;
92 }
93}
94
95static void createPluginStub(const QFileInfo& info,
96 const QString& devicePath,
97 DeploymentList &deploymentList,
98 QStringList& generatedDirs,
99 QStringList& generatedFiles)
100{
101 QString pluginStubDir = Option::output_dir + QLatin1Char('/') + QLatin1String(PLUGIN_STUB_DIR);
102 QDir().mkpath(pluginStubDir);
103 if (!generatedDirs.contains(pluginStubDir))
104 generatedDirs << pluginStubDir;
105 // Plugin stubs must have different name from the actual plugins, because
106 // the toolchain for creating ROM images cannot handle non-binary .dll files properly.
107 QFile stubFile(pluginStubDir + QLatin1Char('/') + info.completeBaseName() + QLatin1Char('.') + QLatin1String(SUFFIX_QTPLUGIN));
108 if (stubFile.open(QIODevice::WriteOnly)) {
109 if (!generatedFiles.contains(stubFile.fileName()))
110 generatedFiles << stubFile.fileName();
111 QTextStream t(&stubFile);
112 // Add note to stub so that people will not wonder what it is.
113 // Creation date is added to make new stub to deploy always to
114 // force plugin cache miss when loading plugins.
115 t << "This file is a Qt plugin stub file. The real Qt plugin is located in " SYSBIN_DIR ". Created:" << QDateTime::currentDateTime().toString(Qt::ISODate) << "\n";
116 } else {
117 fprintf(stderr, "cannot deploy \"%s\" because of plugin stub file creation failed\n", info.fileName().toLatin1().constData());
118 }
119 QFileInfo stubInfo(stubFile);
120 deploymentList.append(CopyItem(Option::fixPathToLocalOS(stubInfo.absoluteFilePath()),
121 fixPathToEpocOS(devicePath + "/" + stubInfo.fileName())));
122}
123
124QString generate_uid(const QString& target)
125{
126 static QMap<QString, QString> targetToUid;
127
128 QString tmp = targetToUid[target];
129
130 if (!tmp.isEmpty()) {
131 return tmp;
132 }
133
134 quint32 hash = 5381;
135 int c;
136
137 for (int i = 0; i < target.size(); ++i) {
138 c = target.at(i).toAscii();
139 hash ^= c + ((c - i) << i % 20) + ((c + i) << (i + 5) % 20) + ((c - 2 * i) << (i + 10) % 20) + ((c + 2 * i) << (i + 15) % 20);
140 }
141
142 tmp.setNum(hash, 16);
143 for (int i = tmp.size(); i < 8; ++i)
144 tmp.prepend("0");
145
146 targetToUid[target] = tmp;
147
148 return tmp;
149}
150
151// UIDs starting with 0xE are test UIDs in symbian
152QString generate_test_uid(const QString& target)
153{
154 QString tmp = generate_uid(target);
155 tmp.replace(0, 1, "E");
156 tmp.prepend("0x");
157
158 return tmp;
159}
160
161
162void initProjectDeploySymbian(QMakeProject* project,
163 DeploymentList &deploymentList,
164 const QString &testPath,
165 bool deployBinaries,
166 bool epocBuild,
167 const QString &platform,
168 const QString &build,
169 QStringList& generatedDirs,
170 QStringList& generatedFiles)
171{
172 QString targetPath = project->values("deploy.path").join(" ");
173 if (targetPath.isEmpty())
174 targetPath = testPath;
175 if (targetPath.endsWith("/") || targetPath.endsWith("\\"))
176 targetPath = targetPath.mid(0, targetPath.size() - 1);
177
178 bool targetPathHasDriveLetter = false;
179 if (targetPath.size() > 1) {
180 targetPathHasDriveLetter = targetPath.at(1) == QLatin1Char(':');
181 }
182
183 QString deploymentDrive;
184 if (0 == platform.compare(QLatin1String(ROM_DEPLOYMENT_PLATFORM))) {
185 deploymentDrive = qt_epocRoot() + HW_Z_DIR;
186 } else {
187 deploymentDrive = targetPathHasDriveLetter ? targetPath.left(2) : QLatin1String("c:");
188 }
189
190 foreach(QString item, project->values("DEPLOYMENT")) {
191 QString devicePath = project->first(item + ".path");
192 QString devicePathWithoutDrive = devicePath;
193
194 bool devicePathHasDriveLetter = false;
195 if (devicePath.size() > 1) {
196 devicePathHasDriveLetter = devicePath.at(1) == QLatin1Char(':');
197 }
198
199 // Sometimes devicePath can contain disk but APP_RESOURCE_DIR does not,
200 // so remove the drive letter for comparison purposes.
201 if (devicePathHasDriveLetter)
202 {
203 devicePathWithoutDrive.remove(0,2);
204 }
205 if (!deployBinaries
206 && 0 != platform.compare(QLatin1String(ROM_DEPLOYMENT_PLATFORM))
207 && !devicePathWithoutDrive.isEmpty()
208 && (0 == devicePathWithoutDrive.compare(project->values("APP_RESOURCE_DIR").join(""), Qt::CaseInsensitive)
209 || 0 == devicePathWithoutDrive.compare(project->values("REG_RESOURCE_IMPORT_DIR").join(""), Qt::CaseInsensitive))) {
210 // Do not deploy resources in emulator builds, as that seems to cause conflicts
211 // If there is ever a real need to deploy pre-built resources for emulator,
212 // BLD_INF_RULES.prj_exports can be used as a workaround.
213 continue;
214 }
215
216 if (devicePath.isEmpty() || devicePath == QLatin1String(".")) {
217 devicePath = targetPath;
218 }
219 // check if item.path is relative (! either / or \)
220 else if (!(devicePath.at(0) == QLatin1Char('/')
221 || devicePath.at(0) == QLatin1Char('\\')
222 || devicePathHasDriveLetter)) {
223 // Create output path
224 devicePath = Option::fixPathToLocalOS(QDir::cleanPath(targetPath + QLatin1Char('/') + devicePath));
225 } else {
226 if (0 == platform.compare(QLatin1String(EMULATOR_DEPLOYMENT_PLATFORM))) {
227 if (devicePathHasDriveLetter) {
228 devicePath = qt_epocRoot() + "epoc32/winscw/" + devicePath.remove(1, 1);
229 } else {
230 devicePath = qt_epocRoot() + "epoc32/winscw/c" + devicePath;
231 }
232 } else {
233 if (devicePathHasDriveLetter
234 && 0 == platform.compare(QLatin1String(ROM_DEPLOYMENT_PLATFORM))) {
235 devicePath.remove(0,2);
236 }
237 if (0 == platform.compare(QLatin1String(ROM_DEPLOYMENT_PLATFORM))
238 || (!devicePathHasDriveLetter && targetPathHasDriveLetter)) {
239 devicePath = deploymentDrive + devicePath;
240 }
241 }
242 }
243
244 devicePath.replace(QLatin1String("\\"), QLatin1String("/"));
245
246 if (!deployBinaries
247 && 0 == devicePath.right(8).compare(QLatin1String(SYSBIN_DIR), Qt::CaseInsensitive)
248 && 0 != platform.compare(QLatin1String(ROM_DEPLOYMENT_PLATFORM))) {
249 // Skip deploying to SYSBIN_DIR for anything but binary deployments
250 // Note: Deploying pre-built binaries also follow this rule, so emulator builds
251 // will not get those deployed. Since there is no way to differentiate currently
252 // between pre-built binaries for emulator and HW anyway, this is not a major issue.
253 continue;
254 }
255
256 QStringList flags = project->values(item + ".flags");
257
258 foreach(QString source, project->values(item + ".sources")) {
259 source = Option::fixPathToLocalOS(source);
260 QString nameFilter;
261 QFileInfo info(source);
262 QString searchPath;
263 bool dirSearch = false;
264
265 if (info.isDir()) {
266 nameFilter = QLatin1String("*");
267 searchPath = info.absoluteFilePath();
268 dirSearch = true;
269 } else {
270 if (info.exists() || source.indexOf('*') != -1) {
271 nameFilter = source.split(QDir::separator()).last();
272 searchPath = info.absolutePath();
273 } else {
274 // Entry was not found. That is ok if it is a binary, since those do not necessarily yet exist.
275 // Dlls need to be processed even when not deploying binaries for the stubs
276 if (isBinary(info)) {
277 if (deployBinaries) {
278 // Executables and libraries are deployed to \sys\bin
279 QFileInfo targetPath;
280 if (epocBuild)
281 targetPath.setFile(qt_epocRoot() + "epoc32/release/" + platform + "/" + build + "/");
282 else
283 targetPath.setFile(info.path() + QDir::separator());
284 if(devicePathHasDriveLetter) {
285 deploymentList.append(CopyItem(
286 Option::fixPathToLocalOS(targetPath.absolutePath() + "/" + info.fileName(),
287 false, true),
288 fixPathToEpocOS(devicePath.left(2) + QLatin1String(SYSBIN_DIR "/")
289 + info.fileName()),
290 flags));
291 } else {
292 deploymentList.append(CopyItem(
293 Option::fixPathToLocalOS(targetPath.absolutePath() + "/" + info.fileName(),
294 false, true),
295 fixPathToEpocOS(deploymentDrive + QLatin1String("/" SYSBIN_DIR "/")
296 + info.fileName()),
297 flags));
298 }
299 }
300 if (isPlugin(info, devicePath)) {
301 createPluginStub(info, devicePath, deploymentList, generatedDirs, generatedFiles);
302 continue;
303 }
304 } else {
305 // Generate deployment even if file doesn't exist, as this may be the case
306 // when generating .pkg files.
307 deploymentList.append(CopyItem(Option::fixPathToLocalOS(info.absoluteFilePath()),
308 fixPathToEpocOS(devicePath + "/" + info.fileName()),
309 flags));
310 continue;
311 }
312 }
313 }
314
315 int pathSize = info.absolutePath().size();
316 QDirIterator iterator(searchPath, QStringList() << nameFilter
317 , QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks
318 , dirSearch ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags);
319
320 while (iterator.hasNext()) {
321 iterator.next();
322 QFileInfo iteratorInfo(iterator.filePath());
323 QString absoluteItemPath = Option::fixPathToLocalOS(iteratorInfo.absolutePath());
324 int diffSize = absoluteItemPath.size() - pathSize;
325
326 if (!iteratorInfo.isDir()) {
327 if (isPlugin(iterator.fileInfo(), devicePath)) {
328 // This deploys pre-built plugins. Other pre-built binaries will deploy normally,
329 // as they have SYSBIN_DIR target path.
330 if (deployBinaries
331 || (0 == platform.compare(QLatin1String(ROM_DEPLOYMENT_PLATFORM)))) {
332 if (devicePathHasDriveLetter) {
333 deploymentList.append(CopyItem(
334 Option::fixPathToLocalOS(absoluteItemPath + "/" + iterator.fileName()),
335 fixPathToEpocOS(devicePath.left(2) + QLatin1String(SYSBIN_DIR "/")
336 + iterator.fileName()),
337 flags));
338 } else {
339 deploymentList.append(CopyItem(
340 Option::fixPathToLocalOS(absoluteItemPath + "/" + iterator.fileName()),
341 fixPathToEpocOS(deploymentDrive + QLatin1String("/" SYSBIN_DIR "/")
342 + iterator.fileName()),
343 flags));
344 }
345 }
346 createPluginStub(info, devicePath + "/" + absoluteItemPath.right(diffSize),
347 deploymentList, generatedDirs, generatedFiles);
348 continue;
349 } else {
350 deploymentList.append(CopyItem(
351 Option::fixPathToLocalOS(absoluteItemPath + "/" + iterator.fileName()),
352 fixPathToEpocOS(devicePath + "/" + absoluteItemPath.right(diffSize)
353 + "/" + iterator.fileName()),
354 flags));
355 }
356 }
357 }
358 }
359 }
360
361 // Remove deployments that do not actually do anything
362 if (0 == platform.compare(QLatin1String(EMULATOR_DEPLOYMENT_PLATFORM))
363 || 0 == platform.compare(QLatin1String(ROM_DEPLOYMENT_PLATFORM))) {
364 QMutableListIterator<CopyItem> i(deploymentList);
365 while(i.hasNext()) {
366 CopyItem &item = i.next();
367 QFileInfo fromItem(item.from);
368 QFileInfo toItem(item.to);
369#if defined(Q_OS_WIN)
370 if (0 == fromItem.absoluteFilePath().compare(toItem.absoluteFilePath(), Qt::CaseInsensitive))
371#else
372 if (0 == fromItem.absoluteFilePath().compare(toItem.absoluteFilePath()))
373#endif
374 i.remove();
375 }
376 }
377}
Note: See TracBrowser for help on using the repository browser.