source: trunk/qmake/generators/symbian/symmake_abld.cpp@ 599

Last change on this file since 599 was 561, checked in by Dmitry A. Kuminov, 16 years ago

trunk: Merged in qt 4.6.1 sources.

  • Property svn:eol-style set to native
File size: 20.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 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 "symmake_abld.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#define DO_NOTHING_TARGET "do_nothing"
52#define CREATE_TEMPS_TARGET "create_temps"
53#define EXTENSION_CLEAN "extension_clean"
54#define PRE_TARGETDEPS_TARGET "pre_targetdeps"
55#define COMPILER_CLEAN_TARGET "compiler_clean"
56#define FINALIZE_TARGET "finalize"
57#define GENERATED_SOURCES_TARGET "generated_sources"
58#define ALL_SOURCE_DEPS_TARGET "all_source_deps"
59#define WINSCW_DEPLOYMENT_TARGET "winscw_deployment"
60#define WINSCW_DEPLOYMENT_CLEAN_TARGET "winscw_deployment_clean"
61#define STORE_BUILD_TARGET "store_build"
62
63SymbianAbldMakefileGenerator::SymbianAbldMakefileGenerator() : SymbianMakefileGenerator() { }
64SymbianAbldMakefileGenerator::~SymbianAbldMakefileGenerator() { }
65
66void SymbianAbldMakefileGenerator::writeMkFile(const QString& wrapperFileName, bool deploymentOnly)
67{
68 QString gnuMakefileName = QLatin1String("Makefile_") + uid3;
69 removeSpecialCharacters(gnuMakefileName);
70 gnuMakefileName.append(".mk");
71
72 QFile ft(gnuMakefileName);
73 if (ft.open(QIODevice::WriteOnly)) {
74 generatedFiles << ft.fileName();
75 QTextStream t(&ft);
76
77 t << "# ==============================================================================" << endl;
78 t << "# Generated by qmake (" << qmake_version() << ") (Qt " << QT_VERSION_STR << ") on: ";
79 t << QDateTime::currentDateTime().toString() << endl;
80 t << "# This file is generated by qmake and should not be modified by the" << endl;
81 t << "# user." << endl;
82 t << "# Name : " << gnuMakefileName << endl;
83 t << "# Part of : " << project->values("TARGET").join(" ") << endl;
84 t << "# Description : This file is used to call necessary targets on wrapper makefile" << endl;
85 t << "# during normal Symbian build process." << endl;
86 t << "# Version : " << endl;
87 t << "#" << endl;
88 t << "# ==============================================================================" << "\n" << endl;
89
90 t << endl << endl;
91
92 t << "MAKE = make" << endl;
93 t << endl;
94
95 t << "VISUAL_CFG = RELEASE" << endl;
96 t << "ifeq \"$(CFG)\" \"UDEB\"" << endl;
97 t << "VISUAL_CFG = DEBUG" << endl;
98 t << "endif" << endl;
99 t << endl;
100
101 t << DO_NOTHING_TARGET " :" << endl;
102 t << "\t" << "@rem " DO_NOTHING_TARGET << endl << endl;
103
104 QString buildDeps;
105 QString cleanDeps;
106 QString finalDeps;
107 QString cleanDepsWinscw;
108 QString finalDepsWinscw;
109 QStringList wrapperTargets;
110 if (deploymentOnly) {
111 buildDeps.append(STORE_BUILD_TARGET);
112 cleanDeps.append(DO_NOTHING_TARGET);
113 cleanDepsWinscw.append(WINSCW_DEPLOYMENT_CLEAN_TARGET);
114 finalDeps.append(DO_NOTHING_TARGET);
115 finalDepsWinscw.append(WINSCW_DEPLOYMENT_TARGET);
116 wrapperTargets << WINSCW_DEPLOYMENT_TARGET
117 << WINSCW_DEPLOYMENT_CLEAN_TARGET
118 << STORE_BUILD_TARGET;
119 } else {
120 buildDeps.append(CREATE_TEMPS_TARGET " " PRE_TARGETDEPS_TARGET " " STORE_BUILD_TARGET);
121 cleanDeps.append(EXTENSION_CLEAN);
122 cleanDepsWinscw.append(EXTENSION_CLEAN " " WINSCW_DEPLOYMENT_CLEAN_TARGET);
123 finalDeps.append(FINALIZE_TARGET);
124 finalDepsWinscw.append(FINALIZE_TARGET " " WINSCW_DEPLOYMENT_TARGET);
125 wrapperTargets << PRE_TARGETDEPS_TARGET
126 << CREATE_TEMPS_TARGET
127 << EXTENSION_CLEAN
128 << FINALIZE_TARGET
129 << WINSCW_DEPLOYMENT_CLEAN_TARGET
130 << WINSCW_DEPLOYMENT_TARGET
131 << STORE_BUILD_TARGET;
132 }
133
134 t << "MAKMAKE: " << buildDeps << endl << endl;
135 t << "LIB: " << buildDeps << endl << endl;
136 t << "BLD: " << buildDeps << endl << endl;
137 t << "ifeq \"$(PLATFORM)\" \"WINSCW\"" << endl;
138 t << "CLEAN: " << cleanDepsWinscw << endl;
139 t << "else" << endl;
140 t << "CLEAN: " << cleanDeps << endl;
141 t << "endif" << endl << endl;
142 t << "CLEANLIB: " DO_NOTHING_TARGET << endl << endl;
143 t << "RESOURCE: " DO_NOTHING_TARGET << endl << endl;
144 t << "FREEZE: " DO_NOTHING_TARGET << endl << endl;
145 t << "SAVESPACE: " DO_NOTHING_TARGET << endl << endl;
146 t << "RELEASABLES: " DO_NOTHING_TARGET << endl << endl;
147 t << "ifeq \"$(PLATFORM)\" \"WINSCW\"" << endl;
148 t << "FINAL: " << finalDepsWinscw << endl;
149 t << "else" << endl;
150 t << "FINAL: " << finalDeps << endl;
151 t << "endif" << endl << endl;
152
153 QString makefile(Option::fixPathToTargetOS(fileInfo(wrapperFileName).canonicalFilePath()));
154 foreach(QString target, wrapperTargets) {
155 t << target << " : " << makefile << endl;
156 t << "\t-$(MAKE) -f \"" << makefile << "\" " << target << " QT_SIS_TARGET=$(VISUAL_CFG)-$(PLATFORM)" << endl << endl;
157 }
158
159 t << endl;
160 } // if(ft.open(QIODevice::WriteOnly))
161}
162
163void SymbianAbldMakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, bool isPrimaryMakefile)
164{
165 QStringList allPlatforms;
166 foreach(QString platform, project->values("SYMBIAN_PLATFORMS")) {
167 allPlatforms << platform.toLower();
168 }
169
170 QStringList debugPlatforms = allPlatforms;
171 QStringList releasePlatforms = allPlatforms;
172 releasePlatforms.removeAll("winscw"); // No release for emulator
173
174 QString testClause;
175 if (project->values("CONFIG").contains("symbian_test", Qt::CaseInsensitive))
176 testClause = QLatin1String(" test");
177 else
178 testClause = QLatin1String("");
179
180 QTextStream t(&wrapperFile);
181
182 t << "# ==============================================================================" << endl;
183 t << "# Generated by qmake (" << qmake_version() << ") (Qt " << QT_VERSION_STR << ") on: ";
184 t << QDateTime::currentDateTime().toString() << endl;
185 t << "# This file is generated by qmake and should not be modified by the" << endl;
186 t << "# user." << endl;
187 t << "# Name : " << wrapperFile.fileName() << endl;
188 t << "# Description : Wrapper Makefile for calling Symbian build tools" << endl;
189 t << "#" << endl;
190 t << "# ==============================================================================" << "\n" << endl;
191 t << endl;
192
193 t << "MAKEFILE = " << wrapperFile.fileName() << endl;
194 t << "QMAKE = " << Option::fixPathToTargetOS(var("QMAKE_QMAKE")) << endl;
195 t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl;
196 t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl;
197 t << "MOVE = " << var("QMAKE_MOVE") << endl;
198 t << "XCOPY = xcopy /d /f /h /r /y /i" << endl;
199 t << "ABLD = ABLD.BAT" << endl;
200 t << "DEBUG_PLATFORMS = " << debugPlatforms.join(" ") << endl;
201 t << "RELEASE_PLATFORMS = " << releasePlatforms.join(" ") << endl;
202 t << "MAKE = make" << endl;
203 t << endl;
204 t << "ifeq (WINS,$(findstring WINS, $(PLATFORM)))" << endl;
205 t << "ZDIR=$(EPOCROOT)epoc32\\release\\$(PLATFORM)\\$(CFG)\\Z" << endl;
206 t << "else" << endl;
207 t << "ZDIR=$(EPOCROOT)epoc32\\data\\z" << endl;
208 t << "endif" << endl;
209 t << endl;
210 t << "DEFINES" << '\t' << " = "
211 << varGlue("PRL_EXPORT_DEFINES","-D"," -D"," ")
212 << varGlue("QMAKE_COMPILER_DEFINES", "-D", "-D", " ")
213 << varGlue("DEFINES","-D"," -D","") << endl;
214
215 t << "INCPATH" << '\t' << " = ";
216
217 for (QMap<QString, QStringList>::iterator it = systeminclude.begin(); it != systeminclude.end(); ++it) {
218 QStringList values = it.value();
219 for (int i = 0; i < values.size(); ++i) {
220 t << " -I\"" << values.at(i) << "\"";
221 }
222 }
223 t << endl;
224 t << "first: default" << endl;
225 if (debugPlatforms.contains("winscw"))
226 t << "default: debug-winscw";
227 else if (debugPlatforms.contains("armv5"))
228 t << "default: debug-armv5";
229 else if (debugPlatforms.size())
230 t << "default: debug-" << debugPlatforms.first();
231 else
232 t << "default: all";
233
234 t << endl;
235 if (!isPrimaryMakefile) {
236 t << "all:" << endl;
237 } else {
238 t << "all: debug release" << endl;
239 t << endl;
240 t << "qmake:" << endl;
241 t << "\t$(QMAKE) -spec symbian-abld -o \"" << fileInfo(Option::output.fileName()).fileName()
242 << "\" \"" << project->projectFile() << "\"" << endl;
243 t << endl;
244 t << BLD_INF_FILENAME ":" << endl;
245 t << "\t$(QMAKE)" << endl;
246 t << endl;
247 t << "$(ABLD): " BLD_INF_FILENAME << endl;
248 t << "\tbldmake bldfiles" << endl;
249 t << endl;
250
251 t << "debug: $(ABLD)" << endl;
252 foreach(QString item, debugPlatforms) {
253 t << "\t$(ABLD)" << testClause << " build " << item << " udeb" << endl;
254 }
255 t << endl;
256 t << "release: $(ABLD)" << endl;
257 foreach(QString item, releasePlatforms) {
258 t << "\t$(ABLD)" << testClause << " build " << item << " urel" << endl;
259 }
260 t << endl;
261
262 // For more specific builds, targets are in this form: build-platform, e.g. release-armv5
263 foreach(QString item, debugPlatforms) {
264 t << "debug-" << item << ": $(ABLD)" << endl;
265 t << "\t$(ABLD)" << testClause << " build " << item << " udeb" << endl;
266 }
267
268 foreach(QString item, releasePlatforms) {
269 t << "release-" << item << ": $(ABLD)" << endl;
270 t << "\t$(ABLD)" << testClause << " build " << item << " urel" << endl;
271 }
272
273 t << endl;
274 t << "export: $(ABLD)" << endl;
275 t << "\t$(ABLD)" << testClause << " export" << endl;
276 t << endl;
277
278 t << "cleanexport: $(ABLD)" << endl;
279 t << "\t$(ABLD)" << testClause << " cleanexport" << endl;
280 t << endl;
281
282 }
283
284 // pre_targetdeps target depends on:
285 // - all targets specified in PRE_TARGETDEPS
286 // - the GENERATED_SOURCES sources (so that they get generated)
287 // - all dependencies of sources targeted for compilation
288 // (mainly to ensure that any included UNUSED_SOURCES that need to be generated get generated)
289 //
290 // Unfortunately, Symbian build chain doesn't support linking generated objects to target,
291 // so supporting generating sources is the best we can do. This is enough for mocs.
292
293 if (targetType != TypeSubdirs) {
294 writeExtraTargets(t);
295 writeExtraCompilerTargets(t);
296
297 t << CREATE_TEMPS_TARGET ":" << endl;
298 // generate command lines like this ...
299 // -@ if NOT EXIST ".\somedir" mkdir ".\somedir"
300 QStringList dirsToClean;
301 for (QMap<QString, QStringList>::iterator it = systeminclude.begin(); it != systeminclude.end(); ++it) {
302 QStringList values = it.value();
303 for (int i = 0; i < values.size(); ++i) {
304 if (values.at(i).endsWith("/" QT_EXTRA_INCLUDE_DIR)) {
305 QString fixedValue(QDir::toNativeSeparators(values.at(i)));
306 dirsToClean << fixedValue;
307 t << "\t-@ if NOT EXIST \"" << fixedValue << "\" mkdir \""
308 << fixedValue << "\"" << endl;
309 }
310 }
311 }
312 t << endl;
313
314 // Note: EXTENSION_CLEAN will get called many times when doing reallyclean
315 // This is why the "2> NUL" gets appended to generated clean targets in makefile.cpp.
316 t << EXTENSION_CLEAN ": " COMPILER_CLEAN_TARGET << endl;
317 generateCleanCommands(t, dirsToClean, var("QMAKE_DEL_DIR"), " /S /Q ", "", "");
318 t << endl;
319
320 t << PRE_TARGETDEPS_TARGET ":"
321 << MAKEFILE_DEPENDENCY_SEPARATOR GENERATED_SOURCES_TARGET
322 << MAKEFILE_DEPENDENCY_SEPARATOR ALL_SOURCE_DEPS_TARGET;
323 if (project->values("PRE_TARGETDEPS").size())
324 t << MAKEFILE_DEPENDENCY_SEPARATOR << project->values("PRE_TARGETDEPS").join(MAKEFILE_DEPENDENCY_SEPARATOR);
325 t << endl << endl;
326 t << GENERATED_SOURCES_TARGET ":";
327 if (project->values("GENERATED_SOURCES").size())
328 t << MAKEFILE_DEPENDENCY_SEPARATOR << project->values("GENERATED_SOURCES").join(MAKEFILE_DEPENDENCY_SEPARATOR);
329 t << endl << endl;
330 t << ALL_SOURCE_DEPS_TARGET ":";
331
332 QStringList allDeps;
333 for (QMap<QString, QStringList>::iterator it = sources.begin(); it != sources.end(); ++it) {
334 QString currentSourcePath = it.key();
335 QStringList values = it.value();
336 for (int i = 0; i < values.size(); ++i) {
337 // we need additional check
338 QString sourceFile = currentSourcePath + "/" + values.at(i);
339 QStringList deps = findDependencies(QDir::toNativeSeparators(sourceFile));
340 appendIfnotExist(allDeps, deps);
341 }
342 }
343
344 foreach(QString item, allDeps) {
345 t << MAKEFILE_DEPENDENCY_SEPARATOR << item;
346 }
347 t << endl << endl;
348
349 // Post link operations
350 t << FINALIZE_TARGET ":" << endl;
351 if (!project->isEmpty("QMAKE_POST_LINK")) {
352 t << '\t' << var("QMAKE_POST_LINK");
353 t << endl;
354 }
355 t << endl;
356 } else {
357 QList<MakefileGenerator::SubTarget*> subtargets = findSubDirsSubTargets();
358 writeSubTargets(t, subtargets, SubTargetSkipDefaultVariables | SubTargetSkipDefaultTargets);
359 qDeleteAll(subtargets);
360 }
361
362 writeDeploymentTargets(t);
363
364 writeSisTargets(t);
365
366 writeStoreBuildTarget(t);
367
368 generateDistcleanTargets(t);
369
370 t << "clean: $(ABLD)" << endl;
371 t << "\t-$(ABLD)" << testClause << " reallyclean" << endl;
372 t << "\t-bldmake clean" << endl;
373 t << endl;
374
375 t << "clean-debug: $(ABLD)" << endl;
376 foreach(QString item, debugPlatforms) {
377 t << "\t$(ABLD)" << testClause << " reallyclean " << item << " udeb" << endl;
378 }
379 t << endl;
380 t << "clean-release: $(ABLD)" << endl;
381 foreach(QString item, releasePlatforms) {
382 t << "\t$(ABLD)" << testClause << " reallyclean " << item << " urel" << endl;
383 }
384 t << endl;
385
386 // For more specific builds, targets are in this form: clean-build-platform, e.g. clean-release-armv5
387 foreach(QString item, debugPlatforms) {
388 t << "clean-debug-" << item << ": $(ABLD)" << endl;
389 t << "\t$(ABLD)" << testClause << " reallyclean " << item << " udeb" << endl;
390 }
391 foreach(QString item, releasePlatforms) {
392 t << "clean-release-" << item << ": $(ABLD)" << endl;
393 t << "\t$(ABLD)" << testClause << " reallyclean " << item << " urel" << endl;
394 }
395 t << endl;
396
397 generateExecutionTargets(t, debugPlatforms);
398}
399
400void SymbianAbldMakefileGenerator::writeBldInfExtensionRulesPart(QTextStream& t, const QString &iconTargetFile)
401{
402 // We don't use extensions for anything in abld
403 Q_UNUSED(t);
404 Q_UNUSED(iconTargetFile);
405}
406
407bool SymbianAbldMakefileGenerator::writeDeploymentTargets(QTextStream &t)
408{
409 t << WINSCW_DEPLOYMENT_TARGET ":" << endl;
410
411 QString remoteTestPath = epocRoot() + QLatin1String("epoc32\\winscw\\c\\private\\") + privateDirUid; // default 4 OpenC; 4 all Symbian too
412 DeploymentList depList;
413 initProjectDeploySymbian(project, depList, remoteTestPath, false, QLatin1String("winscw"), QLatin1String("udeb"), generatedDirs, generatedFiles);
414
415 if (depList.size())
416 t << "\t-echo Deploying changed files..." << endl;
417
418 for (int i = 0; i < depList.size(); ++i) {
419 // Xcopy prompts for selecting file or directory if target doesn't exist,
420 // and doesn't provide switch to force file selection. It does provide dir forcing, though,
421 // so strip the last part of the destination.
422 t << "\t-$(XCOPY) \"" << depList.at(i).from << "\" \"" << depList.at(i).to.left(depList.at(i).to.lastIndexOf("\\") + 1) << "\"" << endl;
423 }
424
425 t << endl;
426
427 t << WINSCW_DEPLOYMENT_CLEAN_TARGET ":" << endl;
428 QStringList cleanList;
429 for (int i = 0; i < depList.size(); ++i) {
430 cleanList.append(depList.at(i).to);
431 }
432 generateCleanCommands(t, cleanList, "$(DEL_FILE)", "", "", "");
433
434 // Note: If deployment creates any directories, they will not get deleted after cleanup.
435 // To do this in robust fashion could be quite complex.
436
437 t << endl;
438
439 return true;
440}
441
442void SymbianAbldMakefileGenerator::writeStoreBuildTarget(QTextStream &t)
443{
444 t << STORE_BUILD_TARGET ":" << endl;
445 t << "\t@echo # ============================================================================== > " MAKE_CACHE_NAME << endl;
446 t << "\t@echo # This file is generated by make and should not be modified by the user >> " MAKE_CACHE_NAME << endl;
447 t << "\t@echo # Name : " << MAKE_CACHE_NAME << " >> " MAKE_CACHE_NAME << endl;
448 t << "\t@echo # Part of : " << project->values("TARGET").join(" ") << " >> " MAKE_CACHE_NAME << endl;
449 t << "\t@echo # Description : This file is used to cache last build target for >> " MAKE_CACHE_NAME << endl;
450 t << "\t@echo # make sis target. >> " MAKE_CACHE_NAME << endl;
451 t << "\t@echo # Version : >> " MAKE_CACHE_NAME << endl;
452 t << "\t@echo # >> " MAKE_CACHE_NAME << endl;
453 t << "\t@echo # ============================================================================== >> " MAKE_CACHE_NAME << endl;
454 t << "\t@echo. >> " MAKE_CACHE_NAME << endl;
455 t << "\t@echo QT_SIS_TARGET ?= $(QT_SIS_TARGET) >> " MAKE_CACHE_NAME << endl;
456 t << endl;
457
458 generatedFiles << MAKE_CACHE_NAME;
459}
460
461void SymbianAbldMakefileGenerator::writeBldInfMkFilePart(QTextStream& t, bool addDeploymentExtension)
462{
463 // Normally emulator deployment gets done via regular makefile, but since subdirs
464 // do not get that, special deployment only makefile is generated for them if needed.
465 if (targetType != TypeSubdirs || addDeploymentExtension) {
466 QString gnuMakefileName = QLatin1String("Makefile_") + uid3;
467 removeSpecialCharacters(gnuMakefileName);
468 gnuMakefileName.append(".mk");
469 t << "gnumakefile " << gnuMakefileName << endl;
470 }
471}
472
473void SymbianAbldMakefileGenerator::appendAbldTempDirs(QStringList& sysincspaths, QString includepath)
474{
475 // As a workaround for Symbian toolchain insistence to treat include
476 // statements as relative to source file rather than the file they appear in,
477 // we generate extra temporary include directories to make
478 // relative include paths used in various headers to work properly.
479 // Note that this is not a fix-all solution; it's just a stop-gap measure
480 // to make Qt itself build until toolchain can support relative includes in
481 // a way that Qt expects.
482 QString epocPath("epoc32");
483 if (!includepath.contains(epocPath)) // No temp dirs for epoc includes
484 appendIfnotExist(sysincspaths, includepath + QString("/" QT_EXTRA_INCLUDE_DIR));
485}
Note: See TracBrowser for help on using the repository browser.