1 /****************************************************************************
2 ** $Id: qt/msvc_nmake.cpp 3.3.8 edited Jan 11 14:37 $
3 **
4 ** Implementation of NmakeMakefileGenerator class.
5 **
6 ** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.
7 **
8 ** This file is part of qmake.
9 **
10 ** This file may be distributed under the terms of the Q Public License
11 ** as defined by Trolltech ASA of Norway and appearing in the file
12 ** LICENSE.QPL included in the packaging of this file.
13 **
14 ** This file may be distributed and/or modified under the terms of the
15 ** GNU General Public License version 2 as published by the Free Software
16 ** Foundation and appearing in the file LICENSE.GPL included in the
17 ** packaging of this file.
18 **
19 ** Licensees holding valid Qt Enterprise Edition licenses may use this
20 ** file in accordance with the Qt Commercial License Agreement provided
21 ** with the Software.
22 **
23 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
24 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
25 **
26 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
27 ** information about Qt Commercial License Agreements.
28 ** See http://www.trolltech.com/qpl/ for QPL licensing information.
29 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
30 **
31 ** Contact info@trolltech.com if any conditions of this licensing are
32 ** not clear to you.
33 **
34 **********************************************************************/
35
36 #include "msvc_nmake.h"
37 #include "option.h"
38 #include <qregexp.h>
39 #include <qdict.h>
40 #include <qdir.h>
41 #include <stdlib.h>
42 #include <time.h>
43
NmakeMakefileGenerator(QMakeProject * p)44 NmakeMakefileGenerator::NmakeMakefileGenerator(QMakeProject *p) : Win32MakefileGenerator(p), init_flag(FALSE)
45 {
46
47 }
48
49 bool
writeMakefile(QTextStream & t)50 NmakeMakefileGenerator::writeMakefile(QTextStream &t)
51 {
52 writeHeader(t);
53 if(!project->variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty()) {
54 { //write the extra unix targets..
55 QStringList &qut = project->variables()["QMAKE_EXTRA_WIN_TARGETS"];
56 for(QStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it)
57 t << *it << " ";
58 }
59 t << "all clean:" << "\n\t"
60 << "@echo \"Some of the required modules ("
61 << var("QMAKE_FAILED_REQUIREMENTS") << ") are not available.\"" << "\n\t"
62 << "@echo \"Skipped.\"" << endl << endl;
63 writeMakeQmake(t);
64 return TRUE;
65 }
66
67 if(project->first("TEMPLATE") == "app" ||
68 project->first("TEMPLATE") == "lib") {
69 writeNmakeParts(t);
70 return MakefileGenerator::writeMakefile(t);
71 }
72 else if(project->first("TEMPLATE") == "subdirs") {
73 writeSubDirs(t);
74 return TRUE;
75 }
76 return FALSE;
77 }
78
79 QStringList
findDependencies(const QString & file)80 &NmakeMakefileGenerator::findDependencies(const QString &file)
81 {
82 QStringList &aList = MakefileGenerator::findDependencies(file);
83 // Note: The QMAKE_IMAGE_COLLECTION file have all images
84 // as dependency, so don't add precompiled header then
85 if (file == project->first("QMAKE_IMAGE_COLLECTION"))
86 return aList;
87 for(QStringList::Iterator it = Option::cpp_ext.begin(); it != Option::cpp_ext.end(); ++it) {
88 if(file.endsWith(*it)) {
89 if(!precompObj.isEmpty() && !aList.contains(precompObj))
90 aList += precompObj;
91 break;
92 }
93 }
94 return aList;
95 }
96
97 void
writeNmakeParts(QTextStream & t)98 NmakeMakefileGenerator::writeNmakeParts(QTextStream &t)
99 {
100 t << "####### Compiler, tools and options" << endl << endl;
101 t << "CC = " << var("QMAKE_CC") << endl;
102 t << "CXX = " << var("QMAKE_CXX") << endl;
103 t << "LEX = " << var("QMAKE_LEX") << endl;
104 t << "YACC = " << var("QMAKE_YACC") << endl;
105 t << "CFLAGS = " << var("QMAKE_CFLAGS") << " "
106 << varGlue("PRL_EXPORT_DEFINES","-D"," -D","") << " "
107 << varGlue("DEFINES","-D"," -D","") << endl;
108 t << "CXXFLAGS = " << var("QMAKE_CXXFLAGS") << " "
109 << varGlue("PRL_EXPORT_DEFINES","-D"," -D","") << " "
110 << varGlue("DEFINES","-D"," -D","") << endl;
111 t << "LEXFLAGS =" << var("QMAKE_LEXFLAGS") << endl;
112 t << "YACCFLAGS =" << var("QMAKE_YACCFLAGS") << endl;
113
114 t << "INCPATH = ";
115 QStringList &incs = project->variables()["INCLUDEPATH"];
116 for(QStringList::Iterator incit = incs.begin(); incit != incs.end(); ++incit) {
117 QString inc = (*incit);
118 if (inc.endsWith("\\"))
119 inc.truncate(inc.length()-1);
120 if (inc.startsWith("\"") && inc.endsWith("\""))
121 inc = inc.mid(1, inc.length() - 2);
122 t << " -I\"" << inc << "\"";
123 }
124 t << " -I\"" << specdir() << "\""
125 << endl;
126 if(!project->variables()["QMAKE_APP_OR_DLL"].isEmpty()) {
127 t << "LINK = " << var("QMAKE_LINK") << endl;
128 t << "LFLAGS = " << var("QMAKE_LFLAGS");
129 if ( !project->variables()["QMAKE_LIBDIR"].isEmpty() )
130 t << " " << varGlue("QMAKE_LIBDIR","/LIBPATH:\"","\" /LIBPATH:\"","\"");
131 t << endl;
132 t << "LIBS = ";
133 QStringList &libs = project->variables()["QMAKE_LIBS"];
134 for(QStringList::Iterator libit = libs.begin(); libit != libs.end(); ++libit) {
135 QString lib = (*libit);
136 if (lib.endsWith("\\"))
137 lib.truncate(lib.length()-1);
138 t << " \"" << lib << "\"";
139 }
140 t << endl;
141 }
142 else {
143 t << "LIB = " << var("QMAKE_LIB") << endl;
144 }
145 t << "MOC = " << (project->isEmpty("QMAKE_MOC") ? QString("moc") :
146 Option::fixPathToTargetOS(var("QMAKE_MOC"), FALSE)) << endl;
147 t << "UIC = " << (project->isEmpty("QMAKE_UIC") ? QString("uic") :
148 Option::fixPathToTargetOS(var("QMAKE_UIC"), FALSE)) << endl;
149 t << "QMAKE = " << (project->isEmpty("QMAKE_QMAKE") ? QString("qmake") :
150 Option::fixPathToTargetOS(var("QMAKE_QMAKE"), FALSE)) << endl;
151 t << "IDC = " << (project->isEmpty("QMAKE_IDC") ? QString("idc") :
152 Option::fixPathToTargetOS(var("QMAKE_IDC"), FALSE)) << endl;
153 t << "IDL = " << (project->isEmpty("QMAKE_IDL") ? QString("midl") :
154 Option::fixPathToTargetOS(var("QMAKE_IDL"), FALSE)) << endl;
155 t << "ZIP = " << var("QMAKE_ZIP") << endl;
156 t << "COPY_FILE = " << var("QMAKE_COPY") << endl;
157 t << "COPY_DIR = " << var("QMAKE_COPY") << endl;
158 t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl;
159 t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl;
160 t << "MOVE = " << var("QMAKE_MOVE") << endl;
161 t << "CHK_DIR_EXISTS = " << var("QMAKE_CHK_DIR_EXISTS") << endl;
162 t << "MKDIR = " << var("QMAKE_MKDIR") << endl;
163 t << "INSTALL_FILE= " << var("QMAKE_INSTALL_FILE") << endl;
164 t << "INSTALL_DIR = " << var("QMAKE_INSTALL_DIR") << endl;
165 t << endl;
166
167 t << "####### Files" << endl << endl;
168 t << "HEADERS = " << varList("HEADERS") << endl;
169 t << "SOURCES = " << varList("SOURCES") << endl;
170 t << "OBJECTS = " << varList("OBJECTS") << endl;
171 t << "FORMS = " << varList("FORMS") << endl;
172 t << "UICDECLS = " << varList("UICDECLS") << endl;
173 t << "UICIMPLS = " << varList("UICIMPLS") << endl;
174 t << "SRCMOC = " << varList("SRCMOC") << endl;
175 t << "OBJMOC = " << varList("OBJMOC") << endl;
176
177 QString extraCompilerDeps;
178 if(!project->isEmpty("QMAKE_EXTRA_WIN_COMPILERS")) {
179 t << "OBJCOMP = " << varList("OBJCOMP") << endl;
180 extraCompilerDeps += " $(OBJCOMP) ";
181
182 QStringList &comps = project->variables()["QMAKE_EXTRA_WIN_COMPILERS"];
183 for(QStringList::Iterator compit = comps.begin(); compit != comps.end(); ++compit) {
184 QStringList &vars = project->variables()[(*compit) + ".variables"];
185 for(QStringList::Iterator varit = vars.begin(); varit != vars.end(); ++varit) {
186 QStringList vals = project->variables()[(*varit)];
187 if(!vals.isEmpty())
188 t << "QMAKE_COMP_" << (*varit) << " = " << valList(vals) << endl;
189 }
190 }
191 }
192
193 t << "DIST = " << varList("DISTFILES") << endl;
194 t << "TARGET = ";
195 if( !project->variables()[ "DESTDIR" ].isEmpty() )
196 t << varGlue("TARGET",project->first("DESTDIR"),"",project->first("TARGET_EXT"));
197 else
198 t << project->variables()[ "TARGET" ].first() << project->variables()[ "TARGET_EXT" ].first();
199 t << endl;
200 t << endl;
201
202 t << "####### Implicit rules" << endl << endl;
203 t << ".SUFFIXES: .c";
204 QStringList::Iterator cppit;
205 for(cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit)
206 t << " " << (*cppit);
207 t << endl << endl;
208
209 if(!project->isActiveConfig("no_batch")) {
210 // Batchmode doesn't use the non implicit rules QMAKE_RUN_CXX & QMAKE_RUN_CC
211 project->variables().remove("QMAKE_RUN_CXX");
212 project->variables().remove("QMAKE_RUN_CC");
213
214 QDict<void> source_directories;
215 source_directories.insert(".", (void*)1);
216 QString directories[] = { QString("MOC_DIR"), QString("UI_SOURCES_DIR"), QString("UI_DIR"), QString::null };
217 for(int y = 0; !directories[y].isNull(); y++) {
218 QString dirTemp = project->first(directories[y]);
219 if (dirTemp.endsWith("\\"))
220 dirTemp.truncate(dirTemp.length()-1);
221 if(!dirTemp.isEmpty())
222 source_directories.insert(dirTemp, (void*)1);
223 }
224 QString srcs[] = { QString("SOURCES"), QString("UICIMPLS"), QString("SRCMOC"), QString::null };
225 for(int x = 0; !srcs[x].isNull(); x++) {
226 QStringList &l = project->variables()[srcs[x]];
227 for(QStringList::Iterator sit = l.begin(); sit != l.end(); ++sit) {
228 QString sep = "\\";
229 if((*sit).find(sep) == -1)
230 sep = "/";
231 QString dir = (*sit).section(sep, 0, -2);
232 if(!dir.isEmpty() && !source_directories[dir])
233 source_directories.insert(dir, (void*)1);
234 }
235 }
236
237 for(QDictIterator<void> it(source_directories); it.current(); ++it) {
238 if(it.currentKey().isEmpty())
239 continue;
240 for(cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit)
241 t << "{" << it.currentKey() << "}" << (*cppit) << "{" << var("OBJECTS_DIR") << "}" << Option::obj_ext << "::\n\t"
242 << var("QMAKE_RUN_CXX_IMP_BATCH").replace( QRegExp( "\\$@" ), var("OBJECTS_DIR") ) << endl << "\t$<" << endl << "<<" << endl << endl;
243 t << "{" << it.currentKey() << "}" << ".c{" << var("OBJECTS_DIR") << "}" << Option::obj_ext << "::\n\t"
244 << var("QMAKE_RUN_CC_IMP_BATCH").replace( QRegExp( "\\$@" ), var("OBJECTS_DIR") ) << endl << "\t$<" << endl << "<<" << endl << endl;
245 }
246 } else {
247 for(cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit)
248 t << (*cppit) << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CXX_IMP") << endl << endl;
249 t << ".c" << Option::obj_ext << ":\n\t" << var("QMAKE_RUN_CC_IMP") << endl << endl;
250 }
251
252 t << "####### Build rules" << endl << endl;
253 t << "all: " << fileFixify(Option::output.name()) << " " << varGlue("ALL_DEPS"," "," "," ") << "$(TARGET)" << endl << endl;
254 t << "$(TARGET): " << var("PRE_TARGETDEPS") << " $(UICDECLS) $(OBJECTS) $(OBJMOC) "
255 << extraCompilerDeps << var("POST_TARGETDEPS");
256 if(!project->variables()["QMAKE_APP_OR_DLL"].isEmpty()) {
257 t << "\n\t" << "$(LINK) $(LFLAGS) /OUT:$(TARGET) @<< " << "\n\t "
258 << "$(OBJECTS) $(OBJMOC) $(LIBS)";
259 } else {
260 t << "\n\t" << "$(LIB) /OUT:$(TARGET) @<<" << "\n\t "
261 << "$(OBJECTS) $(OBJMOC)";
262 }
263 t << extraCompilerDeps;
264 t << endl << "<<" << endl;
265 if ( !project->variables()["QMAKE_POST_LINK"].isEmpty() )
266 t << "\t" << var( "QMAKE_POST_LINK" ) << endl;
267 if(project->isActiveConfig("dll") && !project->variables()["DLLDESTDIR"].isEmpty()) {
268 QStringList dlldirs = project->variables()["DLLDESTDIR"];
269 for ( QStringList::Iterator dlldir = dlldirs.begin(); dlldir != dlldirs.end(); ++dlldir ) {
270 t << "\n\t" << "-$(COPY_FILE) \"$(TARGET)\" " << *dlldir;
271 }
272 }
273 QString targetfilename = project->variables()["TARGET"].first();
274 if(project->isActiveConfig("activeqt")) {
275 QString version = project->variables()["VERSION"].first();
276 if ( version.isEmpty() )
277 version = "1.0";
278
279 if ( project->isActiveConfig("dll")) {
280 t << "\n\t" << ("-$(IDC) $(TARGET) /idl " + var("OBJECTS_DIR") + targetfilename + ".idl -version " + version);
281 t << "\n\t" << ("-$(IDL) /nologo " + var("OBJECTS_DIR") + targetfilename + ".idl /tlb " + var("OBJECTS_DIR") + targetfilename + ".tlb");
282 t << "\n\t" << ("-$(IDC) $(TARGET) /tlb " + var("OBJECTS_DIR") + targetfilename + ".tlb");
283 t << "\n\t" << ("-$(IDC) $(TARGET) /regserver" );
284 } else {
285 t << "\n\t" << ("-$(TARGET) -dumpidl " + var("OBJECTS_DIR") + targetfilename + ".idl -version " + version);
286 t << "\n\t" << ("-$(IDL) /nologo " + var("OBJECTS_DIR") + targetfilename + ".idl /tlb " + var("OBJECTS_DIR") + targetfilename + ".tlb");
287 t << "\n\t" << ("-$(IDC) $(TARGET) /tlb " + var("OBJECTS_DIR") + targetfilename + ".tlb");
288 t << "\n\t" << "-$(TARGET) -regserver";
289 }
290 }
291 t << endl << endl;
292
293 if(!project->variables()["RC_FILE"].isEmpty()) {
294 t << var("RES_FILE") << ": " << var("RC_FILE") << "\n\t"
295 << var("QMAKE_RC") << " " << var("RC_FILE") << endl << endl;
296 }
297
298 t << "mocables: $(SRCMOC)" << endl
299 << "uicables: $(UICIMPLS) $(UICDECLS)" << endl << endl;
300
301 writeMakeQmake(t);
302
303 QStringList dist_files = Option::mkfile::project_files;
304 if(!project->isEmpty("QMAKE_INTERNAL_INCLUDED_FILES"))
305 dist_files += project->variables()["QMAKE_INTERNAL_INCLUDED_FILES"];
306 if(!project->isEmpty("TRANSLATIONS"))
307 dist_files << var("TRANSLATIONS");
308 if(!project->isEmpty("FORMS")) {
309 QStringList &forms = project->variables()["FORMS"];
310 for(QStringList::Iterator formit = forms.begin(); formit != forms.end(); ++formit) {
311 QString ui_h = fileFixify((*formit) + Option::h_ext.first());
312 if(QFile::exists(ui_h) )
313 dist_files << ui_h;
314 }
315 }
316 t << "dist:" << "\n\t"
317 << "$(ZIP) " << var("QMAKE_ORIG_TARGET") << ".zip " << "$(SOURCES) $(HEADERS) $(DIST) $(FORMS) "
318 << dist_files.join(" ") << " " << var("TRANSLATIONS") << " " << var("IMAGES") << endl << endl;
319
320 t << "uiclean:"
321 << varGlue("UICDECLS" ,"\n\t-$(DEL_FILE) ","\n\t-$(DEL_FILE) ","")
322 << varGlue("UICIMPLS" ,"\n\t-$(DEL_FILE) ","\n\t-$(DEL_FILE) ","") << endl;
323
324 t << "mocclean:"
325 << varGlue("SRCMOC" ,"\n\t-$(DEL_FILE) ","\n\t-$(DEL_FILE) ","")
326 << varGlue("OBJMOC" ,"\n\t-$(DEL_FILE) ","\n\t-$(DEL_FILE) ","") << endl;
327
328 t << "clean: uiclean mocclean"
329 << varGlue("OBJECTS","\n\t-$(DEL_FILE) ","\n\t-$(DEL_FILE) ","")
330 << varGlue("QMAKE_CLEAN","\n\t-$(DEL_FILE) ","\n\t-$(DEL_FILE) ","\n")
331 << varGlue("CLEAN_FILES","\n\t-$(DEL_FILE) ","\n\t-$(DEL_FILE) ","\n");
332 if ( project->isActiveConfig("activeqt")) {
333 t << ("\n\t-$(DEL_FILE) " + var("OBJECTS_DIR") + targetfilename + ".idl");
334 t << ("\n\t-$(DEL_FILE) " + var("OBJECTS_DIR") + targetfilename + ".tlb");
335 }
336 if(!project->isEmpty("IMAGES"))
337 t << varGlue("QMAKE_IMAGE_COLLECTION", "\n\t-$(DEL_FILE) ", "\n\t-$(DEL_FILE) ", "");
338 t << endl;
339
340 // user defined targets
341
342 QStringList::Iterator it;
343 QStringList &qut = project->variables()["QMAKE_EXTRA_WIN_TARGETS"];
344 for(it = qut.begin(); it != qut.end(); ++it) {
345 QString targ = var((*it) + ".target"),
346 cmd = var((*it) + ".commands"), deps;
347 if(targ.isEmpty())
348 targ = (*it);
349 QStringList &deplist = project->variables()[(*it) + ".depends"];
350 for(QStringList::Iterator dep_it = deplist.begin(); dep_it != deplist.end(); ++dep_it) {
351 QString dep = var((*dep_it) + ".target");
352 if(dep.isEmpty())
353 dep = (*dep_it);
354 deps += " " + dep;
355 }
356 if(!project->variables()["QMAKE_NOFORCE"].isEmpty() &&
357 project->variables()[(*it) + ".CONFIG"].findIndex("phony") != -1)
358 deps += QString(" ") + "FORCE";
359 t << "\n\n" << targ << ":" << deps << "\n\t"
360 << cmd;
361 }
362 t << endl << endl;
363
364 QStringList &quc = project->variables()["QMAKE_EXTRA_WIN_COMPILERS"];
365 for(it = quc.begin(); it != quc.end(); ++it) {
366 QString tmp_out = project->variables()[(*it) + ".output"].first();
367 QString tmp_cmd = project->variables()[(*it) + ".commands"].join(" ");
368 QString tmp_dep = project->variables()[(*it) + ".depends"].join(" ");
369 QStringList &vars = project->variables()[(*it) + ".variables"];
370 if(tmp_out.isEmpty() || tmp_cmd.isEmpty())
371 continue;
372 QStringList &tmp = project->variables()[(*it) + ".input"];
373 for(QStringList::Iterator it2 = tmp.begin(); it2 != tmp.end(); ++it2) {
374 QStringList &inputs = project->variables()[(*it2)];
375 for(QStringList::Iterator input = inputs.begin(); input != inputs.end(); ++input) {
376 QFileInfo fi(Option::fixPathToLocalOS((*input)));
377 QString in = Option::fixPathToTargetOS((*input), FALSE),
378 out = tmp_out, cmd = tmp_cmd, deps;
379 out.replace("${QMAKE_FILE_BASE}", fi.baseName());
380 out.replace("${QMAKE_FILE_NAME}", fi.filePath());
381 cmd.replace("${QMAKE_FILE_BASE}", fi.baseName());
382 cmd.replace("${QMAKE_FILE_OUT}", out);
383 cmd.replace("${QMAKE_FILE_NAME}", fi.filePath());
384 for(QStringList::Iterator it3 = vars.begin(); it3 != vars.end(); ++it3)
385 cmd.replace("$(" + (*it3) + ")", "$(QMAKE_COMP_" + (*it3)+")");
386 if(!tmp_dep.isEmpty()) {
387 char buff[256];
388 QString dep_cmd = tmp_dep;
389 dep_cmd.replace("${QMAKE_FILE_NAME}", fi.filePath());
390 if(FILE *proc = QT_POPEN(dep_cmd.latin1(), "r")) {
391 while(!feof(proc)) {
392 int read_in = int(fread(buff, 1, 255, proc));
393 if(!read_in)
394 break;
395 int l = 0;
396 for(int i = 0; i < read_in; i++) {
397 if(buff[i] == '\n' || buff[i] == ' ') {
398 deps += " " + QCString(buff+l, (i - l) + 1);
399 l = i;
400 }
401 }
402 }
403 fclose(proc);
404 }
405 }
406 t << out << ": " << in << deps << "\n\t"
407 << cmd << endl << endl;
408 }
409 }
410 }
411 t << endl;
412
413 if(project->variables()["QMAKE_NOFORCE"].isEmpty())
414 t << "FORCE:" << endl << endl;
415
416 t << "distclean: clean"
417 << "\n\t-$(DEL_FILE) $(TARGET)"
418 << endl << endl;
419
420 // precompiled header
421 if(usePCH) {
422 QString precompRule = QString("-c -Yc -Fp%1 -Fo%2").arg(precompPch).arg(precompObj);
423 t << precompObj << ": " << precompH << " " << findDependencies(precompH).join(" \\\n\t\t")
424 << "\n\t" << ("$(CXX) " + precompRule + " $(CXXFLAGS) $(INCPATH) -TP ") << precompH << endl << endl;
425 }
426 }
427
428 QString
var(const QString & value)429 NmakeMakefileGenerator::var(const QString &value)
430 {
431 if (usePCH) {
432 if ((value == "QMAKE_RUN_CXX_IMP_BATCH"
433 || value == "QMAKE_RUN_CXX_IMP"
434 || value == "QMAKE_RUN_CXX")) {
435 QFileInfo precompHInfo(precompH);
436 QString precompRule = QString("-c -FI%1 -Yu%2 -Fp%3")
437 .arg(precompHInfo.fileName())
438 .arg(precompHInfo.fileName())
439 .arg(precompPch);
440 QString p = MakefileGenerator::var(value);
441 p.replace("-c", precompRule);
442 // Cannot use -Gm with -FI & -Yu, as this gives an
443 // internal compiler error, on the newer compilers
444 p.remove("-Gm");
445 return p;
446 } else if (value == "QMAKE_CXXFLAGS") {
447 // Remove internal compiler error option
448 return MakefileGenerator::var(value).remove("-Gm");
449 }
450 }
451
452 // Normal val
453 return MakefileGenerator::var(value);
454 }
455
456 void
init()457 NmakeMakefileGenerator::init()
458 {
459 if(init_flag)
460 return;
461 init_flag = TRUE;
462
463 /* this should probably not be here, but I'm using it to wrap the .t files */
464 if(project->first("TEMPLATE") == "app")
465 project->variables()["QMAKE_APP_FLAG"].append("1");
466 else if(project->first("TEMPLATE") == "lib")
467 project->variables()["QMAKE_LIB_FLAG"].append("1");
468 else if(project->first("TEMPLATE") == "subdirs") {
469 MakefileGenerator::init();
470 if(project->variables()["MAKEFILE"].isEmpty())
471 project->variables()["MAKEFILE"].append("Makefile");
472 if(project->variables()["QMAKE"].isEmpty())
473 project->variables()["QMAKE"].append("qmake");
474 return;
475 }
476
477 if(project->isEmpty("QMAKE_INSTALL_FILE"))
478 project->variables()["QMAKE_INSTALL_FILE"].append("$(COPY_FILE)");
479 if(project->isEmpty("QMAKE_INSTALL_DIR"))
480 project->variables()["QMAKE_INSTALL_DIR"].append("$(COPY_DIR)");
481
482 bool is_qt = (project->first("TARGET") == "qt" QTDLL_POSTFIX || project->first("TARGET") == "qt-mt" QTDLL_POSTFIX);
483 project->variables()["QMAKE_ORIG_TARGET"] = project->variables()["TARGET"];
484
485 QString targetfilename = project->variables()["TARGET"].first();
486 QStringList &configs = project->variables()["CONFIG"];
487 if (project->isActiveConfig("qt") && project->isActiveConfig("shared"))
488 project->variables()["DEFINES"].append("QT_DLL");
489 if (project->isActiveConfig("qt_dll"))
490 if(configs.findIndex("qt") == -1) configs.append("qt");
491 if ( project->isActiveConfig("qtopia") ) {
492 if(configs.findIndex("qtopialib") == -1)
493 configs.append("qtopialib");
494 if(configs.findIndex("qtopiainc") == -1)
495 configs.append("qtopiainc");
496 }
497 if ( project->isActiveConfig("qt") ) {
498 if ( project->isActiveConfig( "plugin" ) ) {
499 project->variables()["CONFIG"].append("dll");
500 if(project->isActiveConfig("qt"))
501 project->variables()["DEFINES"].append("QT_PLUGIN");
502 }
503 if ( (project->variables()["DEFINES"].findIndex("QT_NODLL") == -1) &&
504 ((project->variables()["DEFINES"].findIndex("QT_MAKEDLL") != -1 ||
505 project->variables()["DEFINES"].findIndex("QT_DLL") != -1) ||
506 (getenv("QT_DLL") && !getenv("QT_NODLL"))) ) {
507 project->variables()["QMAKE_QT_DLL"].append("1");
508 if ( is_qt && !project->variables()["QMAKE_LIB_FLAG"].isEmpty() )
509 project->variables()["CONFIG"].append("dll");
510 }
511 if ( project->isActiveConfig("thread") )
512 project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_THREAD_SUPPORT");
513 if ( project->isActiveConfig("accessibility" ) )
514 project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_ACCESSIBILITY_SUPPORT");
515 if ( project->isActiveConfig("tablet") )
516 project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_TABLET_SUPPORT");
517 }
518 if ( project->isActiveConfig("dll") || !project->variables()["QMAKE_APP_FLAG"].isEmpty() ) {
519 project->variables()["CONFIG"].remove("staticlib");
520 project->variables()["QMAKE_APP_OR_DLL"].append("1");
521 } else {
522 project->variables()["CONFIG"].append("staticlib");
523 }
524 if ( project->isActiveConfig("warn_off") ) {
525 project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_WARN_OFF"];
526 project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_WARN_OFF"];
527 } else if ( project->isActiveConfig("warn_on") ) {
528 project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_WARN_ON"];
529 project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_WARN_ON"];
530 }
531 if ( project->isActiveConfig("debug") ) {
532 if ( project->isActiveConfig("thread") ) {
533 // use the DLL RT even here
534 if ( project->variables()["DEFINES"].contains("QT_DLL") ) {
535 project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT_DLLDBG"];
536 project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT_DLLDBG"];
537 } else {
538 project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT_DBG"];
539 project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT_DBG"];
540 }
541 }
542 project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_DEBUG"];
543 project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_DEBUG"];
544 project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_DEBUG"];
545 } else {
546 if ( project->isActiveConfig("thread") ) {
547 if ( project->variables()["DEFINES"].contains("QT_DLL") ) {
548 project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT_DLL"];
549 project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT_DLL"];
550 } else {
551 project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_MT"];
552 project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_MT"];
553 }
554 }
555 project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_RELEASE"];
556 project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_RELEASE"];
557 project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_RELEASE"];
558 }
559 if ( project->isActiveConfig("thread") && !project->variables()["DEFINES"].contains("QT_DLL")
560 && !is_qt && project->first("TARGET") != "qtmain") {
561 project->variables()["QMAKE_LFLAGS"].append("/NODEFAULTLIB:\"libc\"");
562 }
563
564 if ( !project->variables()["QMAKE_INCDIR"].isEmpty())
565 project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR"];
566 if ( project->isActiveConfig("qt") || project->isActiveConfig("opengl") )
567 project->variables()["CONFIG"].append("windows");
568 if ( project->isActiveConfig("qtopiainc") )
569 project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_QTOPIA"];
570 if ( project->isActiveConfig("qtopialib") ) {
571 if(!project->isEmpty("QMAKE_LIBDIR_QTOPIA"))
572 project->variables()["QMAKE_LIBDIR"] += project->variables()["QMAKE_LIBDIR_QTOPIA"];
573 project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QTOPIA"];
574 }
575 if ( project->isActiveConfig("qt") ) {
576 project->variables()["CONFIG"].append("moc");
577 project->variables()["INCLUDEPATH"] += project->variables()["QMAKE_INCDIR_QT"];
578 project->variables()["QMAKE_LIBDIR"] += project->variables()["QMAKE_LIBDIR_QT"];
579 if ( !project->isActiveConfig("debug") )
580 project->variables()[is_qt ? "PRL_EXPORT_DEFINES" : "DEFINES"].append("QT_NO_DEBUG");
581 if ( is_qt && !project->variables()["QMAKE_LIB_FLAG"].isEmpty() ) {
582 if ( !project->variables()["QMAKE_QT_DLL"].isEmpty()) {
583 project->variables()["DEFINES"].append("QT_MAKEDLL");
584 project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_QT_DLL"];
585 }
586 } else {
587 if(project->isActiveConfig("thread"))
588 project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_THREAD"];
589 else
590 project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT"];
591 if ( !project->variables()["QMAKE_QT_DLL"].isEmpty() ) {
592 int hver = findHighestVersion(project->first("QMAKE_LIBDIR_QT"), "qt");
593 if ( hver == -1 )
594 hver = findHighestVersion(project->first("QMAKE_LIBDIR_QT"), "qt-mt");
595 if(hver != -1) {
596 QString ver;
597 ver.sprintf("qt%s" QTDLL_POSTFIX "%d.lib", (project->isActiveConfig("thread") ? "-mt" : ""), hver);
598 QStringList &libs = project->variables()["QMAKE_LIBS"];
599 for(QStringList::Iterator libit = libs.begin(); libit != libs.end(); ++libit)
600 (*libit).replace(QRegExp("qt(-mt)?\\.lib"), ver);
601 }
602 }
603 if ( project->isActiveConfig( "activeqt" ) ) {
604 project->variables().remove("QMAKE_LIBS_QT_ENTRY");
605 project->variables()["QMAKE_LIBS_QT_ENTRY"] = "qaxserver.lib";
606 if ( project->isActiveConfig( "dll" ) )
607 project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_QT_ENTRY"];
608 }
609 if ( !project->isActiveConfig("dll") && !project->isActiveConfig("plugin") ) {
610 project->variables()["QMAKE_LIBS"] +=project->variables()["QMAKE_LIBS_QT_ENTRY"];
611 }
612 }
613 }
614 if ( project->isActiveConfig("opengl") ) {
615 project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_OPENGL"];
616 project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_OPENGL"];
617 }
618 if ( project->isActiveConfig("dll") ) {
619 project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CFLAGS_CONSOLE_DLL"];
620 project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CXXFLAGS_CONSOLE_DLL"];
621 project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_LFLAGS_CONSOLE_DLL"];
622 project->variables()["QMAKE_LFLAGS_WINDOWS_ANY"] = project->variables()["QMAKE_LFLAGS_WINDOWS_DLL"];
623 if ( !project->variables()["QMAKE_LIB_FLAG"].isEmpty()) {
624 project->variables()["TARGET_EXT"].append(
625 QStringList::split('.',project->first("VERSION")).join("") + ".dll");
626 } else {
627 project->variables()["TARGET_EXT"].append(".dll");
628 }
629 } else {
630 project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CFLAGS_CONSOLE"];
631 project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_CXXFLAGS_CONSOLE"];
632 project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"] = project->variables()["QMAKE_LFLAGS_CONSOLE"];
633 project->variables()["QMAKE_LFLAGS_WINDOWS_ANY"] = project->variables()["QMAKE_LFLAGS_WINDOWS"];
634 if ( !project->variables()["QMAKE_APP_FLAG"].isEmpty()) {
635 project->variables()["TARGET_EXT"].append(".exe");
636 } else {
637 project->variables()["TARGET_EXT"].append(".lib");
638 }
639 }
640 if ( project->isActiveConfig("windows") ) {
641 if ( project->isActiveConfig("console") ) {
642 project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"];
643 project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"];
644 project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"];
645 project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_CONSOLE"];
646 } else {
647 project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_WINDOWS_ANY"];
648 }
649 project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_WINDOWS"];
650 } else {
651 project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_CONSOLE_ANY"];
652 project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_CONSOLE_ANY"];
653 project->variables()["QMAKE_LFLAGS"] += project->variables()["QMAKE_LFLAGS_CONSOLE_ANY"];
654 project->variables()["QMAKE_LIBS"] += project->variables()["QMAKE_LIBS_CONSOLE"];
655 }
656 if ( project->isActiveConfig("stl") ) {
657 project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_STL_ON"];
658 project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_STL_ON"];
659 } else {
660 project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_STL_OFF"];
661 project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_STL_OFF"];
662 }
663 if ( project->isActiveConfig("exceptions") ) {
664 project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_EXCEPTIONS_ON"];
665 project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_EXCEPTIONS_ON"];
666 } else {
667 project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_EXCEPTIONS_OFF"];
668 project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_EXCEPTIONS_OFF"];
669 }
670 if ( project->isActiveConfig("rtti") ) {
671 project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_RTTI_ON"];
672 project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_RTTI_ON"];
673 } else {
674 project->variables()["QMAKE_CFLAGS"] += project->variables()["QMAKE_CFLAGS_RTTI_OFF"];
675 project->variables()["QMAKE_CXXFLAGS"] += project->variables()["QMAKE_CXXFLAGS_RTTI_OFF"];
676 }
677
678
679 if ( project->isActiveConfig("moc") )
680 setMocAware(TRUE);
681 project->variables()["QMAKE_LIBS"] += project->variables()["LIBS"];
682
683 QStringList &libList = project->variables()["QMAKE_LIBS"];
684 for( QStringList::Iterator stIt = libList.begin(); stIt != libList.end(); ) {
685 QString s = *stIt;
686 if( s.startsWith( "-l" ) ) {
687 stIt = libList.remove( stIt );
688 stIt = libList.insert( stIt, s.mid( 2 ) + ".lib" );
689 } else if( s.startsWith( "-L" ) ) {
690 stIt = libList.remove( stIt );
691 project->variables()["QMAKE_LIBDIR"].append(QDir::convertSeparators(s.mid( 2 )));
692 } else {
693 stIt++;
694 }
695 }
696
697 project->variables()["QMAKE_FILETAGS"] += QStringList::split(' ',
698 "HEADERS SOURCES DEF_FILE RC_FILE TARGET QMAKE_LIBS DESTDIR DLLDESTDIR INCLUDEPATH");
699 QStringList &l = project->variables()["QMAKE_FILETAGS"];
700 QStringList::Iterator it;
701 for(it = l.begin(); it != l.end(); ++it) {
702 QStringList &gdmf = project->variables()[(*it)];
703 for(QStringList::Iterator inner = gdmf.begin(); inner != gdmf.end(); ++inner)
704 (*inner) = Option::fixPathToTargetOS((*inner), FALSE);
705 }
706
707 if ( !project->variables()["DEF_FILE"].isEmpty() )
708 project->variables()["QMAKE_LFLAGS"].append(QString("/DEF:") + project->first("DEF_FILE"));
709 if(!project->isActiveConfig("incremental"))
710 project->variables()["QMAKE_LFLAGS"].append(QString("/incremental:no"));
711
712 if ( !project->variables()["VERSION"].isEmpty() ) {
713 QString version = project->variables()["VERSION"][0];
714 int firstDot = version.find( "." );
715 QString major = version.left( firstDot );
716 QString minor = version.right( version.length() - firstDot - 1 );
717 minor.replace( ".", "" );
718 project->variables()["QMAKE_LFLAGS"].append( "/VERSION:" + major + "." + minor );
719 }
720 if ( !project->variables()["RC_FILE"].isEmpty()) {
721 if ( !project->variables()["RES_FILE"].isEmpty()) {
722 fprintf(stderr, "Both .rc and .res file specified.\n");
723 fprintf(stderr, "Please specify one of them, not both.");
724 exit(666);
725 }
726 project->variables()["RES_FILE"] = project->variables()["RC_FILE"];
727 project->variables()["RES_FILE"].first().replace(".rc",".res");
728 project->variables()["POST_TARGETDEPS"] += project->variables()["RES_FILE"];
729 project->variables()["CLEAN_FILES"] += project->variables()["RES_FILE"];
730 }
731 if ( !project->variables()["RES_FILE"].isEmpty())
732 project->variables()["QMAKE_LIBS"] += project->variables()["RES_FILE"];
733
734 // Base class init!
735 MakefileGenerator::init();
736
737 // Setup PCH variables
738 precompH = project->first("PRECOMPILED_HEADER");
739 usePCH = !precompH.isEmpty() && project->isActiveConfig("precompile_header");
740 if (usePCH) {
741 // Created files
742 precompObj = var("OBJECTS_DIR") + project->first("TARGET") + "_pch" + Option::obj_ext;
743 precompPch = var("OBJECTS_DIR") + project->first("TARGET") + "_pch.pch";
744 // Add linking of precompObj (required for whole precompiled classes)
745 project->variables()["OBJECTS"] += precompObj;
746 // Add pch file to cleanup
747 project->variables()["QMAKE_CLEAN"] += precompPch;
748 // Return to variable pool
749 project->variables()["PRECOMPILED_OBJECT"] = precompObj;
750 project->variables()["PRECOMPILED_PCH"] = precompPch;
751 }
752
753 if ( !project->variables()["VERSION"].isEmpty()) {
754 QStringList l = QStringList::split('.', project->first("VERSION"));
755 project->variables()["VER_MAJ"].append(l[0]);
756 project->variables()["VER_MIN"].append(l[1]);
757 }
758
759 QString version = QStringList::split('.', project->first("VERSION")).join("");
760 if(project->isActiveConfig("dll")) {
761 project->variables()["QMAKE_CLEAN"].append(project->first("DESTDIR") + project->first("TARGET") + version + ".exp");
762 }
763 if(project->isActiveConfig("debug")) {
764 project->variables()["QMAKE_CLEAN"].append(project->first("DESTDIR") + project->first("TARGET") + version + ".pdb");
765 project->variables()["QMAKE_CLEAN"].append(project->first("DESTDIR") + project->first("TARGET") + version + ".ilk");
766 project->variables()["QMAKE_CLEAN"].append("vc*.pdb");
767 project->variables()["QMAKE_CLEAN"].append("vc*.idb");
768 }
769
770 QStringList &quc = project->variables()["QMAKE_EXTRA_WIN_COMPILERS"];
771 for(it = quc.begin(); it != quc.end(); ++it) {
772 QString tmp_out = project->variables()[(*it) + ".output"].first();
773 if(tmp_out.isEmpty())
774 continue;
775 QStringList &tmp = project->variables()[(*it) + ".input"];
776 for(QStringList::Iterator it2 = tmp.begin(); it2 != tmp.end(); ++it2) {
777 QStringList &inputs = project->variables()[(*it2)];
778 for(QStringList::Iterator input = inputs.begin(); input != inputs.end(); ++input) {
779 QFileInfo fi(Option::fixPathToLocalOS((*input)));
780 QString in = Option::fixPathToTargetOS((*input), FALSE),
781 out = tmp_out;
782 out.replace("${QMAKE_FILE_BASE}", fi.baseName());
783 out.replace("${QMAKE_FILE_NAME}", fi.filePath());
784 if(project->variables()[(*it) + ".CONFIG"].findIndex("no_link") == -1)
785 project->variables()["OBJCOMP"] += out;
786 }
787 }
788 }
789 }
790