summaryrefslogtreecommitdiff
path: root/qmake/generators/win32/winmakefile.cpp
Unidiff
Diffstat (limited to 'qmake/generators/win32/winmakefile.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--qmake/generators/win32/winmakefile.cpp360
1 files changed, 360 insertions, 0 deletions
diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp
new file mode 100644
index 0000000..a07c921
--- a/dev/null
+++ b/qmake/generators/win32/winmakefile.cpp
@@ -0,0 +1,360 @@
1/****************************************************************************
2** $Id$
3**
4** Definition of ________ class.
5**
6** Created : 970521
7**
8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
9**
10** This file is part of the network module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition licenses may use this
22** file in accordance with the Qt Commercial License Agreement provided
23** with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "winmakefile.h"
39#include "option.h"
40#include "project.h"
41#include <qtextstream.h>
42#include <qstring.h>
43#include <qdict.h>
44#include <qregexp.h>
45#include <qstringlist.h>
46#include <qdir.h>
47
48
49Win32MakefileGenerator::Win32MakefileGenerator(QMakeProject *p) : MakefileGenerator(p)
50{
51
52}
53
54
55struct SubDir
56{
57 QString directory, profile, target, makefile;
58};
59
60void
61Win32MakefileGenerator::writeSubDirs(QTextStream &t)
62{
63 QPtrList<SubDir> subdirs;
64 {
65 QStringList subdirs_in = project->variables()["SUBDIRS"];
66 for(QStringList::Iterator it = subdirs_in.begin(); it != subdirs_in.end(); ++it) {
67 QString file = (*it);
68 file = fileFixify(file);
69 SubDir *sd = new SubDir;
70 subdirs.append(sd);
71 sd->makefile = "$(MAKEFILE)";
72 if((*it).right(4) == ".pro") {
73 int slsh = file.findRev(Option::dir_sep);
74 if(slsh != -1) {
75 sd->directory = file.left(slsh+1);
76 sd->profile = file.mid(slsh+1);
77 } else {
78 sd->profile = file;
79 }
80 } else {
81 sd->directory = file;
82 }
83 while(sd->directory.right(1) == Option::dir_sep)
84 sd->directory = sd->directory.left(sd->directory.length() - 1);
85 if(!sd->profile.isEmpty()) {
86 QString basename = sd->directory;
87 int new_slsh = basename.findRev(Option::dir_sep);
88 if(new_slsh != -1)
89 basename = basename.mid(new_slsh+1);
90 if(sd->profile != basename + ".pro")
91 sd->makefile += "." + sd->profile.left(sd->profile.length() - 4); //no need for the .pro
92 }
93 sd->target = "sub-" + (*it);
94 sd->target.replace('/', '-');
95 sd->target.replace('.', '_');
96 }
97 }
98 QPtrListIterator<SubDir> it(subdirs);
99
100 if(!project->isEmpty("MAKEFILE"))
101 t << "MAKEFILE=" << var("MAKEFILE") << endl;
102 t << "QMAKE =" << (project->isEmpty("QMAKE_QMAKE") ? QString("qmake") : var("QMAKE_QMAKE")) << endl;
103 t << "SUBTARGETS= ";
104 for( it.toFirst(); it.current(); ++it)
105 t << " \\\n\t\t" << it.current()->target;
106 t << endl << endl;
107 t << "all: qmake_all $(SUBTARGETS)" << endl << endl;
108
109 for( it.toFirst(); it.current(); ++it) {
110 bool have_dir = !(*it)->directory.isEmpty();
111
112 //make the makefile
113 QString mkfile = (*it)->makefile;
114 if(have_dir)
115 mkfile.prepend((*it)->directory + Option::dir_sep);
116 t << mkfile << ":";
117 if(project->variables()["QMAKE_NOFORCE"].isEmpty())
118 t << " FORCE";
119 if(have_dir)
120 t << "\n\t" << "cd " << (*it)->directory;
121 t << "\n\t" << "$(QMAKE) " << (*it)->profile << " " << buildArgs();
122 if((*it)->makefile != "$(MAKEFILE)")
123 t << " -o " << (*it)->makefile;
124 if(have_dir) {
125 int subLevels = it.current()->directory.contains(Option::dir_sep) + 1;
126 t << "\n\t" << "@cd ..";
127 for(int i = 1; i < subLevels; i++ )
128 t << Option::dir_sep << "..";
129 }
130 t << endl;
131
132 //now actually build
133 t << (*it)->target << ": " << mkfile;
134 if(project->variables()["QMAKE_NOFORCE"].isEmpty())
135 t << " FORCE";
136 if(have_dir)
137 t << "\n\t" << "cd " << (*it)->directory;
138 t << "\n\t" << "$(MAKE)";
139 if((*it)->makefile != "$(MAKEFILE)")
140 t << " -f " << (*it)->makefile;
141 if(have_dir) {
142 int subLevels = it.current()->directory.contains(Option::dir_sep) + 1;
143 t << "\n\t" << "@cd ..";
144 for(int i = 1; i < subLevels; i++ )
145 t << Option::dir_sep << "..";
146 }
147 t << endl << endl;
148 }
149
150 if(project->variables()["QMAKE_INTERNAL_QMAKE_DEPS"].findIndex("qmake_all") == -1)
151 project->variables()["QMAKE_INTERNAL_QMAKE_DEPS"].append("qmake_all");
152 writeMakeQmake(t);
153
154 t << "qmake_all:";
155 if ( !subdirs.isEmpty() ) {
156 for( it.toFirst(); it.current(); ++it) {
157 QString subdir = (*it)->directory;
158 int subLevels = subdir.contains(Option::dir_sep) + 1;
159 t << "\n\t"
160 << "cd " << subdir << "\n\t";
161 int lastSlash = subdir.findRev(Option::dir_sep);
162 if(lastSlash != -1)
163 subdir = subdir.mid( lastSlash + 1 );
164 t << "$(QMAKE) " << subdir << ".pro"
165 << (!project->isEmpty("MAKEFILE") ? QString(" -o ") + var("MAKEFILE") : QString(""))
166 << " " << buildArgs() << "\n\t"
167 << "@cd ..";
168 for(int i = 1; i < subLevels; i++ )
169 t << Option::dir_sep << "..";
170 }
171 } else {
172 // Borland make does not like empty an empty command section, so insert
173 // a dummy command.
174 t << "\n\t" << "@cd .";
175 }
176 t << endl << endl;
177
178 QString targs[] = { QString("clean"), QString("install"), QString("mocclean"), QString::null };
179 for(int x = 0; targs[x] != QString::null; x++) {
180 t << targs[x] << ": qmake_all";
181 if(targs[x] == "clean")
182 t << varGlue("QMAKE_CLEAN","\n\t-del ","\n\t-del ", "");
183 if (!subdirs.isEmpty()) {
184 for( it.toFirst(); it.current(); ++it) {
185 int subLevels = (*it)->directory.contains(Option::dir_sep) + 1;
186 bool have_dir = !(*it)->directory.isEmpty();
187 if(have_dir)
188 t << "\n\t" << "cd " << (*it)->directory;
189 QString in_file;
190 if((*it)->makefile != "$(MAKEFILE)")
191 in_file = " -f " + (*it)->makefile;
192 t << "\n\t" << "$(MAKE) " << in_file << " " << targs[x];
193 if(have_dir) {
194 t << "\n\t" << "@cd ..";
195 for(int i = 1; i < subLevels; i++ )
196 t << Option::dir_sep << "..";
197 }
198 }
199 } else {
200 // Borland make does not like empty an empty command section, so
201 // insert a dummy command.
202 t << "\n\t" << "@cd .";
203 }
204 t << endl << endl;
205 }
206
207 if(project->variables()["QMAKE_NOFORCE"].isEmpty())
208 t << "FORCE:" << endl << endl;
209}
210
211
212int
213Win32MakefileGenerator::findHighestVersion(const QString &d, const
214 QString &stem)
215{
216 if(!QFile::exists(Option::fixPathToLocalOS(d)))
217 return -1;
218 if(!project->variables()["QMAKE_" + stem.upper() +
219 "_VERSION_OVERRIDE"].isEmpty())
220 return project->variables()["QMAKE_" + stem.upper() +
221 "_VERSION_OVERRIDE"].first().toInt();
222 QString bd = d;
223 fixEnvVariables(bd);
224 QDir dir(bd);
225 int biggest=-1;
226 QStringList entries = dir.entryList();
227 QRegExp regx( "(" + stem + "([0-9]*)).lib", FALSE );
228 for(QStringList::Iterator it = entries.begin(); it != entries.end();
229 ++it) {
230 if(regx.exactMatch((*it)))
231 biggest = QMAX(biggest, (regx.cap(1) == stem ||
232 regx.cap(2).isEmpty()) ? -1 : regx.cap(2).toInt());
233 }
234 return biggest;
235}
236
237
238bool
239Win32MakefileGenerator::findLibraries(const QString &where)
240{
241
242 QStringList &l = project->variables()[where];
243 QPtrList<MakefileDependDir> dirs;
244 dirs.setAutoDelete(TRUE);
245 for(QStringList::Iterator it = l.begin(); it != l.end(); ) {
246 QString opt = (*it);
247 bool remove = FALSE;
248 if(opt.startsWith("-L") || opt.startsWith("/L")) {
249 QString r = opt.right(opt.length() - 2), l = Option::fixPathToLocalOS(r);
250 dirs.append(new MakefileDependDir(r.replace("\"",""),
251 l.replace("\"","")));
252 remove = TRUE;
253 } else if(opt.startsWith("-l") || opt.startsWith("/l")) {
254 QString lib = opt.right(opt.length() - 2), out;
255 if(!lib.isEmpty()) {
256 for(MakefileDependDir *mdd = dirs.first(); mdd; mdd = dirs.next() ) {
257 int ver = findHighestVersion(mdd->local_dir, lib);
258 if(ver > 0)
259 lib += QString::number(ver);
260 lib += ".lib";
261 if(QFile::exists(mdd->local_dir + Option::dir_sep + lib)) {
262 out = mdd->real_dir + Option::dir_sep + lib;
263 break;
264 }
265 }
266 }
267 if(out.isEmpty())
268 remove = TRUE;
269 else
270 (*it) = out;
271 } else if(!QFile::exists(Option::fixPathToLocalOS(opt))) {
272 QString dir, file = opt;
273 int slsh = file.findRev(Option::dir_sep);
274 if(slsh != -1) {
275 dir = file.left(slsh+1);
276 file = file.right(file.length() - slsh - 1);
277 }
278 if ( !(project->variables()["QMAKE_QT_DLL"].isEmpty() && (file == "qt.lib" || file == "qt-mt.lib")) ) {
279 if(file.endsWith(".lib")) {
280 file = file.left(file.length() - 4);
281 if(!file.at(file.length()-1).isNumber()) {
282 int ver = findHighestVersion(dir, file);
283 if(ver != -1) {
284 file = QString(dir + file + "%1" + ".lib");
285 if(ver)
286 (*it) = file.arg(ver);
287 else
288 (*it) = file.arg("");
289 }
290 }
291 }
292 }
293 }
294 if(remove)
295 it = l.remove(it);
296 else
297 ++it;
298 }
299 return TRUE;
300}
301
302void
303Win32MakefileGenerator::processPrlFiles()
304{
305 QDict<void> processed;
306 QPtrList<MakefileDependDir> libdirs;
307 libdirs.setAutoDelete(TRUE);
308 {
309 QStringList &libpaths = project->variables()["QMAKE_LIBDIR"];
310 for(QStringList::Iterator libpathit = libpaths.begin(); libpathit != libpaths.end(); ++libpathit) {
311 QString r = (*libpathit), l = r;
312 fixEnvVariables(l);
313 libdirs.append(new MakefileDependDir(r.replace("\"",""),
314 l.replace("\"","")));
315 }
316 }
317 for(bool ret = FALSE; TRUE; ret = FALSE) {
318 //read in any prl files included..
319 QStringList l_out;
320 QString where = "QMAKE_LIBS";
321 if(!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS"))
322 where = project->first("QMAKE_INTERNAL_PRL_LIBS");
323 QStringList &l = project->variables()[where];
324 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
325 QString opt = (*it);
326 if(opt.left(1) == "/") {
327 if(opt.left(9) == "/LIBPATH:") {
328 QString r = opt.mid(9), l = r;
329 fixEnvVariables(l);
330 libdirs.append(new MakefileDependDir(r.replace("\"",""),
331 l.replace("\"","")));
332 }
333 } else {
334 if(!processed[opt]) {
335 if(processPrlFile(opt)) {
336 processed.insert(opt, (void*)1);
337 ret = TRUE;
338 } else {
339 for(MakefileDependDir *mdd = libdirs.first(); mdd; mdd = libdirs.next() ) {
340 QString prl = mdd->local_dir + Option::dir_sep + opt;
341 if(processed[prl]) {
342 break;
343 } else if(processPrlFile(prl)) {
344 processed.insert(prl, (void*)1);
345 ret = TRUE;
346 break;
347 }
348 }
349 }
350 }
351 }
352 if(!opt.isEmpty())
353 l_out.append(opt);
354 }
355 if(ret)
356 l = l_out;
357 else
358 break;
359 }
360}