|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the qmake application of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
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 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "symmake_sbsv2.h" |
|
43 #include "initprojectdeploy_symbian.h" |
|
44 |
|
45 #include <qstring.h> |
|
46 #include <qstringlist.h> |
|
47 #include <qdir.h> |
|
48 #include <qdatetime.h> |
|
49 #include <qdebug.h> |
|
50 |
|
51 SymbianSbsv2MakefileGenerator::SymbianSbsv2MakefileGenerator() : SymbianMakefileGenerator() { } |
|
52 SymbianSbsv2MakefileGenerator::~SymbianSbsv2MakefileGenerator() { } |
|
53 |
|
54 #define FLM_DEST_DIR "epoc32/tools/makefile_templates/qt" |
|
55 #define FLM_SOURCE_DIR "/mkspecs/symbian-sbsv2/flm/qt" |
|
56 |
|
57 // Copies Qt FLMs to correct location under epocroot. |
|
58 // This is not done by configure as it is possible to change epocroot after configure. |
|
59 void SymbianSbsv2MakefileGenerator::exportFlm() |
|
60 { |
|
61 static bool flmExportDone = false; |
|
62 |
|
63 if (!flmExportDone) { |
|
64 QDir sourceDir = QDir(QLibraryInfo::location(QLibraryInfo::PrefixPath) + FLM_SOURCE_DIR); |
|
65 QFileInfoList sourceInfos = sourceDir.entryInfoList(QDir::Files); |
|
66 |
|
67 QDir destDir(epocRoot() + FLM_DEST_DIR); |
|
68 if (!destDir.exists()) { |
|
69 if (destDir.mkpath(destDir.absolutePath())) |
|
70 generatedDirs << destDir.absolutePath(); |
|
71 } |
|
72 |
|
73 foreach(QFileInfo item, sourceInfos) { |
|
74 QFileInfo destInfo = QFileInfo(destDir.absolutePath() + "/" + item.fileName()); |
|
75 if (!destInfo.exists() || destInfo.lastModified() < item.lastModified()) { |
|
76 if (destInfo.exists()) |
|
77 QFile::remove(destInfo.absoluteFilePath()); |
|
78 if (QFile::copy(item.absoluteFilePath(), destInfo.absoluteFilePath())) { |
|
79 if (Option::mkfile::listgen) { |
|
80 generatePrint(destInfo.absoluteFilePath()); |
|
81 } |
|
82 generatedFiles << destInfo.absoluteFilePath(); |
|
83 } |
|
84 else |
|
85 fprintf(stderr, "Error: Could not copy '%s' -> '%s'\n", |
|
86 qPrintable(item.absoluteFilePath()), |
|
87 qPrintable(destInfo.absoluteFilePath())); |
|
88 } |
|
89 } |
|
90 flmExportDone = true; |
|
91 } |
|
92 } |
|
93 |
|
94 void SymbianSbsv2MakefileGenerator::writeMkFile(const QString& wrapperFileName, bool deploymentOnly) |
|
95 { |
|
96 // Can't use extension makefile with sbsv2 |
|
97 Q_UNUSED(wrapperFileName); |
|
98 Q_UNUSED(deploymentOnly); |
|
99 } |
|
100 |
|
101 void SymbianSbsv2MakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, bool isPrimaryMakefile) |
|
102 { |
|
103 QStringList allPlatforms; |
|
104 foreach(QString platform, project->values("SYMBIAN_PLATFORMS")) { |
|
105 allPlatforms << platform.toLower(); |
|
106 } |
|
107 |
|
108 QStringList debugPlatforms = allPlatforms; |
|
109 QStringList releasePlatforms = allPlatforms; |
|
110 releasePlatforms.removeAll("winscw"); // No release for emulator |
|
111 |
|
112 QString testClause; |
|
113 if (project->values("CONFIG").contains("symbian_test", Qt::CaseInsensitive)) |
|
114 testClause = QLatin1String(".test"); |
|
115 else |
|
116 testClause = QLatin1String(""); |
|
117 |
|
118 QTextStream t(&wrapperFile); |
|
119 |
|
120 t << "# ==============================================================================" << endl; |
|
121 t << "# Generated by qmake (" << qmake_version() << ") (Qt " << QT_VERSION_STR << ") on: "; |
|
122 t << QDateTime::currentDateTime().toString() << endl; |
|
123 t << "# This file is generated by qmake and should not be modified by the" << endl; |
|
124 t << "# user." << endl; |
|
125 t << "# Name : " << wrapperFile.fileName() << endl; |
|
126 t << "# Description : Wrapper Makefile for calling Symbian build tools" << endl; |
|
127 t << "#" << endl; |
|
128 t << "# ==============================================================================" << "\n" << endl; |
|
129 t << endl; |
|
130 t << "MAKEFILE = " << wrapperFile.fileName() << endl; |
|
131 t << "QMAKE = " << Option::fixPathToTargetOS(var("QMAKE_QMAKE")) << endl; |
|
132 t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; |
|
133 t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl; |
|
134 t << "MOVE = " << var("QMAKE_MOVE") << endl; |
|
135 t << "DEBUG_PLATFORMS = " << debugPlatforms.join(" ") << endl; |
|
136 t << "RELEASE_PLATFORMS = " << releasePlatforms.join(" ") << endl; |
|
137 t << "MAKE = make" << endl; |
|
138 t << "SBS = sbs" << endl; |
|
139 t << endl; |
|
140 t << "DEFINES" << '\t' << " = " |
|
141 << varGlue("PRL_EXPORT_DEFINES","-D"," -D"," ") |
|
142 << varGlue("QMAKE_COMPILER_DEFINES", "-D", "-D", " ") |
|
143 << varGlue("DEFINES","-D"," -D","") << endl; |
|
144 |
|
145 t << "INCPATH" << '\t' << " = "; |
|
146 |
|
147 for (QMap<QString, QStringList>::iterator it = systeminclude.begin(); it != systeminclude.end(); ++it) { |
|
148 QStringList values = it.value(); |
|
149 for (int i = 0; i < values.size(); ++i) { |
|
150 t << " -I\"" << values.at(i) << "\" "; |
|
151 } |
|
152 } |
|
153 t << endl; |
|
154 t << "first: default" << endl; |
|
155 if (debugPlatforms.contains("winscw")) |
|
156 t << "default: debug-winscw"; |
|
157 else if (debugPlatforms.contains("armv5")) |
|
158 t << "default: debug-armv5"; |
|
159 else if (debugPlatforms.size()) |
|
160 t << "default: debug-" << debugPlatforms.first(); |
|
161 else |
|
162 t << "default: all"; |
|
163 |
|
164 t << endl; |
|
165 if (!isPrimaryMakefile) { |
|
166 t << "all:" << endl; |
|
167 } else { |
|
168 t << "all: debug release" << endl; |
|
169 t << endl; |
|
170 t << "qmake:" << endl; |
|
171 t << "\t$(QMAKE) -spec symbian-sbsv2 -o \"" << fileInfo(Option::output.fileName()).fileName() |
|
172 << "\" \"" << project->projectFile() << "\"" << endl; |
|
173 t << endl; |
|
174 t << BLD_INF_FILENAME ":" << endl; |
|
175 t << "\t$(QMAKE)" << endl; |
|
176 t << endl; |
|
177 |
|
178 t << "debug: " << BLD_INF_FILENAME << endl; |
|
179 foreach(QString item, debugPlatforms) { |
|
180 t << "\t$(SBS) -c " << item << "_udeb" << testClause << endl; |
|
181 } |
|
182 t << endl; |
|
183 t << "release: " << BLD_INF_FILENAME << endl; |
|
184 foreach(QString item, releasePlatforms) { |
|
185 t << "\t$(SBS) -c " << item << "_urel" << testClause << endl; |
|
186 } |
|
187 t << endl; |
|
188 |
|
189 // For more specific builds, targets are in this form: build-platform, e.g. release-armv5 |
|
190 foreach(QString item, debugPlatforms) { |
|
191 t << "debug-" << item << ": " << BLD_INF_FILENAME << endl; |
|
192 t << "\t$(SBS) -c " << item << "_udeb" << testClause << endl; |
|
193 } |
|
194 |
|
195 foreach(QString item, releasePlatforms) { |
|
196 t << "release-" << item << ": " << BLD_INF_FILENAME << endl; |
|
197 t << "\t$(SBS) -c " << item << "_urel" << testClause << endl; |
|
198 } |
|
199 |
|
200 t << endl; |
|
201 t << "export: " << BLD_INF_FILENAME << endl; |
|
202 t << "\t$(SBS) export" << endl; |
|
203 t << endl; |
|
204 |
|
205 t << "cleanexport: " << BLD_INF_FILENAME << endl; |
|
206 t << "\t$(SBS) cleanexport" << endl; |
|
207 t << endl; |
|
208 |
|
209 } |
|
210 |
|
211 // Add all extra targets including extra compiler targest also to wrapper makefile, |
|
212 // even though many of them may have already been added to bld.inf as FLMs. |
|
213 // This is to enable use of targets like 'mocables', which call targets generated by extra compilers. |
|
214 if (targetType != TypeSubdirs) { |
|
215 t << extraTargetsCache; |
|
216 t << extraCompilersCache; |
|
217 } else { |
|
218 QList<MakefileGenerator::SubTarget*> subtargets = findSubDirsSubTargets(); |
|
219 writeSubTargets(t, subtargets, SubTargetSkipDefaultVariables|SubTargetSkipDefaultTargets); |
|
220 qDeleteAll(subtargets); |
|
221 } |
|
222 |
|
223 writeSisTargets(t); |
|
224 |
|
225 generateDistcleanTargets(t); |
|
226 |
|
227 t << "clean: " << BLD_INF_FILENAME << endl; |
|
228 t << "\t-$(SBS) reallyclean" << endl; |
|
229 t << endl; |
|
230 |
|
231 // create execution target |
|
232 if (debugPlatforms.contains("winscw") && targetType == TypeExe) { |
|
233 t << "run:" << endl; |
|
234 t << "\t-call " << epocRoot() << "epoc32/release/winscw/udeb/" << removePathSeparators(escapeFilePath(fileFixify(project->first("TARGET"))).append(".exe")) << endl << endl; |
|
235 } |
|
236 } |
|
237 |
|
238 void SymbianSbsv2MakefileGenerator::writeBldInfExtensionRulesPart(QTextStream& t) |
|
239 { |
|
240 // Makes sure we have needed FLMs in place. |
|
241 exportFlm(); |
|
242 |
|
243 // Parse extra compilers data |
|
244 QStringList defines; |
|
245 QStringList incPath; |
|
246 |
|
247 defines << varGlue("PRL_EXPORT_DEFINES","-D"," -D"," ") |
|
248 << varGlue("QMAKE_COMPILER_DEFINES", "-D", "-D", " ") |
|
249 << varGlue("DEFINES","-D"," -D",""); |
|
250 for (QMap<QString, QStringList>::iterator it = systeminclude.begin(); it != systeminclude.end(); ++it) { |
|
251 QStringList values = it.value(); |
|
252 for (int i = 0; i < values.size(); ++i) { |
|
253 incPath << QLatin1String(" -I\"") + values.at(i) + "\""; |
|
254 } |
|
255 } |
|
256 |
|
257 // Write extra compilers and targets to initialize QMAKE_ET_* variables |
|
258 // Cache results to avoid duplicate calls when creating wrapper makefile |
|
259 QTextStream extraCompilerStream(&extraCompilersCache); |
|
260 QTextStream extraTargetStream(&extraTargetsCache); |
|
261 writeExtraCompilerTargets(extraCompilerStream); |
|
262 writeExtraTargets(extraTargetStream); |
|
263 |
|
264 // Figure out everything the target depends on as we don't want to run extra targets that |
|
265 // are not necessary. |
|
266 QStringList allPreDeps; |
|
267 foreach(QString item, project->values("PRE_TARGETDEPS")) { |
|
268 // Predeps get mangled in windows, so fix them to more sbsv2 friendly format |
|
269 #if defined(Q_OS_WIN) |
|
270 if (item.mid(1, 1) == ":") |
|
271 item = item.mid(0, 1).toUpper().append(item.mid(1)); // Fix drive to uppercase |
|
272 #endif |
|
273 item.replace("\\", "/"); |
|
274 allPreDeps << escapeDependencyPath(item); |
|
275 } |
|
276 |
|
277 foreach (QString item, project->values("GENERATED_SOURCES")) { |
|
278 allPreDeps.append(fileInfo(item).absoluteFilePath()); |
|
279 } |
|
280 |
|
281 for (QMap<QString, QStringList>::iterator it = sources.begin(); it != sources.end(); ++it) { |
|
282 QString currentSourcePath = it.key(); |
|
283 QStringList values = it.value(); |
|
284 for (int i = 0; i < values.size(); ++i) { |
|
285 QString sourceFile = currentSourcePath + "/" + values.at(i); |
|
286 QStringList deps = findDependencies(QDir::toNativeSeparators(sourceFile)); |
|
287 foreach(QString depItem, deps) { |
|
288 appendIfnotExist(allPreDeps, fileInfo(depItem).absoluteFilePath()); |
|
289 } |
|
290 } |
|
291 } |
|
292 |
|
293 // Write FLM rules for all extra targets and compilers that we depend on to build the target. |
|
294 QStringList extraTargets; |
|
295 extraTargets << project->values("QMAKE_EXTRA_TARGETS") << project->values("QMAKE_EXTRA_COMPILERS"); |
|
296 foreach(QString item, extraTargets) { |
|
297 foreach(QString targetItem, project->values(QLatin1String("QMAKE_INTERNAL_ET_PARSED_TARGETS.") + item)) { |
|
298 // Make sure targetpath is absolute |
|
299 QString absoluteTarget = fileInfo(targetItem).absoluteFilePath(); |
|
300 if (allPreDeps.contains(absoluteTarget)) { |
|
301 QStringList deps = project->values(QLatin1String("QMAKE_INTERNAL_ET_PARSED_DEPS.") + item + targetItem); |
|
302 QString commandItem = project->values(QLatin1String("QMAKE_INTERNAL_ET_PARSED_CMD.") + item + targetItem).join(" "); |
|
303 |
|
304 |
|
305 // Make sure all deps paths are absolute |
|
306 QString absoluteDeps; |
|
307 foreach (QString depItem, deps) { |
|
308 if (!depItem.isEmpty()) { |
|
309 absoluteDeps.append(fileInfo(depItem).absoluteFilePath()); |
|
310 absoluteDeps.append(" "); |
|
311 } |
|
312 } |
|
313 |
|
314 t << "START EXTENSION qt/qmake_extra_pre_targetdep" << endl; |
|
315 t << "OPTION PREDEP_TARGET " << absoluteTarget << endl; |
|
316 t << "OPTION DEPS " << absoluteDeps << endl; |
|
317 |
|
318 if (commandItem.indexOf("$(INCPATH)") != -1) |
|
319 commandItem.replace("$(INCPATH)", incPath.join(" ")); |
|
320 if (commandItem.indexOf("$(DEFINES)") != -1) |
|
321 commandItem.replace("$(DEFINES)", defines.join(" ")); |
|
322 |
|
323 // Sbsv2 strips all backslashes (even doubles ones) from option parameters, so just replace them with slashes |
|
324 // Problem: If some command actually needs backslashes for something else than dir separator, we are out of luck... |
|
325 commandItem.replace("\\", "/"); |
|
326 t << "OPTION COMMAND " << commandItem << endl; |
|
327 t << "END" << endl; |
|
328 } |
|
329 } |
|
330 } |
|
331 |
|
332 t << endl; |
|
333 |
|
334 // Write winscw deployment rules |
|
335 QString remoteTestPath = epocRoot() + QLatin1String("epoc32/winscw/c/private/") + privateDirUid; |
|
336 DeploymentList depList; |
|
337 initProjectDeploySymbian(project, depList, remoteTestPath, false, QLatin1String("winscw"), QLatin1String("udeb"), generatedDirs, generatedFiles); |
|
338 |
|
339 //:QTP:QTPROD-92 Deployment of plugins requires WINSCW build before ARM build |
|
340 t << "#if defined(WINSCW)" << endl; |
|
341 //write WINSCW deployment |
|
342 writeSbsDeploymentList(depList, t); |
|
343 t << "#else" << endl; |
|
344 //write ARMV5 deployment |
|
345 remoteTestPath = epocRoot() + QLatin1String("epoc32/data/z/private/") + privateDirUid; |
|
346 depList.clear(); |
|
347 generatedDirs.clear(); |
|
348 generatedFiles.clear(); |
|
349 initProjectDeploySymbian(project, depList, remoteTestPath, false, QLatin1String("armv5"), QLatin1String("urel"), generatedDirs, generatedFiles); |
|
350 writeSbsDeploymentList(depList, t); |
|
351 t << "#endif" << endl; |
|
352 t << endl; |
|
353 |
|
354 // Write post link rules |
|
355 if (!project->isEmpty("QMAKE_POST_LINK")) { |
|
356 t << "START EXTENSION qt/qmake_post_link" << endl; |
|
357 t << "OPTION POST_LINK_CMD " << var("QMAKE_POST_LINK") << endl; |
|
358 t << "OPTION LINK_TARGET " << removePathSeparators(escapeFilePath(fileFixify(project->first("TARGET"))).append(".").append(getTargetExtension())) << endl; |
|
359 t << "END" << endl; |
|
360 t << endl; |
|
361 } |
|
362 |
|
363 // Application icon generation |
|
364 QStringList icons = project->values("ICON"); |
|
365 if (icons.size()) { |
|
366 QString icon = icons.first(); |
|
367 if (icons.size() > 1) |
|
368 fprintf(stderr, "Warning: Only first icon specified in ICON variable is used: '%s'.", qPrintable(icon)); |
|
369 |
|
370 t << "START EXTENSION s60/mifconv" << endl; |
|
371 |
|
372 QFileInfo iconInfo = fileInfo(icon); |
|
373 QString iconPath = iconInfo.path(); |
|
374 QString iconFile = iconInfo.baseName(); |
|
375 |
|
376 t << "OPTION SOURCES -c32 " << iconFile << endl; |
|
377 t << "OPTION SOURCEDIR " << iconPath << endl; |
|
378 t << "OPTION TARGETFILE " << uid3 << ".mif" << endl; |
|
379 t << "OPTION SVGENCODINGVERSION 3" << endl; // Compatibility with S60 3.1 devices and up |
|
380 t << "END" << endl; |
|
381 } |
|
382 |
|
383 // Generate temp dirs |
|
384 QString tempDirs; |
|
385 for (QMap<QString, QStringList>::iterator it = systeminclude.begin(); it != systeminclude.end(); ++it) { |
|
386 QStringList values = it.value(); |
|
387 for (int i = 0; i < values.size(); ++i) { |
|
388 QString value = values.at(i); |
|
389 if (value.endsWith("/" QT_EXTRA_INCLUDE_DIR)) { |
|
390 value = fileInfo(value).absoluteFilePath(); |
|
391 tempDirs.append(value); |
|
392 tempDirs.append(" "); |
|
393 } |
|
394 } |
|
395 } |
|
396 |
|
397 if (tempDirs.size()) |
|
398 tempDirs.chop(1); // Remove final space |
|
399 |
|
400 t << "START EXTENSION qt/qmake_generate_temp_dirs" << endl; |
|
401 t << "OPTION DIRS " << tempDirs << endl; |
|
402 t << "END" << endl; |
|
403 t << endl; |
|
404 |
|
405 /* :QTP:QTPROD-155: Don't write .make.cache during the compilation, it causes dependency problems in |
|
406 * the parallel build clusters |
|
407 t << "START EXTENSION qt/qmake_store_build" << endl; |
|
408 t << "END" << endl; |
|
409 t << endl; |
|
410 */ |
|
411 |
|
412 t << endl; |
|
413 } |
|
414 |
|
415 void SymbianSbsv2MakefileGenerator::writeBldInfMkFilePart(QTextStream& t, bool addDeploymentExtension) |
|
416 { |
|
417 // We don't generate extension makefile in sbsb2 |
|
418 Q_UNUSED(t); |
|
419 Q_UNUSED(addDeploymentExtension); |
|
420 } |