1 /****************************************************************************
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the qmake application of the Qt Toolkit.
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
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.
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.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "symmake_sbsv2.h"
43 #include "initprojectdeploy_symbian.h"
46 #include <qstringlist.h>
48 #include <qdatetime.h>
51 SymbianSbsv2MakefileGenerator::SymbianSbsv2MakefileGenerator() : SymbianMakefileGenerator() { }
52 SymbianSbsv2MakefileGenerator::~SymbianSbsv2MakefileGenerator() { }
54 #define FLM_DEST_DIR "epoc32/tools/makefile_templates/qt"
55 #define FLM_SOURCE_DIR "/mkspecs/symbian-sbsv2/flm/qt"
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()
61 static bool flmExportDone
= false;
64 QDir sourceDir
= QDir(QLibraryInfo::location(QLibraryInfo::PrefixPath
) + FLM_SOURCE_DIR
);
65 QFileInfoList sourceInfos
= sourceDir
.entryInfoList(QDir::Files
);
67 QDir
destDir(epocRoot() + FLM_DEST_DIR
);
68 if (!destDir
.exists()) {
69 if (destDir
.mkpath(destDir
.absolutePath()))
70 generatedDirs
<< destDir
.absolutePath();
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 generatedFiles
<< destInfo
.absoluteFilePath();
81 fprintf(stderr
, "Error: Could not copy '%s' -> '%s'\n",
82 qPrintable(item
.absoluteFilePath()),
83 qPrintable(destInfo
.absoluteFilePath()));
90 void SymbianSbsv2MakefileGenerator::writeMkFile(const QString
& wrapperFileName
, bool deploymentOnly
)
92 // Can't use extension makefile with sbsv2
93 Q_UNUSED(wrapperFileName
);
94 Q_UNUSED(deploymentOnly
);
97 void SymbianSbsv2MakefileGenerator::writeWrapperMakefile(QFile
& wrapperFile
, bool isPrimaryMakefile
)
99 QStringList allPlatforms
;
100 foreach(QString platform
, project
->values("SYMBIAN_PLATFORMS")) {
101 allPlatforms
<< platform
.toLower();
104 QStringList debugPlatforms
= allPlatforms
;
105 QStringList releasePlatforms
= allPlatforms
;
106 releasePlatforms
.removeAll("winscw"); // No release for emulator
109 if (project
->values("CONFIG").contains("symbian_test", Qt::CaseInsensitive
))
110 testClause
= QLatin1String(".test");
112 testClause
= QLatin1String("");
114 QTextStream
t(&wrapperFile
);
116 t
<< "# ==============================================================================" << endl
;
117 t
<< "# Generated by qmake (" << qmake_version() << ") (Qt " << QT_VERSION_STR
<< ") on: ";
118 t
<< QDateTime::currentDateTime().toString() << endl
;
119 t
<< "# This file is generated by qmake and should not be modified by the" << endl
;
120 t
<< "# user." << endl
;
121 t
<< "# Name : " << wrapperFile
.fileName() << endl
;
122 t
<< "# Description : Wrapper Makefile for calling Symbian build tools" << endl
;
124 t
<< "# ==============================================================================" << "\n" << endl
;
126 t
<< "MAKEFILE = " << wrapperFile
.fileName() << endl
;
127 t
<< "QMAKE = " << Option::fixPathToTargetOS(var("QMAKE_QMAKE")) << endl
;
128 t
<< "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl
;
129 t
<< "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl
;
130 t
<< "MOVE = " << var("QMAKE_MOVE") << endl
;
131 t
<< "DEBUG_PLATFORMS = " << debugPlatforms
.join(" ") << endl
;
132 t
<< "RELEASE_PLATFORMS = " << releasePlatforms
.join(" ") << endl
;
133 t
<< "MAKE = make" << endl
;
134 t
<< "SBS = sbs" << endl
;
136 t
<< "DEFINES" << '\t' << " = "
137 << varGlue("PRL_EXPORT_DEFINES","-D"," -D"," ")
138 << varGlue("QMAKE_COMPILER_DEFINES", "-D", "-D", " ")
139 << varGlue("DEFINES","-D"," -D","") << endl
;
141 t
<< "INCPATH" << '\t' << " = ";
143 for (QMap
<QString
, QStringList
>::iterator it
= systeminclude
.begin(); it
!= systeminclude
.end(); ++it
) {
144 QStringList values
= it
.value();
145 for (int i
= 0; i
< values
.size(); ++i
) {
146 t
<< " -I\"" << values
.at(i
) << "\" ";
150 t
<< "first: default" << endl
;
151 if (debugPlatforms
.contains("winscw"))
152 t
<< "default: debug-winscw";
153 else if (debugPlatforms
.contains("armv5"))
154 t
<< "default: debug-armv5";
155 else if (debugPlatforms
.size())
156 t
<< "default: debug-" << debugPlatforms
.first();
161 if (!isPrimaryMakefile
) {
164 t
<< "all: debug release" << endl
;
166 t
<< "qmake:" << endl
;
167 t
<< "\t$(QMAKE) -spec symbian-sbsv2 -o \"" << fileInfo(Option::output
.fileName()).fileName()
168 << "\" \"" << project
->projectFile() << "\"" << endl
;
170 t
<< BLD_INF_FILENAME
":" << endl
;
171 t
<< "\t$(QMAKE)" << endl
;
174 t
<< "debug: " << BLD_INF_FILENAME
<< endl
;
175 foreach(QString item
, debugPlatforms
) {
176 t
<< "\t$(SBS) -c " << item
<< "_udeb" << testClause
<< endl
;
179 t
<< "release: " << BLD_INF_FILENAME
<< endl
;
180 foreach(QString item
, releasePlatforms
) {
181 t
<< "\t$(SBS) -c " << item
<< "_urel" << testClause
<< endl
;
185 // For more specific builds, targets are in this form: build-platform, e.g. release-armv5
186 foreach(QString item
, debugPlatforms
) {
187 t
<< "debug-" << item
<< ": " << BLD_INF_FILENAME
<< endl
;
188 t
<< "\t$(SBS) -c " << item
<< "_udeb" << testClause
<< endl
;
191 foreach(QString item
, releasePlatforms
) {
192 t
<< "release-" << item
<< ": " << BLD_INF_FILENAME
<< endl
;
193 t
<< "\t$(SBS) -c " << item
<< "_urel" << testClause
<< endl
;
197 t
<< "export: " << BLD_INF_FILENAME
<< endl
;
198 t
<< "\t$(SBS) export" << endl
;
201 t
<< "cleanexport: " << BLD_INF_FILENAME
<< endl
;
202 t
<< "\t$(SBS) cleanexport" << endl
;
207 // Add all extra targets including extra compiler targest also to wrapper makefile,
208 // even though many of them may have already been added to bld.inf as FLMs.
209 // This is to enable use of targets like 'mocables', which call targets generated by extra compilers.
210 if (targetType
!= TypeSubdirs
) {
211 t
<< extraTargetsCache
;
212 t
<< extraCompilersCache
;
214 QList
<MakefileGenerator::SubTarget
*> subtargets
= findSubDirsSubTargets();
215 writeSubTargets(t
, subtargets
, SubTargetSkipDefaultVariables
|SubTargetSkipDefaultTargets
);
216 qDeleteAll(subtargets
);
221 generateDistcleanTargets(t
);
223 t
<< "clean: " << BLD_INF_FILENAME
<< endl
;
224 t
<< "\t-$(SBS) reallyclean" << endl
;
227 // create execution target
228 if (debugPlatforms
.contains("winscw") && targetType
== TypeExe
) {
230 t
<< "\t-call " << epocRoot() << "epoc32/release/winscw/udeb/" << removePathSeparators(escapeFilePath(fileFixify(project
->first("TARGET"))).append(".exe")) << endl
<< endl
;
234 void SymbianSbsv2MakefileGenerator::writeBldInfExtensionRulesPart(QTextStream
& t
)
236 // Makes sure we have needed FLMs in place.
239 // Parse extra compilers data
243 defines
<< varGlue("PRL_EXPORT_DEFINES","-D"," -D"," ")
244 << varGlue("QMAKE_COMPILER_DEFINES", "-D", "-D", " ")
245 << varGlue("DEFINES","-D"," -D","");
246 for (QMap
<QString
, QStringList
>::iterator it
= systeminclude
.begin(); it
!= systeminclude
.end(); ++it
) {
247 QStringList values
= it
.value();
248 for (int i
= 0; i
< values
.size(); ++i
) {
249 incPath
<< QLatin1String(" -I\"") + values
.at(i
) + "\"";
253 // Write extra compilers and targets to initialize QMAKE_ET_* variables
254 // Cache results to avoid duplicate calls when creating wrapper makefile
255 QTextStream
extraCompilerStream(&extraCompilersCache
);
256 QTextStream
extraTargetStream(&extraTargetsCache
);
257 writeExtraCompilerTargets(extraCompilerStream
);
258 writeExtraTargets(extraTargetStream
);
260 // Figure out everything the target depends on as we don't want to run extra targets that
261 // are not necessary.
262 QStringList allPreDeps
;
263 foreach(QString item
, project
->values("PRE_TARGETDEPS")) {
264 // Predeps get mangled in windows, so fix them to more sbsv2 friendly format
265 #if defined(Q_OS_WIN)
266 if (item
.mid(1, 1) == ":")
267 item
= item
.mid(0, 1).toUpper().append(item
.mid(1)); // Fix drive to uppercase
269 item
.replace("\\", "/");
270 allPreDeps
<< escapeDependencyPath(item
);
273 foreach (QString item
, project
->values("GENERATED_SOURCES")) {
274 allPreDeps
.append(fileInfo(item
).absoluteFilePath());
277 for (QMap
<QString
, QStringList
>::iterator it
= sources
.begin(); it
!= sources
.end(); ++it
) {
278 QString currentSourcePath
= it
.key();
279 QStringList values
= it
.value();
280 for (int i
= 0; i
< values
.size(); ++i
) {
281 QString sourceFile
= currentSourcePath
+ "/" + values
.at(i
);
282 QStringList deps
= findDependencies(QDir::toNativeSeparators(sourceFile
));
283 foreach(QString depItem
, deps
) {
284 appendIfnotExist(allPreDeps
, fileInfo(depItem
).absoluteFilePath());
289 // Write FLM rules for all extra targets and compilers that we depend on to build the target.
290 QStringList extraTargets
;
291 extraTargets
<< project
->values("QMAKE_EXTRA_TARGETS") << project
->values("QMAKE_EXTRA_COMPILERS");
292 foreach(QString item
, extraTargets
) {
293 foreach(QString targetItem
, project
->values(QLatin1String("QMAKE_INTERNAL_ET_PARSED_TARGETS.") + item
)) {
294 // Make sure targetpath is absolute
295 QString absoluteTarget
= fileInfo(targetItem
).absoluteFilePath();
296 if (allPreDeps
.contains(absoluteTarget
)) {
297 QStringList deps
= project
->values(QLatin1String("QMAKE_INTERNAL_ET_PARSED_DEPS.") + item
+ targetItem
);
298 QString commandItem
= project
->values(QLatin1String("QMAKE_INTERNAL_ET_PARSED_CMD.") + item
+ targetItem
).join(" ");
301 // Make sure all deps paths are absolute
302 QString absoluteDeps
;
303 foreach (QString depItem
, deps
) {
304 if (!depItem
.isEmpty()) {
305 absoluteDeps
.append(fileInfo(depItem
).absoluteFilePath());
306 absoluteDeps
.append(" ");
310 t
<< "START EXTENSION qt/qmake_extra_pre_targetdep" << endl
;
311 t
<< "OPTION PREDEP_TARGET " << absoluteTarget
<< endl
;
312 t
<< "OPTION DEPS " << absoluteDeps
<< endl
;
314 if (commandItem
.indexOf("$(INCPATH)") != -1)
315 commandItem
.replace("$(INCPATH)", incPath
.join(" "));
316 if (commandItem
.indexOf("$(DEFINES)") != -1)
317 commandItem
.replace("$(DEFINES)", defines
.join(" "));
319 // Sbsv2 strips all backslashes (even doubles ones) from option parameters, so just replace them with slashes
320 // Problem: If some command actually needs backslashes for something else than dir separator, we are out of luck...
321 commandItem
.replace("\\", "/");
322 t
<< "OPTION COMMAND " << commandItem
<< endl
;
330 // Write winscw deployment rules
331 QString remoteTestPath
= epocRoot() + QLatin1String("epoc32/winscw/c/private/") + privateDirUid
;
332 DeploymentList depList
;
333 initProjectDeploySymbian(project
, depList
, remoteTestPath
, false, QLatin1String("winscw"), QLatin1String("udeb"), generatedDirs
, generatedFiles
);
335 t
<< "#if defined(WINSCW)" << endl
;
336 for (int i
= 0; i
< depList
.size(); ++i
) {
337 t
<< "START EXTENSION qt/qmake_emulator_deployment" << endl
;
338 QString fromItem
= depList
.at(i
).from
;
339 QString toItem
= depList
.at(i
).to
;
340 fromItem
.replace("\\", "/");
341 toItem
.replace("\\", "/");
342 #if defined(Q_OS_WIN)
343 toItem
.prepend(QDir::current().absolutePath().left(2)); // add drive
345 t
<< "OPTION DEPLOY_SOURCE " << fromItem
<< endl
;
346 t
<< "OPTION DEPLOY_TARGET " << toItem
<< endl
;
349 t
<< "#endif" << endl
;
353 // Write post link rules
354 if (!project
->isEmpty("QMAKE_POST_LINK")) {
355 t
<< "START EXTENSION qt/qmake_post_link" << endl
;
356 t
<< "OPTION POST_LINK_CMD " << var("QMAKE_POST_LINK") << endl
;
357 t
<< "OPTION LINK_TARGET " << removePathSeparators(escapeFilePath(fileFixify(project
->first("TARGET"))).append(".").append(getTargetExtension())) << endl
;
362 // Application icon generation
363 QStringList icons
= project
->values("ICON");
365 QString icon
= icons
.first();
366 if (icons
.size() > 1)
367 fprintf(stderr
, "Warning: Only first icon specified in ICON variable is used: '%s'.", qPrintable(icon
));
369 t
<< "START EXTENSION s60/mifconv" << endl
;
371 QFileInfo iconInfo
= fileInfo(icon
);
372 QString iconPath
= iconInfo
.path();
373 QString iconFile
= iconInfo
.baseName();
375 t
<< "OPTION SOURCES -c32 " << iconFile
<< endl
;
376 t
<< "OPTION SOURCEDIR " << iconPath
<< endl
;
377 t
<< "OPTION TARGETFILE " << uid3
<< ".mif" << endl
;
378 t
<< "OPTION SVGENCODINGVERSION 3" << endl
; // Compatibility with S60 3.1 devices and up
382 // Generate temp dirs
384 for (QMap
<QString
, QStringList
>::iterator it
= systeminclude
.begin(); it
!= systeminclude
.end(); ++it
) {
385 QStringList values
= it
.value();
386 for (int i
= 0; i
< values
.size(); ++i
) {
387 QString value
= values
.at(i
);
388 if (value
.endsWith("/" QT_EXTRA_INCLUDE_DIR
)) {
389 value
= fileInfo(value
).absoluteFilePath();
390 tempDirs
.append(value
);
391 tempDirs
.append(" ");
397 tempDirs
.chop(1); // Remove final space
399 t
<< "START EXTENSION qt/qmake_generate_temp_dirs" << endl
;
400 t
<< "OPTION DIRS " << tempDirs
<< endl
;
404 t
<< "START EXTENSION qt/qmake_store_build" << endl
;
411 void SymbianSbsv2MakefileGenerator::writeBldInfMkFilePart(QTextStream
& t
, bool addDeploymentExtension
)
413 // We don't generate extension makefile in sbsb2
415 Q_UNUSED(addDeploymentExtension
);