Diffstat (limited to 'qmake/generators/win32/winmakefile.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | qmake/generators/win32/winmakefile.cpp | 360 |
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 | |||
49 | Win32MakefileGenerator::Win32MakefileGenerator(QMakeProject *p) : MakefileGenerator(p) | ||
50 | { | ||
51 | |||
52 | } | ||
53 | |||
54 | |||
55 | struct SubDir | ||
56 | { | ||
57 | QString directory, profile, target, makefile; | ||
58 | }; | ||
59 | |||
60 | void | ||
61 | Win32MakefileGenerator::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 | |||
212 | int | ||
213 | Win32MakefileGenerator::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 | |||
238 | bool | ||
239 | Win32MakefileGenerator::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 | |||
302 | void | ||
303 | Win32MakefileGenerator::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 | } | ||