summaryrefslogtreecommitdiff
path: root/qmake
Unidiff
Diffstat (limited to 'qmake') (more/less context) (ignore whitespace changes)
-rw-r--r--qmake/generators/makefile.cpp2085
-rw-r--r--qmake/generators/makefile.h173
-rw-r--r--qmake/generators/projectgenerator.cpp462
-rw-r--r--qmake/generators/projectgenerator.h61
-rw-r--r--qmake/include/qmake/qconfig.h1
-rw-r--r--qmake/include/qmake/qmodules.h1
6 files changed, 2783 insertions, 0 deletions
diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp
new file mode 100644
index 0000000..f490313
--- a/dev/null
+++ b/qmake/generators/makefile.cpp
@@ -0,0 +1,2085 @@
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 "makefile.h"
39#include "option.h"
40#include <qdir.h>
41#include <qfile.h>
42#include <qtextstream.h>
43#include <qregexp.h>
44#include <qdict.h>
45#if defined(Q_OS_UNIX)
46#include <unistd.h>
47#else
48#include <io.h>
49#endif
50#include <stdio.h>
51#include <stdlib.h>
52#include <time.h>
53#include <fcntl.h>
54#include <sys/types.h>
55#include <sys/stat.h>
56
57// Well, Windows doesn't have this, so here's the macro
58#ifndef S_ISDIR
59 #define S_ISDIR(m)(((m) & S_IFMT) == S_IFDIR)
60#endif
61
62static bool createDir(const QString& fullPath)
63{
64 QDir dirTmp;
65 bool ret = TRUE;
66 QString pathComponent, tmpPath;
67 QStringList hierarchy = QStringList::split(QString(Option::dir_sep), fullPath, TRUE);
68 for(QStringList::Iterator it = hierarchy.begin(); it != hierarchy.end(); ++it) {
69 pathComponent = *it + QDir::separator();
70 tmpPath += pathComponent;
71 if(!dirTmp.mkdir(tmpPath)) {
72 ret = FALSE;
73 // break;
74 }
75 }
76 return ret;
77}
78
79
80MakefileGenerator::MakefileGenerator(QMakeProject *p) : init_opath_already(FALSE),
81 init_already(FALSE), moc_aware(FALSE),
82 no_io(FALSE), project(p)
83{
84}
85
86static char *gimme_buffer(off_t s)
87{
88 static char *big_buffer = NULL;
89 static int big_buffer_size = 0;
90 if(!big_buffer || big_buffer_size < s)
91 big_buffer = (char *)realloc(big_buffer, s);
92 return big_buffer;
93}
94
95bool
96MakefileGenerator::generateMocList(QString fn_target)
97{
98 if(!findMocDestination(fn_target).isEmpty())
99 return TRUE;
100
101 QString fn_local = Option::fixPathToLocalOS(fileFixify(fn_target, QDir::currentDirPath(), Option::output_dir));
102
103 int file = open(fn_local.latin1(), O_RDONLY);
104 if(file == -1)
105 return FALSE;
106
107 struct stat fst;
108 if(fstat(file, &fst) || S_ISDIR(fst.st_mode))
109 return FALSE; //shouldn't happen
110 char *big_buffer = gimme_buffer(fst.st_size);
111
112 int total_size_read;
113 for(int have_read = total_size_read = 0;
114 (have_read = read(file, big_buffer + total_size_read,
115 fst.st_size - total_size_read));
116 total_size_read += have_read);
117 close(file);
118
119 bool ignore_qobject = FALSE;
120 int line_count = 1;
121 /* qmake ignore Q_OBJECT */
122#define COMP_LEN 8 //strlen("Q_OBJECT")
123#define OBJ_LEN 8 //strlen("Q_OBJECT")
124#define DIS_LEN 10 //strlen("Q_DISPATCH")
125 int x;
126 for(x = 0; x < (total_size_read-COMP_LEN); x++) {
127 if(*(big_buffer + x) == '/') {
128 x++;
129 if(total_size_read >= x) {
130 if(*(big_buffer + x) == '/') { //c++ style comment
131 for( ;x < total_size_read && *(big_buffer + x) != '\n'; x++);
132 line_count++;
133 } else if(*(big_buffer + x) == '*') { //c style comment
134 for( ;x < total_size_read; x++) {
135 if(*(big_buffer + x) == 't' || *(big_buffer + x) == 'q') { //ignore
136 if(total_size_read >= (x + 20)) {
137 if(!strncmp(big_buffer + x + 1, "make ignore Q_OBJECT", 20)) {
138 debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_OBJECT\"",
139 fn_target.latin1(), line_count);
140 x += 20;
141 ignore_qobject = TRUE;
142 }
143 }
144 } else if(*(big_buffer + x) == '*') {
145 if(total_size_read >= (x+1) && *(big_buffer + (x+1)) == '/') {
146 x += 2;
147 break;
148 }
149 } else if(*(big_buffer + x) == '\n') {
150 line_count++;
151 }
152 }
153 }
154 }
155 }
156#define SYMBOL_CHAR(x) ((x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z') || \
157 (x <= '0' && x >= '9') || x == '_')
158
159 bool interesting = *(big_buffer+x) == 'Q' && (!strncmp(big_buffer+x, "Q_OBJECT", OBJ_LEN) ||
160 !strncmp(big_buffer+x, "Q_DISPATCH", DIS_LEN));
161 if(interesting) {
162 int len = 0;
163 if(!strncmp(big_buffer+x, "Q_OBJECT", OBJ_LEN)) {
164 if(ignore_qobject) {
165 debug_msg(2, "Mocgen: %s:%d Ignoring Q_OBJECT", fn_target.latin1(), line_count);
166 interesting = FALSE;
167 }
168 len=OBJ_LEN;
169 } else if(!strncmp(big_buffer+x, "Q_DISPATCH", DIS_LEN)) {
170 len=DIS_LEN;
171 }
172 if(SYMBOL_CHAR(*(big_buffer+x+len)))
173 interesting = FALSE;
174 if(interesting) {
175 *(big_buffer+x+len) = '\0';
176 debug_msg(2, "Mocgen: %s:%d Found MOC symbol %s", fn_target.latin1(), line_count, big_buffer+x);
177
178 int ext_pos = fn_target.findRev('.');
179 int ext_len = fn_target.length() - ext_pos;
180 int dir_pos = fn_target.findRev(Option::dir_sep, ext_pos);
181 QString mocFile;
182 if(!project->isEmpty("MOC_DIR"))
183 mocFile = project->first("MOC_DIR");
184 else if(dir_pos != -1)
185 mocFile = fn_target.left(dir_pos+1);
186
187 bool cpp_ext = FALSE;
188 for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) {
189 if((cpp_ext = (fn_target.right(ext_len) == (*cppit))))
190 break;
191 }
192 if(cpp_ext) {
193 mocFile += fn_target.mid(dir_pos+1, ext_pos - dir_pos-1) + Option::moc_ext;
194 findDependencies(fn_target).append(mocFile);
195 project->variables()["_SRCMOC"].append(mocFile);
196 } else if(project->variables()["HEADERS"].findIndex(fn_target) != -1) {
197 for(QStringList::Iterator hit = Option::h_ext.begin(); hit != Option::h_ext.end(); ++hit) {
198 if((fn_target.right(ext_len) == (*hit))) {
199 mocFile += Option::moc_mod + fn_target.mid(dir_pos+1, ext_pos - dir_pos-1) +
200 Option::cpp_ext.first();
201 logicWarn(mocFile, "SOURCES");
202 project->variables()["_HDRMOC"].append(mocFile);
203 break;
204 }
205 }
206 }
207
208 if(!mocFile.isEmpty()) {
209 mocFile = Option::fixPathToTargetOS(mocFile);
210 mocablesToMOC[cleanFilePath(fn_target)] = mocFile;
211 mocablesFromMOC[cleanFilePath(mocFile)] = fn_target;
212 }
213 break;
214 }
215 }
216
217 while(x < total_size_read && SYMBOL_CHAR(*(big_buffer+x)))
218 x++;
219 if(*(big_buffer+x) == '\n')
220 line_count++;
221 }
222#undef OBJ_LEN
223#undef DIS_LEN
224 return TRUE;
225}
226
227bool
228MakefileGenerator::generateDependencies(QPtrList<MakefileDependDir> &dirs, QString fn, bool recurse)
229{
230 fn = fileFixify(fn);
231 QStringList &fndeps = findDependencies(fn);
232 if(!fndeps.isEmpty())
233 return TRUE;
234
235 fn = Option::fixPathToLocalOS(fn, FALSE);
236 QString fix_env_fn = Option::fixPathToLocalOS(fn);
237 int file = open(fix_env_fn.latin1(), O_RDONLY);
238 if(file == -1)
239 return FALSE;
240 struct stat fst;
241 if(fstat(file, &fst) || S_ISDIR(fst.st_mode))
242 return FALSE; //shouldn't happen
243
244 QString fndir, fix_env_fndir;
245 int dl = fn.findRev(Option::dir_sep);
246 if(dl != -1)
247 fndir = fn.left(dl+1);
248 dl = fix_env_fn.findRev(Option::dir_sep);
249 if(dl != -1)
250 fix_env_fndir = fix_env_fn.left(dl + 1);
251
252 int line_count = 1;
253 char *big_buffer = gimme_buffer(fst.st_size);
254
255 int total_size_read;
256 for(int have_read = total_size_read = 0;
257 (have_read = read(file, big_buffer + total_size_read,
258 fst.st_size - total_size_read));
259 total_size_read += have_read);
260 close(file);
261
262 bool ui_file = fn.endsWith(Option::ui_ext);
263 for(int x = 0; x < total_size_read; x++) {
264 QStringList *outdeps=&fndeps;
265 QString inc;
266 if(!ui_file) {
267 if(*(big_buffer + x) == '/') {
268 x++;
269 if(total_size_read >= x) {
270 if(*(big_buffer + x) == '/') { //c++ style comment
271 for( ; x < total_size_read && *(big_buffer + x) != '\n'; x++);
272 } else if(*(big_buffer + x) == '*') { //c style comment
273 for( ; x < total_size_read; x++) {
274 if(*(big_buffer + x) == '*') {
275 if(total_size_read >= (x+1) && *(big_buffer + (x+1)) == '/') {
276 x += 2;
277 break;
278 }
279 } else if(*(big_buffer + x) == '\n') {
280 line_count++;
281 }
282 }
283 }
284 }
285 }
286 if(*(big_buffer + x) == '#') {
287 x++;
288 while(x < total_size_read && //Skip spaces after hash
289 (*(big_buffer+x) == ' ' || *(big_buffer+x) == '\t'))
290 x++;
291 if(total_size_read >= x + 8 && !strncmp(big_buffer + x, "include ", 8)) {
292 for(x+=8; //skip spaces after keyword
293 x < total_size_read && (*(big_buffer+x) == ' ' || *(big_buffer+x) == '\t');
294 x++);
295 char term = *(big_buffer + x);
296 if(term == '"');
297 else if(term == '<')
298 term = '>';
299 else
300 continue; //wtf?
301 x++;
302
303 int inc_len;
304 for(inc_len = 0; *(big_buffer + x + inc_len) != term; inc_len++);
305 *(big_buffer + x + inc_len) = '\0';
306 inc = big_buffer + x;
307 } else if(total_size_read >= x + 14 && !strncmp(big_buffer + x, "qmake_warning ", 14)) {
308 for(x+=14; //skip spaces after keyword
309 x < total_size_read && (*(big_buffer+x) == ' ' || *(big_buffer+x) == '\t');
310 x++);
311 char term = '\n';
312 if(*(big_buffer + x) == '"')
313 term = '"';
314 if(*(big_buffer + x) == '\'')
315 term = '\'';
316 if(term != '\n')
317 x++;
318
319 int msg_len;
320 for(msg_len = 0; *(big_buffer + x + msg_len) != term; msg_len++);
321 *(big_buffer + x + msg_len) = '\0';
322 QString msg = big_buffer + x;
323 debug_msg(0, "%s:%d qmake_warning -- %s", fix_env_fn.latin1(),
324 line_count, msg.latin1());
325 *(big_buffer + x + msg_len) = term; //put it back
326 }
327 }
328 } else if(ui_file) {
329 // skip whitespaces
330 while(x < total_size_read &&
331 (*(big_buffer+x) == ' ' || *(big_buffer+x) == '\t'))
332 x++;
333 if(*(big_buffer + x) == '<') {
334 x++;
335 if(total_size_read >= x + 12 && !strncmp(big_buffer + x, "includehint", 11) &&
336 (*(big_buffer + x + 11) == ' ' || *(big_buffer + x + 11) == '>')) {
337 for(x += 12; *(big_buffer + x) != '>'; x++);
338 int inc_len = 0;
339 for(x += 1 ; *(big_buffer + x + inc_len) != '<'; inc_len++);
340 *(big_buffer + x + inc_len) = '\0';
341 inc = big_buffer + x;
342 } else if(total_size_read >= x + 8 && !strncmp(big_buffer + x, "include", 7) &&
343 (*(big_buffer + x + 7) == ' ' || *(big_buffer + x + 7) == '>')) {
344 for(x += 8; *(big_buffer + x) != '>'; x++) {
345 if(total_size_read >= x + 9 && *(big_buffer + x) == 'i' &&
346 !strncmp(big_buffer + x, "impldecl", 8)) {
347 for(x += 8; *(big_buffer + x) != '='; x++);
348 if(*(big_buffer + x) != '=')
349 continue;
350 for(x++; *(big_buffer+x) == '\t' || *(big_buffer+x) == ' '; x++);
351 char quote = 0;
352 if(*(big_buffer+x) == '\'' || *(big_buffer+x) == '"') {
353 quote = *(big_buffer + x);
354 x++;
355 }
356 int val_len;
357 for(val_len = 0; TRUE; val_len++) {
358 if(quote) {
359 if(*(big_buffer+x+val_len) == quote)
360 break;
361 } else if(*(big_buffer + x + val_len) == '>' ||
362 *(big_buffer + x + val_len) == ' ') {
363 break;
364 }
365 }
366 char saved = *(big_buffer + x + val_len);
367 *(big_buffer + x + val_len) = '\0';
368 QString where = big_buffer + x;
369 *(big_buffer + x + val_len) = saved;
370 if(where == "in implementation") {
371 QString cpp = fn.left(fn.length() - Option::ui_ext.length()) +
372 Option::cpp_ext.first();
373 outdeps = &findDependencies(cpp);
374 }
375 }
376 }
377 int inc_len = 0;
378 for(x += 1 ; *(big_buffer + x + inc_len) != '<'; inc_len++);
379 *(big_buffer + x + inc_len) = '\0';
380 inc = big_buffer + x;
381 }
382 }
383 }
384
385 if(!inc.isEmpty()) {
386 debug_msg(5, "%s:%d Found dependency to %s", fix_env_fn.latin1(),
387 line_count, inc.latin1());
388 if(!project->isEmpty("SKIP_DEPENDS")) {
389 bool found = FALSE;
390 QStringList &nodeplist = project->values("SKIP_DEPENDS");
391 for(QStringList::Iterator it = nodeplist.begin();
392 it != nodeplist.end(); ++it) {
393 QRegExp regx((*it));
394 if(regx.search(inc) != -1) {
395 found = TRUE;
396 break;
397 }
398 }
399 if(found)
400 continue;
401 }
402
403 QString fqn;
404 if(project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH") &&
405 !stat(fix_env_fndir + inc, &fst) && !S_ISDIR(fst.st_mode)) {
406 fqn = fndir + inc;
407 } else {
408 if((Option::target_mode == Option::TARG_MAC9_MODE && inc.find(':')) ||
409 (Option::target_mode == Option::TARG_WIN_MODE && inc[1] != ':') ||
410 ((Option::target_mode == Option::TARG_UNIX_MODE ||
411 Option::target_mode == Option::TARG_QNX6_MODE ||
412 Option::target_mode == Option::TARG_MACX_MODE) &&
413 inc[0] != '/')) {
414 for(MakefileDependDir *mdd = dirs.first(); mdd; mdd = dirs.next() ) {
415 if(!stat(mdd->local_dir + QDir::separator() + inc, &fst) &&
416 !S_ISDIR(fst.st_mode)) {
417 fqn = mdd->real_dir + QDir::separator() + inc;
418 break;
419 }
420 }
421 }
422 }
423 if(fqn.isEmpty()) {
424 //these are some hacky heuristics it will try to do on an include
425 //however these can be turned off at runtime, I'm not sure how
426 //reliable these will be, most likely when problems arise turn it off
427 //and see if they go away..
428 if(Option::mkfile::do_dep_heuristics && depHeuristics.contains(inc)) {
429 fqn = depHeuristics[inc];
430 } else if(Option::mkfile::do_dep_heuristics) { //some heuristics..
431 //is it a file from a .ui?
432 QString inc_file = inc.section(Option::dir_sep, -1);
433 int extn = inc_file.findRev('.');
434 if(extn != -1 &&
435 (inc_file.right(inc_file.length()-extn) == Option::cpp_ext.first() ||
436 inc_file.right(inc_file.length()-extn) == Option::h_ext.first())) {
437 QString uip = inc_file.left(extn) + Option::ui_ext;
438 QStringList uil = project->variables()["FORMS"];
439 for(QStringList::Iterator it = uil.begin(); it != uil.end(); ++it) {
440 if((*it).section(Option::dir_sep, -1) == uip) {
441 if(!project->isEmpty("UI_DIR"))
442 fqn = project->first("UI_DIR");
443 else if(!project->isEmpty("UI_HEADERS_DIR"))
444 fqn = project->first("UI_HEADERS_DIR");
445 else
446 fqn = (*it).section(Option::dir_sep, 0, -2);
447 if(!fqn.isEmpty() && !fqn.endsWith(Option::dir_sep))
448 fqn += Option::dir_sep;
449 fqn += inc_file;
450 break;
451 }
452 }
453 }
454 if(fqn.isEmpty()) { //is it from a .y?
455 QString rhs = Option::yacc_mod + Option::h_ext.first();
456 if(inc.endsWith(rhs)) {
457 QString lhs = inc.left(inc.length() - rhs.length()) + Option::yacc_ext;
458 QStringList yl = project->variables()["YACCSOURCES"];
459 for(QStringList::Iterator it = yl.begin(); it != yl.end(); ++it) {
460 QString s = (*it), d;
461 int slsh = s.findRev(Option::dir_sep);
462 if(slsh != -1) {
463 d = s.left(slsh + 1);
464 s = s.right(s.length() - slsh - 1);
465 }
466 if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH"))
467 d = project->first("QMAKE_ABSOLUTE_SOURCE_PATH");
468 if(s == lhs) {
469 fqn = d + inc;
470 break;
471 }
472 }
473 }
474 }
475 depHeuristics.insert(inc, fqn);
476 }
477 if(!Option::mkfile::do_dep_heuristics || fqn.isEmpty()) //I give up
478 continue;
479 }
480
481 fqn = fileFixify(Option::fixPathToTargetOS(fqn, FALSE));
482 debug_msg(4, "Resolved dependancy of %s to %s", inc.latin1(), fqn.latin1());
483 if(outdeps && outdeps->findIndex(fqn) == -1)
484 outdeps->append(fqn);
485 }
486 //read past new line now..
487 for( ; x < total_size_read && (*(big_buffer + x) != '\n'); x++);
488 line_count++;
489 }
490
491 if(recurse) {
492 for(QStringList::Iterator fnit = fndeps.begin(); fnit != fndeps.end(); ++fnit) {
493 generateDependencies(dirs, (*fnit), recurse);
494 QStringList &deplist = findDependencies((*fnit));
495 for(QStringList::Iterator it = deplist.begin(); it != deplist.end(); ++it)
496 if(fndeps.findIndex((*it)) == -1)
497 fndeps.append((*it));
498 }
499 }
500 debug_msg(2, "Dependancies: %s -> %s", fn.latin1(), fndeps.join(" :: ").latin1());
501 return TRUE;
502}
503
504void
505MakefileGenerator::initOutPaths()
506{
507 if(init_opath_already)
508 return;
509 init_opath_already = TRUE;
510 QMap<QString, QStringList> &v = project->variables();
511 if(!v.contains("QMAKE_ABSOLUTE_SOURCE_PATH")) {
512 if(Option::mkfile::do_cache && !Option::mkfile::cachefile.isEmpty() &&
513 v.contains("QMAKE_ABSOLUTE_SOURCE_ROOT")) {
514 QString root = v["QMAKE_ABSOLUTE_SOURCE_ROOT"].first();
515 root = Option::fixPathToTargetOS( root );
516 if(!root.isEmpty()) {
517 QFileInfo fi(Option::mkfile::cachefile);
518 if(!fi.convertToAbs()) {
519 QString cache_r = fi.dirPath(), pwd = Option::output_dir;
520 if ( pwd.startsWith(cache_r) && !pwd.startsWith(root) ) {
521 pwd = Option::fixPathToTargetOS(root + pwd.mid(cache_r.length()));
522 if(QFile::exists(pwd))
523 v.insert("QMAKE_ABSOLUTE_SOURCE_PATH", pwd);
524 }
525 }
526 }
527 }
528 }
529 if(!v["QMAKE_ABSOLUTE_SOURCE_PATH"].isEmpty()) {
530 QString &asp = v["QMAKE_ABSOLUTE_SOURCE_PATH"].first();
531 asp = Option::fixPathToTargetOS( asp );
532 if(asp.isEmpty() || asp == Option::output_dir) //if they're the same, why bother?
533 v["QMAKE_ABSOLUTE_SOURCE_PATH"].clear();
534 }
535 QString currentDir = QDir::currentDirPath();
536 QString dirs[] = { QString("OBJECTS_DIR"), QString("MOC_DIR"), QString("UI_HEADERS_DIR"),
537 QString("UI_SOURCES_DIR"), QString("UI_DIR"), QString("DESTDIR"),
538 QString("SUBLIBS_DIR"), QString::null };
539 for(int x = 0; dirs[x] != QString::null; x++) {
540 if ( !v[dirs[x]].isEmpty() ) {
541 QString orig_path = v[dirs[x]].first();
542 {
543 QString &path = v[dirs[x]].first();
544 path = fileFixify(path, Option::output_dir, Option::output_dir);
545 if(path.right(Option::dir_sep.length()) != Option::dir_sep)
546 path += Option::dir_sep;
547 }
548 if(noIO())
549 continue;
550
551 QString path = project->first(dirs[x]); //not to be changed any further
552 path = Option::fixPathToTargetOS(fileFixify(path, QDir::currentDirPath(), Option::output_dir));
553 debug_msg(3, "Fixed output_dir %s (%s) into %s (%s)", dirs[x].latin1(), orig_path.latin1(),
554 v[dirs[x]].join("::").latin1(), path.latin1());
555
556 QDir d;
557 if(path.startsWith(Option::dir_sep)) {
558 d.cd(Option::dir_sep);
559 path = path.right(path.length() - 1);
560 }
561#ifdef Q_WS_WIN
562 bool driveExists = TRUE;
563 if ( !QDir::isRelativePath( path ) ) {
564 if ( QFile::exists( path.left( 3 ) ) ) {
565 d.cd( path.left( 3 ) );
566 path = path.right( path.length() - 3 );
567 } else {
568 warn_msg(WarnLogic, "%s: Cannot access drive '%s' (%s)", dirs[x].latin1(),
569 path.left( 3 ).latin1(), path.latin1() );
570 driveExists = FALSE;
571 }
572 }
573 if ( driveExists ) {
574#endif
575 QStringList subs = QStringList::split(Option::dir_sep, path);
576 for(QStringList::Iterator subit = subs.begin(); subit != subs.end(); ++subit) {
577 if(!d.cd(*subit)) {
578 d.mkdir((*subit));
579 if ( d.exists( (*subit) ) )
580 d.cd((*subit));
581 else {
582 warn_msg(WarnLogic, "%s: Cannot access directory '%s' (%s)", dirs[x].latin1(),
583 (*subit).latin1(), path.latin1() );
584 break;
585 }
586 }
587 }
588#ifdef Q_WS_WIN
589 }
590#endif
591 }
592 }
593 QDir::current().cd( currentDir );
594}
595
596void
597MakefileGenerator::init()
598{
599 initOutPaths();
600 if(init_already)
601 return;
602 init_already = TRUE;
603
604 QMap<QString, QStringList> &v = project->variables();
605 QString paths[] = { QString("SOURCES"), QString("FORMS"), QString("YACCSOURCES"), QString("INCLUDEPATH"),
606 QString("HEADERS"), QString("HEADERS_ORIG"),
607 QString("LEXSOURCES"), QString("QMAKE_INTERNAL_INCLUDED_FILES"), QString::null };
608 for(int y = 0; paths[y] != QString::null; y++) {
609 QStringList &l = v[paths[y]];
610 if(!l.isEmpty())
611 l = fileFixify(l);
612 }
613
614 /* get deps and mocables */
615 QDict<void> cache_found_files;
616 QString cache_file(Option::output_dir + QDir::separator() + ".qmake.internal.cache");
617 if((Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT ||
618 Option::mkfile::do_deps || Option::mkfile::do_mocs) && !noIO()) {
619 QPtrList<MakefileDependDir> deplist;
620 deplist.setAutoDelete(TRUE);
621 if((Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT || Option::mkfile::do_deps) &&
622 doDepends()) {
623 QStringList incDirs = v["DEPENDPATH"] + v["QMAKE_ABSOLUTE_SOURCE_PATH"];
624 if(project->isActiveConfig("depend_includepath"))
625 incDirs += v["INCLUDEPATH"];
626 for(QStringList::Iterator it = incDirs.begin(); it != incDirs.end(); ++it) {
627 QString r = (*it), l = Option::fixPathToLocalOS((*it));
628 deplist.append(new MakefileDependDir(r.replace("\"",""),
629 l.replace("\"","")));
630 }
631 debug_msg(1, "Dependancy Directories: %s", incDirs.join(" :: ").latin1());
632 if(Option::output.name() != "-" && project->isActiveConfig("qmake_cache")) {
633 QFile cachef(cache_file);
634 if(cachef.open(IO_ReadOnly | IO_Translate)) {
635 QFileInfo cachefi(cache_file);
636 debug_msg(2, "Trying internal cache information: %s", cache_file.latin1());
637 QTextStream cachet(&cachef);
638 QString line, file;
639 enum { CacheInfo, CacheDepend, CacheMoc } state = CacheInfo;
640 while (!cachet.eof()) {
641 line = cachet.readLine().stripWhiteSpace();
642 int sep = line.find('=');
643 if(line == "[depend]") {
644 state = CacheDepend;
645 } else if(line == "[mocable]") {
646 state = CacheMoc;
647 } else if(line == "[check]") {
648 state = CacheInfo;
649 } else if(!line.isEmpty() && sep != -1) {
650 file = line.left(sep).stripWhiteSpace();
651 line = line.right(line.length() - sep - 1).stripWhiteSpace();
652 if(state == CacheInfo) {
653 if(file == "QMAKE_CACHE_VERSION") {
654 if(line != qmake_version())
655 break;
656 } else {
657 const QStringList &l = project->variables()[file];
658 if(!l.isEmpty() && !line.isEmpty() && l.join(" ") != line)
659 break;
660 }
661 } else if(state == CacheDepend) {
662 bool found = (bool)cache_found_files[file];
663 QStringList files = QStringList::split(" ", line);
664 if(!found) {
665 QFileInfo fi(fileFixify(file, QDir::currentDirPath(), Option::output_dir));
666 if(fi.exists() && fi.lastModified() < cachefi.lastModified()) {
667 cache_found_files.insert(file, (void *)1);
668 found = TRUE;
669 }
670 }
671 if(found) {
672 for(QStringList::Iterator dep_it = files.begin();
673 dep_it != files.end(); ++dep_it) {
674 if(!cache_found_files[(*dep_it)]) {
675 QFileInfo fi(fileFixify((*dep_it), QDir::currentDirPath(), Option::output_dir));
676 if(fi.exists() &&
677 fi.lastModified() < cachefi.lastModified()) {
678 cache_found_files.insert((*dep_it), (void *)1);
679 } else {
680 found = FALSE;
681 break;
682 }
683 }
684 }
685 if(found) {
686 debug_msg(2, "Dependancies (cached): %s -> %s", file.latin1(),
687 files.join(" :: ").latin1());
688 findDependencies(file) = files;
689 }
690 }
691 } else {
692 void *found = cache_found_files[file];
693 if(found != (void *)2) {
694 if(found) {
695 cache_found_files.replace(file, (void *)2);
696 } else {
697 QFileInfo fi(fileFixify(file, QDir::currentDirPath(), Option::output_dir));
698 if(fi.exists() && fi.lastModified() < cachefi.lastModified()) {
699 cache_found_files.insert(file, (void *)2);
700 found = (void*)1;
701 }
702 }
703 }
704 if(found && line != "*qmake_ignore*") {
705 int ext_len = file.length() - file.findRev('.');
706 bool cpp_ext = FALSE;
707 for(QStringList::Iterator cppit = Option::cpp_ext.begin();
708 cppit != Option::cpp_ext.end(); ++cppit) {
709 if((cpp_ext = (file.right(ext_len) == (*cppit))))
710 break;
711 }
712 if(cpp_ext) {
713 project->variables()["_SRCMOC"].append(line);
714 } else if(project->variables()["HEADERS"].findIndex(file) != -1) {
715 for(QStringList::Iterator hit = Option::h_ext.begin();
716 hit != Option::h_ext.end(); ++hit) {
717 if((file.right(ext_len) == (*hit))) {
718 project->variables()["_HDRMOC"].append(line);
719 break;
720 }
721 }
722 }
723 debug_msg(2, "Mocgen (cached): %s -> %s", file.latin1(),
724 line.latin1());
725 mocablesToMOC[file] = line;
726 mocablesFromMOC[line] = file;
727 }
728 }
729 }
730 }
731 cachef.close();
732 }
733 }
734 }
735 if(!noIO()) {
736 QString sources[] = { QString("OBJECTS"), QString("LEXSOURCES"), QString("YACCSOURCES"),
737 QString("HEADERS"), QString("SOURCES"), QString("FORMS"),
738 QString::null };
739 depHeuristics.clear();
740 bool write_cache = FALSE, read_cache = QFile::exists(cache_file);
741 for(int x = 0; sources[x] != QString::null; x++) {
742 QStringList vpath, &l = v[sources[x]];
743 for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) {
744 if(!(*val_it).isEmpty()) {
745 QString file = Option::fixPathToLocalOS((*val_it));
746 if(!QFile::exists(file)) {
747 bool found = FALSE;
748 if(QDir::isRelativePath(file)) {
749 if(vpath.isEmpty())
750 vpath = v["VPATH_" + sources[x]] + v["VPATH"] +
751 v["QMAKE_ABSOLUTE_SOURCE_PATH"] + v["DEPENDPATH"];
752
753 for(QStringList::Iterator vpath_it = vpath.begin();
754 vpath_it != vpath.end(); ++vpath_it) {
755 QString real_dir = Option::fixPathToLocalOS((*vpath_it));
756 if(QFile::exists(real_dir + QDir::separator() + (*val_it))) {
757 QString dir = (*vpath_it);
758 if(dir.right(Option::dir_sep.length()) != Option::dir_sep)
759 dir += Option::dir_sep;
760 (*val_it) = fileFixify(dir + (*val_it));
761 found = TRUE;
762 debug_msg(1, "Found file through vpath %s -> %s",
763 file.latin1(), (*val_it).latin1());
764 break;
765 }
766 }
767 }
768 if(!found) {
769 QString dir, regex = (*val_it), real_dir;
770 if(regex.findRev(Option::dir_sep) != -1) {
771 dir = regex.left(regex.findRev(Option::dir_sep) + 1);
772 real_dir = fileFixify(Option::fixPathToLocalOS(dir),
773 QDir::currentDirPath(), Option::output_dir);
774 regex = regex.right(regex.length() - dir.length());
775 }
776 if(real_dir.isEmpty() || QFile::exists(real_dir)) {
777 QDir d(real_dir, regex);
778 if(!d.count()) {
779 debug_msg(1, "%s:%d Failure to find %s in vpath (%s)",
780 __FILE__, __LINE__,
781 (*val_it).latin1(), vpath.join("::").latin1());
782 warn_msg(WarnLogic, "Failure to find: %s", (*val_it).latin1());
783 continue;
784 } else {
785 (*val_it) = dir + d[0];
786 for(int i = 1; i < (int)d.count(); i++)
787 l.insert(val_it, dir + d[i]);
788 }
789 } else {
790 debug_msg(1, "%s:%d Cannot match %s%c%s, as %s does not exist.",
791 __FILE__, __LINE__,
792 real_dir.latin1(), QDir::separator(), regex.latin1(),
793 real_dir.latin1());
794 warn_msg(WarnLogic, "Failure to find: %s", (*val_it).latin1());
795 }
796 }
797 }
798
799 QString val_file = fileFixify((*val_it));
800 bool found_cache_moc = FALSE, found_cache_dep = FALSE;
801 if(read_cache && Option::output.name() != "-" &&
802 project->isActiveConfig("qmake_cache")) {
803 if(!findDependencies(val_file).isEmpty())
804 found_cache_dep = TRUE;
805 if(cache_found_files[(*val_it)] == (void *)2)
806 found_cache_moc = TRUE;
807 if(!found_cache_moc || !found_cache_dep)
808 write_cache = TRUE;
809 }
810 if(!found_cache_dep && sources[x] != "OBJECTS") {
811 debug_msg(5, "Looking for dependancies for %s", (*val_it).latin1());
812 generateDependencies(deplist, (*val_it), doDepends());
813 }
814 if(found_cache_moc) {
815 QString moc = findMocDestination(val_file);
816 if(!moc.isEmpty()) {
817 for(QStringList::Iterator cppit = Option::cpp_ext.begin();
818 cppit != Option::cpp_ext.end(); ++cppit) {
819 if(val_file.endsWith((*cppit))) {
820 QStringList &deps = findDependencies(val_file);
821 if(!deps.contains(moc))
822 deps.append(moc);
823 break;
824 }
825 }
826 }
827 } else if(mocAware() && (sources[x] == "SOURCES" || sources[x] == "HEADERS") &&
828 (Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT ||
829 Option::mkfile::do_mocs)) {
830 generateMocList((*val_it));
831 }
832 }
833 }
834 }
835 if(project->isActiveConfig("qmake_cache") && (write_cache || !read_cache)) {
836 QFile cachef(cache_file);
837 if(cachef.open(IO_WriteOnly | IO_Translate)) {
838 debug_msg(2, "Writing internal cache information: %s", cache_file.latin1());
839 QTextStream cachet(&cachef);
840 cachet << "[check]" << "\n"
841 << "QMAKE_CACHE_VERSION = " << qmake_version() << "\n"
842 << "QMAKE_ABSOLUTE_SOURCE_PATH = " << var("QMAKE_ABSOLUTE_SOURCE_PATH") << "\n"
843 << "MOC_DIR = " << var("MOC_DIR") << "\n"
844 << "UI_DIR = " << var("UI_DIR") << "\n"
845 << "UI_HEADERS_DIR = " << var("UI_HEADERS_DIR") << "\n"
846 << "UI_SOURCES_DIR = " << var("UI_SOURCES_DIR") << "\n";
847 cachet << "[depend]" << endl;
848 for(QMap<QString, QStringList>::Iterator it = depends.begin();
849 it != depends.end(); ++it)
850 cachet << depKeyMap[it.key()] << " = " << it.data().join(" ") << endl;
851 cachet << "[mocable]" << endl;
852 QString mc, moc_sources[] = { QString("HEADERS"), QString("SOURCES"), QString::null };
853 for(int x = 0; moc_sources[x] != QString::null; x++) {
854 QStringList &l = v[moc_sources[x]];
855 for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) {
856 if(!(*val_it).isEmpty()) {
857 mc = mocablesToMOC[(*val_it)];
858 if(mc.isEmpty())
859 mc = "*qmake_ignore*";
860 cachet << (*val_it) << " = " << mc << endl;
861 }
862 }
863 }
864 cachef.close();
865 }
866 }
867 }
868 }
869 v["OBJECTS"] = createObjectList("SOURCES") + v["OBJECTS"]; // init variables
870
871 //lex files
872 {
873 QStringList &impls = v["LEXIMPLS"];
874 QStringList &l = v["LEXSOURCES"];
875 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
876 QString dir;
877 QFileInfo fi((*it));
878 if(fi.dirPath() != ".")
879 dir = fi.dirPath() + Option::dir_sep;
880 dir = fileFixify(dir, QDir::currentDirPath(), Option::output_dir);
881 if(!dir.isEmpty() && dir.right(Option::dir_sep.length()) != Option::dir_sep)
882 dir += Option::dir_sep;
883 QString impl = dir + fi.baseName(TRUE) + Option::lex_mod + Option::cpp_ext.first();
884 logicWarn(impl, "SOURCES");
885 logicWarn(impl, "SOURCES");
886 impls.append(impl);
887 if( ! project->isActiveConfig("lex_included")) {
888 v["SOURCES"].append(impl);
889 // attribute deps of lex file to impl file
890 QStringList &lexdeps = findDependencies((*it));
891 QStringList &impldeps = findDependencies(impl);
892 for(QStringList::ConstIterator d = lexdeps.begin(); d != lexdeps.end(); ++d) {
893 if(!impldeps.contains(*d))
894 impldeps.append(*d);
895 }
896 lexdeps.clear();
897 }
898 }
899 if( ! project->isActiveConfig("lex_included"))
900 v["OBJECTS"] += (v["LEXOBJECTS"] = createObjectList("LEXIMPLS"));
901 }
902 //yacc files
903 {
904 QStringList &decls = v["YACCCDECLS"], &impls = v["YACCIMPLS"];
905 QStringList &l = v["YACCSOURCES"];
906 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
907 QString dir;
908 QFileInfo fi((*it));
909 if(fi.dirPath() != ".")
910 dir = fi.dirPath() + Option::dir_sep;
911 dir = fileFixify(dir, QDir::currentDirPath(), Option::output_dir);
912 if(!dir.isEmpty() && dir.right(Option::dir_sep.length()) != Option::dir_sep)
913 dir += Option::dir_sep;
914 QString impl = dir + fi.baseName(TRUE) + Option::yacc_mod + Option::cpp_ext.first();
915 logicWarn(impl, "SOURCES");
916 QString decl = dir + fi.baseName(TRUE) + Option::yacc_mod + Option::h_ext.first();
917 logicWarn(decl, "HEADERS");
918
919 decls.append(decl);
920 impls.append(impl);
921 v["SOURCES"].append(impl);
922 QStringList &impldeps = findDependencies(impl);
923 impldeps.append(decl);
924 // attribute deps of yacc file to impl file
925 QStringList &yaccdeps = findDependencies((*it));
926 for(QStringList::ConstIterator d = yaccdeps.begin(); d != yaccdeps.end(); ++d) {
927 if(!impldeps.contains(*d))
928 impldeps.append(*d);
929 }
930 if( project->isActiveConfig("lex_included")) {
931 // is there a matching lex file ? Transfer its dependencies.
932 QString lexsrc = fi.baseName(TRUE) + Option::lex_ext;
933 if(fi.dirPath() != ".")
934 lexsrc.prepend(fi.dirPath() + Option::dir_sep);
935 if(v["LEXSOURCES"].findIndex(lexsrc) != -1) {
936 QString trg = dir + fi.baseName(TRUE) + Option::lex_mod + Option::cpp_ext.first();
937 impldeps.append(trg);
938 impldeps += findDependencies(lexsrc);
939 depends[lexsrc].clear();
940 }
941 }
942 yaccdeps.clear();
943 }
944 v["OBJECTS"] += (v["YACCOBJECTS"] = createObjectList("YACCIMPLS"));
945 }
946
947 //UI files
948 {
949 if(!project->isEmpty("UI_DIR"))
950 project->variables()["INCLUDEPATH"].append(project->first("UI_DIR"));
951 else if(!project->isEmpty("UI_HEADERS_DIR"))
952 project->variables()["INCLUDEPATH"].append(project->first("UI_HEADERS_DIR"));
953 QStringList &decls = v["UICDECLS"], &impls = v["UICIMPLS"];
954 QStringList &l = v["FORMS"];
955 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
956 QString impl, decl;
957 QFileInfo fi(Option::fixPathToLocalOS((*it)));
958 if ( !project->isEmpty("UI_DIR") ) {
959 impl = decl = project->first("UI_DIR");
960 QString d = fi.dirPath();
961 if( d == ".")
962 d = QDir::currentDirPath();
963 d = fileFixify(d);
964 if( !project->variables()["INCLUDEPATH"].contains(d))
965 project->variables()["INCLUDEPATH"].append(d);
966 } else {
967 if(decl.isEmpty() && !project->isEmpty("UI_HEADERS_DIR"))
968 decl = project->first("UI_HEADERS_DIR");
969 if ( !decl.isEmpty() || (project->isEmpty("UI_HEADERS_DIR") && !project->isEmpty("UI_SOURCES_DIR")) ) {
970 QString d = fi.dirPath();
971 if( d == ".")
972 d = QDir::currentDirPath();
973 d = fileFixify(d);
974 if( !project->variables()["INCLUDEPATH"].contains(d))
975 project->variables()["INCLUDEPATH"].append(d);
976 }
977 if(impl.isEmpty() && !project->isEmpty("UI_SOURCES_DIR"))
978 impl = project->first("UI_SOURCES_DIR");
979 if(fi.dirPath() != ".") {
980 if(impl.isEmpty())
981 impl = fi.dirPath() + Option::dir_sep;
982 if(decl.isEmpty())
983 decl = fi.dirPath() + Option::dir_sep;
984 }
985 }
986 impl += fi.baseName(TRUE) + Option::cpp_ext.first(),
987 decl += fi.baseName(TRUE) + Option::h_ext.first();
988 logicWarn(impl, "SOURCES");
989 logicWarn(decl, "HEADERS");
990 decls.append(decl);
991 impls.append(impl);
992 findDependencies(impl).append(decl);
993
994 QString mocable = Option::moc_mod + fi.baseName(TRUE) + Option::cpp_ext.first();
995 if(!v["MOC_DIR"].isEmpty())
996 mocable.prepend(v["MOC_DIR"].first());
997 else if(fi.dirPath() != ".")
998 mocable.prepend(fi.dirPath() + Option::dir_sep);
999 logicWarn(mocable, "SOURCES");
1000 mocablesToMOC[cleanFilePath(decl)] = mocable;
1001 mocablesFromMOC[cleanFilePath(mocable)] = decl;
1002 v["_UIMOC"].append(mocable);
1003 }
1004 v["OBJECTS"] += (v["UICOBJECTS"] = createObjectList("UICDECLS"));
1005 }
1006
1007 //Image files
1008 if(!project->isEmpty("IMAGES")) {
1009 if(project->isEmpty("QMAKE_IMAGE_COLLECTION"))
1010 v["QMAKE_IMAGE_COLLECTION"].append("qmake_image_collection" + Option::cpp_ext.first());
1011 QString imgfile = project->first("QMAKE_IMAGE_COLLECTION");
1012 Option::fixPathToTargetOS(imgfile);
1013 if(!project->isEmpty("UI_DIR") || !project->isEmpty("UI_SOURCES_DIR")) {
1014 if(imgfile.find(Option::dir_sep) != -1)
1015 imgfile = imgfile.right(imgfile.findRev(Option::dir_sep) + 1);
1016 imgfile.prepend( (project->isEmpty("UI_DIR") ? project->first("UI_SOURCES_DIR") :
1017 project->first("UI_DIR")) );
1018 v["QMAKE_IMAGE_COLLECTION"] = QStringList(imgfile);
1019 }
1020 logicWarn(imgfile, "SOURCES");
1021 if(!noIO()) {
1022 QStringList &l = v["IMAGES"];
1023 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
1024 if(!QFile::exists((*it))) {
1025 warn_msg(WarnLogic, "Failure to open: %s", (*it).latin1());
1026 continue;
1027 }
1028 findDependencies(imgfile).append(fileFixify((*it)));
1029 }
1030 }
1031 v["OBJECTS"] += (v["IMAGEOBJECTS"] = createObjectList("QMAKE_IMAGE_COLLECTION"));
1032 }
1033
1034 if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH"))
1035 project->variables()["INCLUDEPATH"].append(Option::output_dir);
1036
1037 //moc files
1038 if ( mocAware() ) {
1039 if(!project->isEmpty("MOC_DIR"))
1040 project->variables()["INCLUDEPATH"].append(project->first("MOC_DIR"));
1041 v["OBJMOC"] = createObjectList("_HDRMOC") + createObjectList("_UIMOC");
1042
1043 QStringList &l = v["SRCMOC"];
1044 l = v["_HDRMOC"] + v["_UIMOC"] + v["_SRCMOC"];
1045 for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) {
1046 if(!(*val_it).isEmpty())
1047 (*val_it) = Option::fixPathToTargetOS((*val_it), FALSE);
1048 }
1049 }
1050}
1051
1052bool
1053MakefileGenerator::processPrlFile(QString &file)
1054{
1055 bool ret = FALSE, try_replace_file=FALSE;
1056 QString prl_file;
1057 if(file.endsWith(Option::prl_ext)) {
1058 try_replace_file = TRUE;
1059 prl_file = file;
1060 file = "";
1061 } else {
1062 QString tmp = file;
1063 int ext = tmp.findRev('.');
1064 if(ext != -1)
1065 tmp = tmp.left(ext);
1066 prl_file = tmp + Option::prl_ext;
1067 }
1068 prl_file = fileFixify(prl_file);
1069 if(!QFile::exists(fileFixify(prl_file, QDir::currentDirPath(), Option::output_dir)) &&
1070 project->isActiveConfig("qt")) {
1071 QString stem = prl_file, dir, extn;
1072 int slsh = stem.findRev('/'), hadlib = 0;
1073 if(slsh != -1) {
1074 dir = stem.left(slsh + 1);
1075 stem = stem.right(stem.length() - slsh - 1);
1076 }
1077 if(stem.startsWith("lib")) {
1078 hadlib = 1;
1079 stem = stem.right(stem.length() - 3);
1080 }
1081 int dot = stem.find('.');
1082 if(dot != -1) {
1083 extn = stem.right(stem.length() - dot);
1084 stem = stem.left(dot);
1085 }
1086 if(stem == "qt" || stem == "qte" || stem == "qte-mt" || stem == "qt-mt") {
1087 if(stem.endsWith("-mt"))
1088 stem = stem.left(stem.length() - 3); //lose the -mt
1089 else
1090 stem += "-mt"; //try the thread case
1091 prl_file = dir;
1092 if(hadlib)
1093 prl_file += "lib";
1094 prl_file += stem + extn;
1095 try_replace_file = TRUE;
1096 }
1097 }
1098 QString real_prl_file = Option::fixPathToLocalOS(prl_file);
1099 if(project->variables()["QMAKE_PRL_INTERNAL_FILES"].findIndex(prl_file) != -1) {
1100 ret = TRUE;
1101 } else if(!real_prl_file.isEmpty() &&
1102 QFile::exists(fileFixify(real_prl_file, QDir::currentDirPath(), Option::output_dir))) {
1103 project->variables()["QMAKE_PRL_INTERNAL_FILES"].append(prl_file);
1104 QMakeProject proj;
1105 debug_msg(1, "Processing PRL file: %s", real_prl_file.latin1());
1106 if(!proj.read(fileFixify(real_prl_file, QDir::currentDirPath(), Option::output_dir),
1107 QDir::currentDirPath())) {
1108 fprintf(stderr, "Error processing prl file: %s\n", real_prl_file.latin1());
1109 } else {
1110 ret = TRUE;
1111 QMap<QString, QStringList> &vars = proj.variables();
1112 for( QMap<QString, QStringList>::Iterator it = vars.begin(); it != vars.end(); ++it)
1113 processPrlVariable(it.key(), it.data());
1114 if(try_replace_file && !proj.isEmpty("QMAKE_PRL_TARGET")) {
1115 QString dir;
1116 int slsh = real_prl_file.findRev(Option::dir_sep);
1117 if(slsh != -1)
1118 dir = real_prl_file.left(slsh+1);
1119 file = dir + proj.first("QMAKE_PRL_TARGET");
1120 }
1121 }
1122 if(ret)
1123 project->variables()["QMAKE_INTERNAL_INCLUDED_FILES"].append(prl_file);
1124 }
1125 return ret;
1126}
1127
1128void
1129MakefileGenerator::processPrlVariable(const QString &var, const QStringList &l)
1130{
1131 if(var == "QMAKE_PRL_LIBS") {
1132 QString where = "QMAKE_LIBS";
1133 if(!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS"))
1134 where = project->first("QMAKE_INTERNAL_PRL_LIBS");
1135 QStringList &out = project->variables()[where];
1136 for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
1137 if( out.findIndex((*it)) == -1)
1138 out.append((*it));
1139 }
1140 } else if(var == "QMAKE_PRL_DEFINES") {
1141 QStringList &out = project->variables()["DEFINES"];
1142 for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
1143 if(out.findIndex((*it)) == -1 &&
1144 project->variables()["PRL_EXPORT_DEFINES"].findIndex((*it)) == -1)
1145 out.append((*it));
1146 }
1147 }
1148}
1149
1150void
1151MakefileGenerator::processPrlFiles()
1152{
1153 QDict<void> processed;
1154 for(bool ret = FALSE; TRUE; ret = FALSE) {
1155 //read in any prl files included..
1156 QStringList l_out;
1157 QString where = "QMAKE_LIBS";
1158 if(!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS"))
1159 where = project->first("QMAKE_INTERNAL_PRL_LIBS");
1160 QStringList &l = project->variables()[where];
1161 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
1162 QString file = (*it);
1163 if(!processed[file] && processPrlFile(file)) {
1164 processed.insert(file, (void*)1);
1165 ret = TRUE;
1166 }
1167 if(!file.isEmpty())
1168 l_out.append(file);
1169 }
1170 if(ret)
1171 l = l_out;
1172 else
1173 break;
1174 }
1175}
1176
1177void
1178MakefileGenerator::writePrlFile(QTextStream &t)
1179{
1180 QString target = project->first("TARGET");
1181 int slsh = target.findRev(Option::dir_sep);
1182 if(slsh != -1)
1183 target = target.right(target.length() - slsh - 1);
1184 QString bdir = Option::output_dir;
1185 if(bdir.isEmpty())
1186 bdir = QDir::currentDirPath();
1187 t << "QMAKE_PRL_BUILD_DIR = " << bdir << endl;
1188
1189 if(!project->projectFile().isEmpty() && project->projectFile() != "-")
1190 t << "QMAKE_PRO_INPUT = " << project->projectFile().section('/', -1) << endl;
1191
1192 if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH"))
1193 t << "QMAKE_PRL_SOURCE_DIR = " << project->first("QMAKE_ABSOLUTE_SOURCE_PATH") << endl;
1194 t << "QMAKE_PRL_TARGET = " << target << endl;
1195 if(!project->isEmpty("PRL_EXPORT_DEFINES"))
1196 t << "QMAKE_PRL_DEFINES = " << project->variables()["PRL_EXPORT_DEFINES"].join(" ") << endl;
1197 if(!project->isEmpty("CONFIG"))
1198 t << "QMAKE_PRL_CONFIG = " << project->variables()["CONFIG"].join(" ") << endl;
1199 if(project->isActiveConfig("staticlib") || project->isActiveConfig("explicitlib")) {
1200 QStringList libs;
1201 if(!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS"))
1202 libs = project->variables()["QMAKE_INTERNAL_PRL_LIBS"];
1203 else
1204 libs << "QMAKE_LIBS"; //obvious one
1205 t << "QMAKE_PRL_LIBS = ";
1206 for(QStringList::Iterator it = libs.begin(); it != libs.end(); ++it)
1207 t << project->variables()[(*it)].join(" ") << " ";
1208 t << endl;
1209 }
1210}
1211
1212bool
1213MakefileGenerator::write()
1214{
1215 init();
1216 findLibraries();
1217 if((Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE || //write prl
1218 Option::qmake_mode == Option::QMAKE_GENERATE_PRL) &&
1219 project->isActiveConfig("create_prl") && project->first("TEMPLATE") == "lib" &&
1220 !project->isActiveConfig("plugin")) {
1221 QString prl = var("TARGET");
1222 int slsh = prl.findRev(Option::dir_sep);
1223 if(slsh != -1)
1224 prl = prl.right(prl.length() - slsh);
1225 int dot = prl.find('.');
1226 if(dot != -1)
1227 prl = prl.left(dot);
1228 prl += Option::prl_ext;
1229 if(!project->isEmpty("DESTDIR"))
1230 prl.prepend(var("DESTDIR"));
1231 QString local_prl = fileFixify(prl, QDir::currentDirPath(), Option::output_dir);
1232 fixEnvVariables(local_prl);
1233 QFile ft(local_prl);
1234 if(ft.open(IO_WriteOnly)) {
1235 project->variables()["ALL_DEPS"].append(prl);
1236 project->variables()["QMAKE_INTERNAL_PRL_FILE"].append(prl);
1237 QTextStream t(&ft);
1238 writePrlFile(t);
1239 ft.close();
1240 }
1241 }
1242 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE &&
1243 project->isActiveConfig("link_prl")) //load up prl's
1244 processPrlFiles();
1245
1246 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
1247 Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) {
1248 QTextStream t(&Option::output);
1249 writeMakefile(t);
1250 }
1251 return TRUE;
1252}
1253
1254void
1255MakefileGenerator::writeObj(QTextStream &t, const QString &obj, const QString &src)
1256{
1257 QStringList &objl = project->variables()[obj];
1258 QStringList &srcl = project->variables()[src];
1259
1260 QStringList::Iterator oit = objl.begin();
1261 QStringList::Iterator sit = srcl.begin();
1262 QString stringSrc("$src");
1263 QString stringObj("$obj");
1264 for( ;sit != srcl.end() && oit != objl.end(); oit++, sit++) {
1265 if((*sit).isEmpty())
1266 continue;
1267
1268 if(!doDepends()) {
1269 QString sdep, odep = (*sit) + " ";
1270 QStringList deps = findDependencies((*sit));
1271 for(QStringList::Iterator dit = deps.begin(); dit != deps.end(); dit++) {
1272 if((*dit).endsWith(Option::moc_ext))
1273 odep += (*dit) + " ";
1274 else
1275 sdep += (*dit) + " ";
1276 }
1277 t << (*sit) << ": " << sdep << endl
1278 << (*oit) << ": " << odep ;
1279 } else {
1280 t << (*oit) << ": " << (*sit) << " " << findDependencies((*sit)).join(" \\\n\t\t");
1281 }
1282
1283 QString comp, cimp;
1284 for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) {
1285 if((*sit).endsWith((*cppit))) {
1286 comp = "QMAKE_RUN_CXX";
1287 cimp = "QMAKE_RUN_CXX_IMP";
1288 break;
1289 }
1290 }
1291 if(comp.isEmpty()) {
1292 comp = "QMAKE_RUN_CC";
1293 cimp = "QMAKE_RUN_CC_IMP";
1294 }
1295 bool use_implicit_rule = !project->isEmpty(cimp);
1296 if(use_implicit_rule) {
1297 if(!project->isEmpty("OBJECTS_DIR")) {
1298 use_implicit_rule = FALSE;
1299 } else {
1300 int dot = (*sit).findRev('.');
1301 if(dot == -1 || ((*sit).left(dot) + Option::obj_ext != (*oit)))
1302 use_implicit_rule = FALSE;
1303 }
1304 }
1305 if (!use_implicit_rule) {
1306 QString p = var(comp);
1307 p.replace(stringSrc, (*sit));
1308 p.replace(stringObj, (*oit));
1309 t << "\n\t" << p;
1310 }
1311 t << endl << endl;
1312 }
1313}
1314
1315
1316void
1317MakefileGenerator::writeUicSrc(QTextStream &t, const QString &ui)
1318{
1319 QStringList &uil = project->variables()[ui];
1320 for(QStringList::Iterator it = uil.begin(); it != uil.end(); it++) {
1321 QString deps = findDependencies((*it)).join(" \\\n\t\t"), decl, impl;
1322 {
1323 QString tmp = (*it);
1324 decl = tmp.replace(QRegExp("\\" + Option::ui_ext + "$"), Option::h_ext.first());
1325 tmp = (*it);
1326 impl = tmp.replace(QRegExp("\\" + Option::ui_ext + "$"), Option::cpp_ext.first());
1327 int dlen = (*it).findRev(Option::dir_sep) + 1;
1328 if(!project->isEmpty("UI_DIR")) {
1329 decl = project->first("UI_DIR") + decl.right(decl.length() - dlen);
1330 impl = project->first("UI_DIR") + impl.right(impl.length() - dlen);
1331 } else {
1332 if(!project->isEmpty("UI_HEADERS_DIR"))
1333 decl = project->first("UI_HEADERS_DIR") + decl.right(decl.length() - dlen);
1334 if(!project->isEmpty("UI_SOURCES_DIR"))
1335 impl = project->first("UI_SOURCES_DIR") + impl.right(impl.length() - dlen);
1336 }
1337 }
1338 t << decl << ": " << (*it) << " " << deps << "\n\t"
1339 << "$(UIC) " << (*it) << " -o " << decl << endl << endl;
1340
1341 QString mildDecl = decl;
1342 int k = mildDecl.findRev( Option::dir_sep );
1343 if ( k != -1 )
1344 mildDecl = mildDecl.mid( k + 1 );
1345
1346 t << impl << ": " << decl << " " << (*it) << " " << deps << "\n\t"
1347 << "$(UIC) " << (*it) << " -i " << mildDecl << " -o " << impl << endl << endl;
1348 }
1349}
1350
1351
1352void
1353MakefileGenerator::writeMocObj(QTextStream &t, const QString &obj, const QString &src)
1354{
1355 QStringList &objl = project->variables()[obj],
1356 &srcl = project->variables()[src];
1357 QStringList::Iterator oit = objl.begin(), sit = srcl.begin();
1358 QString stringSrc("$src"), stringObj("$obj");
1359 for( ;sit != srcl.end() && oit != objl.end(); oit++, sit++) {
1360 QString hdr = findMocSource((*sit));
1361 t << (*oit) << ": " << (*sit) << " "
1362 << hdr << " " << findDependencies(hdr).join(" \\\n\t\t");
1363 bool use_implicit_rule = !project->isEmpty("QMAKE_RUN_CXX_IMP");
1364 if(use_implicit_rule) {
1365 if(!project->isEmpty("OBJECTS_DIR") || !project->isEmpty("MOC_DIR")) {
1366 use_implicit_rule = FALSE;
1367 } else {
1368 int dot = (*sit).findRev('.');
1369 if(dot == -1 || ((*sit).left(dot) + Option::obj_ext != (*oit)))
1370 use_implicit_rule = FALSE;
1371 }
1372 }
1373 if (!use_implicit_rule) {
1374 QString p = var("QMAKE_RUN_CXX");
1375 p.replace(stringSrc, (*sit));
1376 p.replace(stringObj, (*oit));
1377 t << "\n\t" << p;
1378 }
1379 t << endl << endl;
1380 }
1381}
1382
1383
1384void
1385MakefileGenerator::writeMocSrc(QTextStream &t, const QString &src)
1386{
1387 QStringList &l = project->variables()[src];
1388 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
1389 QString m = Option::fixPathToTargetOS(findMocDestination(*it));
1390 if ( !m.isEmpty()) {
1391 QString deps;
1392 if(!project->isActiveConfig("no_mocdepend"))
1393 deps += "$(MOC) ";
1394 deps += (*it);
1395 t << m << ": " << deps << "\n\t"
1396 << "$(MOC) " << (*it) << " -o " << m << endl << endl;
1397 }
1398 }
1399}
1400
1401void
1402MakefileGenerator::writeYaccSrc(QTextStream &t, const QString &src)
1403{
1404 QStringList &l = project->variables()[src];
1405 if(project->isActiveConfig("yacc_no_name_mangle") && l.count() > 1)
1406 warn_msg(WarnLogic, "yacc_no_name_mangle specified, but multiple parsers expected."
1407 "This can lead to link problems.\n");
1408 QString default_out_h = "y.tab.h", default_out_c = "y.tab.c";
1409 if(!project->isEmpty("QMAKE_YACC_HEADER"))
1410 default_out_h = project->first("QMAKE_YACC_HEADER");
1411 if(!project->isEmpty("QMAKE_YACC_SOURCE"))
1412 default_out_c = project->first("QMAKE_YACC_SOURCE");
1413 QString stringBase("$base");
1414 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
1415 QFileInfo fi((*it));
1416 QString dir = fileFixify(Option::output_dir);
1417 if(!dir.isEmpty() && dir.right(Option::dir_sep.length()) != Option::dir_sep)
1418 dir += Option::dir_sep;
1419 QString impl = dir + fi.baseName(TRUE) + Option::yacc_mod + Option::cpp_ext.first();
1420 QString decl = dir + fi.baseName(TRUE) + Option::yacc_mod + Option::h_ext.first();
1421
1422 QString yaccflags = "$(YACCFLAGS)", mangle = "y";
1423 if(!project->isActiveConfig("yacc_no_name_mangle")) {
1424 mangle = fi.baseName(TRUE);
1425 yaccflags += " -p " + mangle;
1426 }
1427 QString out_h = default_out_h, out_c = default_out_c;
1428 if(!mangle.isEmpty()) {
1429 out_h.replace(stringBase, mangle);
1430 out_c.replace(stringBase, mangle);
1431 }
1432
1433 t << impl << ": " << (*it) << "\n\t"
1434 << "$(YACC) " << yaccflags << " " << (*it) << "\n\t"
1435 << "-$(DEL_FILE) " << impl << " " << decl << "\n\t"
1436 << "-$(MOVE) " << out_h << " " << decl << "\n\t"
1437 << "-$(MOVE) " << out_c << " " << impl << endl << endl;
1438 t << decl << ": " << impl << endl << endl;
1439 }
1440}
1441
1442void
1443MakefileGenerator::writeLexSrc(QTextStream &t, const QString &src)
1444{
1445 QStringList &l = project->variables()[src];
1446 if(project->isActiveConfig("yacc_no_name_mangle") && l.count() > 1)
1447 warn_msg(WarnLogic, "yacc_no_name_mangle specified, but multiple parsers expected.\n"
1448 "This can lead to link problems.\n");
1449 QString default_out_c = "lex.$base.c";
1450 if(!project->isEmpty("QMAKE_LEX_SOURCE"))
1451 default_out_c = project->first("QMAKE_LEX_SOURCE");
1452 QString stringBase("$base");
1453 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
1454 QFileInfo fi((*it));
1455 QString dir = fileFixify(Option::output_dir);
1456 if(!dir.isEmpty() && dir.right(Option::dir_sep.length()) != Option::dir_sep)
1457 dir += Option::dir_sep;
1458 QString impl = dir + fi.baseName(TRUE) + Option::lex_mod + Option::cpp_ext.first();
1459
1460 QString lexflags = "$(LEXFLAGS)", stub="yy";
1461 if(!project->isActiveConfig("yacc_no_name_mangle")) {
1462 stub = fi.baseName(TRUE);
1463 lexflags += " -P" + stub;
1464 }
1465 QString out_c = default_out_c;
1466 if(!stub.isEmpty())
1467 out_c.replace(stringBase, stub);
1468
1469 t << impl << ": " << (*it) << " " << findDependencies((*it)).join(" \\\n\t\t") << "\n\t"
1470 << ( "$(LEX) " + lexflags + " " ) << (*it) << "\n\t"
1471 << "-$(DEL_FILE) " << impl << " " << "\n\t"
1472 << "-$(MOVE) " << out_c << " " << impl << endl << endl;
1473 }
1474}
1475
1476void
1477MakefileGenerator::writeImageObj(QTextStream &t, const QString &obj)
1478{
1479 QStringList &objl = project->variables()[obj];
1480 QString stringSrc("$src");
1481 QString stringObj("$obj");
1482
1483 QString uidir;
1484 for(QStringList::Iterator oit = objl.begin(); oit != objl.end(); oit++) {
1485 QString src(project->first("QMAKE_IMAGE_COLLECTION"));
1486 t << (*oit) << ": " << src;
1487 bool use_implicit_rule = !project->isEmpty("QMAKE_RUN_CXX_IMP");
1488 if(use_implicit_rule) {
1489 if(!project->isEmpty("OBJECTS_DIR") || !project->isEmpty("UI_DIR") || !project->isEmpty("UI_SOURCES_DIR")) {
1490 use_implicit_rule = FALSE;
1491 } else {
1492 int dot = src.findRev('.');
1493 if(dot == -1 || (src.left(dot) + Option::obj_ext != (*oit)))
1494 use_implicit_rule = FALSE;
1495 }
1496 }
1497 if(!use_implicit_rule) {
1498 QString p = var("QMAKE_RUN_CXX");
1499 p.replace( stringSrc, src);
1500 p.replace( stringObj, (*oit));
1501 t << "\n\t" << p;
1502 }
1503 t << endl << endl;
1504 }
1505}
1506
1507
1508void
1509MakefileGenerator::writeImageSrc(QTextStream &t, const QString &src)
1510{
1511 QStringList &l = project->variables()[src];
1512 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
1513 QString gen = project->first("MAKEFILE_GENERATOR");
1514 if ( gen == "MSVC" ) {
1515 t << (*it) << ": " << findDependencies((*it)).join(" \\\n\t\t") << "\n\t"
1516 << "$(UIC) -o " << (*it) << " -embed " << project->first("QMAKE_ORIG_TARGET")
1517 << " -f <<\n" << findDependencies((*it)).join(" ") << "\n<<" << endl << endl;
1518 } else if ( gen == "BMAKE" ) {
1519 t << (*it) << ": " << findDependencies((*it)).join(" \\\n\t\t") << "\n\t"
1520 << "$(UIC) " << " -embed " << project->first("QMAKE_ORIG_TARGET")
1521 << " -f &&|\n" << findDependencies((*it)).join(" ") << "\n| -o " << (*it) << endl << endl;
1522 } else {
1523 t << (*it) << ": " << findDependencies((*it)).join(" \\\n\t\t") << "\n\t"
1524 << "$(UIC) " << " -embed " << project->first("QMAKE_ORIG_TARGET")
1525 << " " << findDependencies((*it)).join(" ") << " -o " << (*it) << endl << endl;
1526 }
1527 }
1528}
1529
1530
1531void
1532MakefileGenerator::writeInstalls(QTextStream &t, const QString &installs)
1533{
1534 QString all_installs, all_uninstalls;
1535 QStringList &l = project->variables()[installs];
1536 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
1537 QString pvar = (*it) + ".path";
1538 if(project->variables()[pvar].isEmpty()) {
1539 warn_msg(WarnLogic, "%s is not defined: install target not created\n", pvar.latin1());
1540 continue;
1541 }
1542
1543 bool do_default = TRUE;
1544 QString target, dst="$(INSTALL_ROOT)" + Option::fixPathToTargetOS(project->variables()[pvar].first(), FALSE);
1545 if(dst.right(1) != Option::dir_sep)
1546 dst += Option::dir_sep;
1547 QStringList tmp, &uninst = project->variables()[(*it) + ".uninstall"];
1548 //other
1549 tmp = project->variables()[(*it) + ".extra"];
1550 if(!tmp.isEmpty()) {
1551 do_default = FALSE;
1552 if(!target.isEmpty())
1553 target += "\n\t";
1554 target += tmp.join(" ");
1555 }
1556 //masks
1557 tmp = project->variables()[(*it) + ".files"];
1558 if(!tmp.isEmpty()) {
1559 if(!target.isEmpty())
1560 target += "\n";
1561 do_default = FALSE;
1562 for(QStringList::Iterator wild_it = tmp.begin(); wild_it != tmp.end(); ++wild_it) {
1563 QString wild = Option::fixPathToLocalOS((*wild_it), FALSE), wild_var = fileFixify(wild);
1564 if(QFile::exists(wild)) { //real file
1565 QFileInfo fi(wild);
1566 target += QString("\t-") + (fi.isDir() ? "$(COPY_DIR)" : "$(COPY_FILE)") +
1567 " \"" + Option::fixPathToTargetOS(fileFixify(wild), FALSE) + "\" \"" + fileFixify(dst) + "\"\n";
1568 if(!project->isActiveConfig("debug") &&
1569 !fi.isDir() && fi.isExecutable() && !project->isEmpty("QMAKE_STRIP"))
1570 target += QString("\t") + var("QMAKE_STRIP") + " \"" + fileFixify(dst + wild) + "\"\n";
1571 uninst.append(QString("-$(DEL_FILE) -r") + " \"" + fileFixify(dst + wild) + "\"");
1572 continue;
1573 }
1574 QString dirstr = QDir::currentDirPath(), f = wild; //wild
1575 int slsh = f.findRev(Option::dir_sep);
1576 if(slsh != -1) {
1577 dirstr = f.left(slsh+1);
1578 f = f.right(f.length() - slsh - 1);
1579 }
1580 if(dirstr.right(Option::dir_sep.length()) != Option::dir_sep)
1581 dirstr += Option::dir_sep;
1582 if(!uninst.isEmpty())
1583 uninst.append("\n\t");
1584 uninst.append(QString("-$(DEL_FILE) -r") + " " + fileFixify(dst + f) + "");
1585
1586 QDir dir(dirstr, f);
1587 for(uint x = 0; x < dir.count(); x++) {
1588 QString file = dir[x];
1589 if(file == "." || file == "..") //blah
1590 continue;
1591 QFileInfo fi(file);
1592 target += QString("\t-") + (fi.isDir() ? "$(COPY_DIR)" : "$(COPY_FILE)") +
1593 " \"" + Option::fixPathToTargetOS(fileFixify(dirstr + file), FALSE) +
1594 "\" \"" + fileFixify(dst) + "\"\n";
1595 if(!project->isActiveConfig("debug") &&
1596 !fi.isDir() && fi.isExecutable() && !project->isEmpty("QMAKE_STRIP"))
1597 target += QString("\t") + var("QMAKE_STRIP") + " \"" + fileFixify(dst + file) + "\"\n";
1598 }
1599 }
1600 }
1601 //default?
1602 if(do_default)
1603 target = defaultInstall((*it));
1604
1605 if(!target.isEmpty()) {
1606 t << "install_" << (*it) << ": " << "\n\t"
1607 << "@test -d " << dst << " || mkdir -p " << dst << "\n\t"
1608 << target << endl << endl;
1609 all_installs += QString("install_") + (*it) + " ";
1610 if(!uninst.isEmpty()) {
1611 t << "uninstall_" << (*it) << ": " << "\n\t"
1612 << uninst.join(" ") << "\n\t"
1613 << "-$(DEL_DIR) \"" << dst << "\"" << endl << endl;
1614 all_uninstalls += "uninstall_" + (*it) + " ";
1615 }
1616 t << endl;
1617 } else {
1618 debug_msg(1, "no definition for install %s: install target not created",(*it).latin1());
1619 }
1620 }
1621 t << "install: all " << all_installs << "\n\n";
1622 t << "uninstall: " << all_uninstalls << "\n\n";
1623}
1624
1625QString
1626MakefileGenerator::var(const QString &var)
1627{
1628 return val(project->variables()[var]);
1629}
1630
1631QString
1632MakefileGenerator::val(const QStringList &varList)
1633{
1634 return valGlue(varList, "", " ", "");
1635}
1636
1637QString
1638MakefileGenerator::varGlue(const QString &var, const QString &before, const QString &glue, const QString &after)
1639{
1640 return valGlue(project->variables()[var], before, glue, after);
1641}
1642
1643QString
1644MakefileGenerator::valGlue(const QStringList &varList, const QString &before, const QString &glue, const QString &after)
1645{
1646 QString ret;
1647 for(QStringList::ConstIterator it = varList.begin(); it != varList.end(); ++it) {
1648 if(!(*it).isEmpty()) {
1649 if(!ret.isEmpty())
1650 ret += glue;
1651 ret += (*it);
1652 }
1653 }
1654 return ret.isEmpty() ? QString("") : before + ret + after;
1655}
1656
1657
1658QString
1659MakefileGenerator::varList(const QString &var)
1660{
1661 return valList(project->variables()[var]);
1662}
1663
1664QString
1665MakefileGenerator::valList(const QStringList &varList)
1666{
1667 return valGlue(varList, "", " \\\n\t\t", "");
1668}
1669
1670
1671QStringList
1672MakefileGenerator::createObjectList(const QString &var)
1673{
1674 QStringList &l = project->variables()[var], ret;
1675 QString objdir, dir;
1676 if(!project->variables()["OBJECTS_DIR"].isEmpty())
1677 objdir = project->first("OBJECTS_DIR");
1678 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
1679 QFileInfo fi(Option::fixPathToLocalOS((*it)));
1680 if(objdir.isEmpty() && project->isActiveConfig("object_with_source")) {
1681 QString fName = Option::fixPathToTargetOS((*it), FALSE);
1682 int dl = fName.findRev(Option::dir_sep);
1683 if(dl != -1)
1684 dir = fName.left(dl + 1);
1685 } else {
1686 dir = objdir;
1687 }
1688 ret.append(dir + fi.baseName(TRUE) + Option::obj_ext);
1689 }
1690 return ret;
1691}
1692
1693bool
1694MakefileGenerator::writeMakefile(QTextStream &t)
1695{
1696 t << "####### Compile" << endl << endl;
1697 writeObj(t, "OBJECTS", "SOURCES");
1698 writeUicSrc(t, "FORMS");
1699 writeObj(t, "UICOBJECTS", "UICIMPLS");
1700 writeMocObj(t, "OBJMOC", "SRCMOC" );
1701 writeMocSrc(t, "HEADERS");
1702 writeMocSrc(t, "SOURCES");
1703 writeMocSrc(t, "UICDECLS");
1704 writeYaccSrc(t, "YACCSOURCES");
1705 writeLexSrc(t, "LEXSOURCES");
1706 writeImageObj(t, "IMAGEOBJECTS");
1707 writeImageSrc(t, "QMAKE_IMAGE_COLLECTION");
1708
1709 t << "####### Install" << endl << endl;
1710 writeInstalls(t, "INSTALLS");
1711 return TRUE;
1712}
1713
1714QString MakefileGenerator::buildArgs()
1715{
1716 static QString ret;
1717 if(ret.isEmpty()) {
1718 //special variables
1719 if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH"))
1720 ret += " QMAKE_ABSOLUTE_SOURCE_PATH=\"" + project->first("QMAKE_ABSOLUTE_SOURCE_PATH") + "\"";
1721
1722 //warnings
1723 else if(Option::warn_level == WarnNone)
1724 ret += " -Wnone";
1725 else if(Option::warn_level == WarnAll)
1726 ret += " -Wall";
1727 else if(Option::warn_level & WarnParser)
1728 ret += " -Wparser";
1729 //other options
1730 if(!Option::user_template.isEmpty())
1731 ret += " -t " + Option::user_template;
1732 if(!Option::mkfile::do_cache)
1733 ret += " -nocache";
1734 if(!Option::mkfile::do_deps)
1735 ret += " -nodepend";
1736 if(!Option::mkfile::do_mocs)
1737 ret += " -nomoc";
1738 if(!Option::mkfile::do_dep_heuristics)
1739 ret += " -nodependheuristics";
1740 if(!Option::mkfile::qmakespec_commandline.isEmpty())
1741 ret += " -spec " + Option::mkfile::qmakespec_commandline;
1742
1743 //arguments
1744 for(QStringList::Iterator it = Option::before_user_vars.begin();
1745 it != Option::before_user_vars.end(); ++it) {
1746 if((*it).left(qstrlen("QMAKE_ABSOLUTE_SOURCE_PATH")) != "QMAKE_ABSOLUTE_SOURCE_PATH")
1747 ret += " \"" + (*it) + "\"";
1748 }
1749 if(Option::after_user_vars.count()) {
1750 ret += " -after ";
1751 for(QStringList::Iterator it = Option::after_user_vars.begin();
1752 it != Option::after_user_vars.end(); ++it) {
1753 if((*it).left(qstrlen("QMAKE_ABSOLUTE_SOURCE_PATH")) != "QMAKE_ABSOLUTE_SOURCE_PATH")
1754 ret += " \"" + (*it) + "\"";
1755 }
1756 }
1757 }
1758 return ret;
1759}
1760
1761//could get stored argv, but then it would have more options than are
1762//probably necesary this will try to guess the bare minimum..
1763QString MakefileGenerator::build_args()
1764{
1765 static QString ret;
1766 if(ret.isEmpty()) {
1767 ret = "$(QMAKE)";
1768
1769 // general options and arguments
1770 ret += buildArgs();
1771
1772 //output
1773 QString ofile = Option::fixPathToTargetOS(fileFixify(Option::output.name()));
1774 if (!ofile.isEmpty() && ofile != project->first("QMAKE_MAKEFILE"))
1775 ret += " -o " + ofile;
1776
1777 //inputs
1778 QStringList files = fileFixify(Option::mkfile::project_files);
1779 ret += " " + files.join(" ");
1780 }
1781 return ret;
1782}
1783
1784bool
1785MakefileGenerator::writeHeader(QTextStream &t)
1786{
1787 time_t foo = time(NULL);
1788 t << "#############################################################################" << endl;
1789 t << "# Makefile for building: " << var("TARGET") << endl;
1790 t << "# Generated by qmake (" << qmake_version() << ") on: " << ctime(&foo);
1791 t << "# Project: " << fileFixify(project->projectFile()) << endl;
1792 t << "# Template: " << var("TEMPLATE") << endl;
1793 t << "# Command: " << build_args() << endl;
1794 t << "#############################################################################" << endl;
1795 t << endl;
1796 return TRUE;
1797}
1798
1799
1800//makes my life easier..
1801bool
1802MakefileGenerator::writeMakeQmake(QTextStream &t)
1803{
1804 QString ofile = Option::fixPathToTargetOS(fileFixify(Option::output.name()));
1805 if(project->isEmpty("QMAKE_FAILED_REQUIREMENTS") &&
1806 !project->isEmpty("QMAKE_INTERNAL_PRL_FILE")) {
1807 QStringList files = fileFixify(Option::mkfile::project_files);
1808 t << project->first("QMAKE_INTERNAL_PRL_FILE") << ": " << "\n\t"
1809 << "@$(QMAKE) -prl " << buildArgs() << " " << files.join(" ") << endl;
1810 }
1811
1812 QString pfile = project->projectFile();
1813 if(pfile != "(stdin)") {
1814 QString qmake = build_args();
1815 if(!ofile.isEmpty() && !project->isActiveConfig("no_autoqmake")) {
1816 t << ofile << ": " << fileFixify(pfile) << " ";
1817 if(Option::mkfile::do_cache)
1818 t << fileFixify(Option::mkfile::cachefile) << " ";
1819 if(!specdir().isEmpty())
1820 t << specdir() << Option::dir_sep << "qmake.conf" << " ";
1821 t << project->variables()["QMAKE_INTERNAL_INCLUDED_FILES"].join(" \\\n\t\t") << "\n\t"
1822 << qmake <<endl;
1823 }
1824 if(project->first("QMAKE_ORIG_TARGET") != "qmake") {
1825 t << "qmake: " <<
1826 project->variables()["QMAKE_INTERNAL_QMAKE_DEPS"].join(" \\\n\t\t") << "\n\t"
1827 << "@" << qmake << endl << endl;
1828 }
1829 }
1830 return TRUE;
1831}
1832
1833QStringList
1834MakefileGenerator::fileFixify(const QStringList& files, const QString &out_dir, const QString &in_dir, bool force_fix) const
1835{
1836 if(files.isEmpty())
1837 return files;
1838 QStringList ret;
1839 for(QStringList::ConstIterator it = files.begin(); it != files.end(); ++it) {
1840 if(!(*it).isEmpty())
1841 ret << fileFixify((*it), out_dir, in_dir, force_fix);
1842 }
1843 return ret;
1844}
1845
1846QString
1847MakefileGenerator::fileFixify(const QString& file0, const QString &out_d, const QString &in_d, bool force_fix) const
1848{
1849 QString file = file0;
1850 if(file.isEmpty())
1851 return file;
1852 int depth = 4;
1853 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
1854 Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
1855 if(project && !project->isEmpty("QMAKE_PROJECT_DEPTH"))
1856 depth = project->first("QMAKE_PROJECT_DEPTH").toInt();
1857 else if(Option::mkfile::cachefile_depth != -1)
1858 depth = Option::mkfile::cachefile_depth;
1859 }
1860
1861 QChar quote;
1862 if((file.startsWith("'") || file.startsWith("\"")) && file.startsWith(file.right(1))) {
1863 quote = file.at(0);
1864 file = file.mid(1, file.length() - 2);
1865 }
1866 QString orig_file = file;
1867 if(!force_fix && project->isActiveConfig("no_fixpath")) {
1868 if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH")) { //absoluteify it
1869 QString qfile = Option::fixPathToLocalOS(file);
1870 if(QDir::isRelativePath(file)) { //already absolute
1871 QFileInfo fi(qfile);
1872 if(!fi.convertToAbs()) //strange
1873 file = fi.filePath();
1874 }
1875 }
1876 } else { //fix it..
1877 QString qfile(Option::fixPathToLocalOS(file, TRUE)), in_dir(in_d), out_dir(out_d);
1878 {
1879 if(out_dir.isNull())
1880 out_dir = Option::output_dir;
1881 if(out_dir == ".")
1882 out_dir = QDir::currentDirPath();
1883 if(in_dir.isEmpty() || in_dir == ".")
1884 in_dir = QDir::currentDirPath();
1885 if(!QDir::isRelativePath(in_dir) || !QDir::isRelativePath(out_dir)) {
1886 QFileInfo in_fi(in_dir);
1887 if(!in_fi.convertToAbs())
1888 in_dir = in_fi.filePath();
1889 QFileInfo out_fi(out_dir);
1890 if(!out_fi.convertToAbs())
1891 out_dir = out_fi.filePath();
1892 }
1893 }
1894 if(out_dir != in_dir || !QDir::isRelativePath(qfile)) {
1895 if(QDir::isRelativePath(qfile)) {
1896 if(file.left(Option::dir_sep.length()) != Option::dir_sep &&
1897 in_dir.right(Option::dir_sep.length()) != Option::dir_sep)
1898 file.prepend(Option::dir_sep);
1899 file.prepend(in_dir);
1900 }
1901 file = Option::fixPathToTargetOS(file, FALSE);
1902 QString match_dir = Option::fixPathToTargetOS(out_dir, FALSE);
1903 if(file == match_dir) {
1904 file = "";
1905 } else if(file.startsWith(match_dir) &&
1906 file.mid(match_dir.length(), Option::dir_sep.length()) == Option::dir_sep) {
1907 file = file.right(file.length() - (match_dir.length() + 1));
1908 } else {
1909 for(int i = 1; i <= depth; i++) {
1910 int sl = match_dir.findRev(Option::dir_sep);
1911 if(sl == -1)
1912 break;
1913 match_dir = match_dir.left(sl);
1914 if(match_dir.isEmpty())
1915 break;
1916 if(file.startsWith(match_dir) &&
1917 file.mid(match_dir.length(), Option::dir_sep.length()) == Option::dir_sep) {
1918 //concat
1919 int remlen = file.length() - (match_dir.length() + 1);
1920 if (remlen < 0)
1921 remlen = 0;
1922 file = file.right(remlen);
1923 //prepend
1924 for(int o = 0; o < i; o++)
1925 file.prepend(".." + Option::dir_sep);
1926 }
1927 }
1928 }
1929 }
1930 }
1931 file = Option::fixPathToTargetOS(file, FALSE);
1932 if(!quote.isNull())
1933 file = quote + file + quote;
1934 debug_msg(3, "Fixed %s :: to :: %s (%d)", orig_file.latin1(), file.latin1(), depth);
1935 return file;
1936}
1937
1938QString
1939MakefileGenerator::cleanFilePath(const QString &file) const
1940{
1941 return fileFixify(Option::fixPathToTargetOS(file));
1942}
1943
1944void MakefileGenerator::logicWarn(const QString &f, const QString &w)
1945{
1946 if(!(Option::warn_level & WarnLogic))
1947 return;
1948 QString file = f;
1949 int slsh = f.findRev(Option::dir_sep);
1950 if(slsh != -1)
1951 file = file.right(file.length() - slsh - 1);
1952 QStringList &l = project->variables()[w];
1953 for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) {
1954 QString file2((*val_it));
1955 slsh = file2.findRev(Option::dir_sep);
1956 if(slsh != -1)
1957 file2 = file2.right(file2.length() - slsh - 1);
1958 if(file2 == file) {
1959 warn_msg(WarnLogic, "Found potential symbol conflict of %s (%s) in %s",
1960 file.latin1(), (*val_it).latin1(), w.latin1());
1961 break;
1962 }
1963 }
1964}
1965
1966QStringList
1967&MakefileGenerator::findDependencies(const QString &file)
1968{
1969 QString key = file;
1970 Option::fixPathToTargetOS(key);
1971 if(key.find(Option::dir_sep))
1972 key = key.right(key.length() - key.findRev(Option::dir_sep) - 1);
1973 if(!depKeyMap.contains(key))
1974 depKeyMap.insert(key, file);
1975 return depends[key];
1976}
1977
1978
1979QString
1980MakefileGenerator::specdir()
1981{
1982 if(!spec.isEmpty())
1983 return spec;
1984 spec = Option::mkfile::qmakespec;
1985 const char *d = getenv("QTDIR");
1986 if(d) {
1987 QString qdir = Option::fixPathToTargetOS(QString(d));
1988 if(qdir.endsWith(QString(QChar(QDir::separator()))))
1989 qdir.truncate(qdir.length()-1);
1990 //fix path
1991 QFileInfo fi(spec);
1992 QString absSpec(fi.absFilePath());
1993 absSpec = Option::fixPathToTargetOS(absSpec);
1994 //replace what you can
1995 if(absSpec.startsWith(qdir)) {
1996 absSpec.replace(0, qdir.length(), "$(QTDIR)");
1997 spec = absSpec;
1998 }
1999 }
2000 return spec;
2001}
2002
2003bool
2004MakefileGenerator::openOutput(QFile &file) const
2005{
2006 {
2007 QString outdir;
2008 if(!file.name().isEmpty()) {
2009 QFileInfo fi(file);
2010 if(fi.isDir())
2011 outdir = file.name() + QDir::separator();
2012 }
2013 if(!outdir.isEmpty() || file.name().isEmpty()) {
2014 QString fname = "Makefile";
2015 if(!project->isEmpty("MAKEFILE"))
2016 fname = project->first("MAKEFILE");
2017 file.setName(outdir + fname);
2018 }
2019 }
2020 if(QDir::isRelativePath(file.name()))
2021 file.setName(Option::output_dir + file.name()); //pwd when qmake was run
2022 if(project->isEmpty("QMAKE_MAKEFILE"))
2023 project->variables()["QMAKE_MAKEFILE"].append(file.name());
2024 int slsh = file.name().findRev(Option::dir_sep);
2025 if(slsh != -1)
2026 createDir(file.name().left(slsh));
2027 if(file.open(IO_WriteOnly | IO_Translate)) {
2028 QFileInfo fi(Option::output);
2029 QString od = Option::fixPathToTargetOS((fi.isSymLink() ? fi.readLink() : fi.dirPath()) );
2030 if(QDir::isRelativePath(od))
2031 od.prepend(Option::output_dir);
2032 Option::output_dir = od;
2033 return TRUE;
2034 }
2035 return FALSE;
2036}
2037
2038
2039
2040//Factory thing
2041#include "unixmake.h"
2042#include "borland_bmake.h"
2043#include "msvc_nmake.h"
2044#include "msvc_dsp.h"
2045#include "msvc_vcproj.h"
2046#include "metrowerks_xml.h"
2047#include "pbuilder_pbx.h"
2048#include "projectgenerator.h"
2049
2050MakefileGenerator *
2051MakefileGenerator::create(QMakeProject *proj)
2052{
2053 if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT)
2054 return new ProjectGenerator(proj);
2055
2056 MakefileGenerator *mkfile = NULL;
2057 QString gen = proj->first("MAKEFILE_GENERATOR");
2058 if(gen.isEmpty()) {
2059 fprintf(stderr, "No generator specified in config file: %s\n",
2060 proj->projectFile().latin1());
2061 } else if(gen == "UNIX") {
2062 mkfile = new UnixMakefileGenerator(proj);
2063 } else if(gen == "MSVC") {
2064 // Visual Studio =< v6.0
2065 if(proj->first("TEMPLATE").find(QRegExp("^vc.*")) != -1)
2066 mkfile = new DspMakefileGenerator(proj);
2067 else
2068 mkfile = new NmakeMakefileGenerator(proj);
2069 } else if(gen == "MSVC.NET") {
2070 // Visual Studio >= v7.0
2071 if(proj->first("TEMPLATE").find(QRegExp("^vc.*")) != -1)
2072 mkfile = new VcprojGenerator(proj);
2073 else
2074 mkfile = new NmakeMakefileGenerator(proj);
2075 } else if(gen == "BMAKE") {
2076 mkfile = new BorlandMakefileGenerator(proj);
2077 } else if(gen == "METROWERKS") {
2078 mkfile = new MetrowerksMakefileGenerator(proj);
2079 } else if(gen == "PROJECTBUILDER") {
2080 mkfile = new ProjectBuilderMakefileGenerator(proj);
2081 } else {
2082 fprintf(stderr, "Unknown generator specified: %s\n", gen.latin1());
2083 }
2084 return mkfile;
2085}
diff --git a/qmake/generators/makefile.h b/qmake/generators/makefile.h
new file mode 100644
index 0000000..1d19d98
--- a/dev/null
+++ b/qmake/generators/makefile.h
@@ -0,0 +1,173 @@
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#ifndef __MAKEFILE_H__
38#define __MAKEFILE_H__
39
40#include "option.h"
41#include "project.h"
42#include <qtextstream.h>
43
44class MakefileGenerator
45{
46 QString spec;
47 bool init_opath_already, init_already, moc_aware, no_io;
48 QStringList createObjectList(const QString &var);
49 QString build_args();
50 QMap<QString, QString> depHeuristics, depKeyMap;
51 QMap<QString, QString> mocablesToMOC, mocablesFromMOC;
52 QMap<QString, QStringList> depends;
53
54protected:
55 void writeObj(QTextStream &, const QString &obj, const QString &src);
56 void writeUicSrc(QTextStream &, const QString &ui);
57 void writeMocObj(QTextStream &, const QString &obj, const QString &src);
58 void writeMocSrc(QTextStream &, const QString &src);
59 void writeLexSrc(QTextStream &, const QString &lex);
60 void writeYaccSrc(QTextStream &, const QString &yac);
61 void writeInstalls(QTextStream &t, const QString &installs);
62 void writeImageObj(QTextStream &t, const QString &obj);
63 void writeImageSrc(QTextStream &t, const QString &images);
64
65protected:
66
67 QMakeProject *project;
68
69 class MakefileDependDir {
70 public:
71 MakefileDependDir(QString r, QString l) : real_dir(r), local_dir(l) { }
72 QString real_dir, local_dir;
73 };
74 bool generateDependencies(QPtrList<MakefileDependDir> &dirs, QString x, bool recurse);
75
76 QString buildArgs();
77
78 QString specdir();
79 QString cleanFilePath(const QString &file) const;
80 bool generateMocList(QString fn);
81
82 QString findMocSource(const QString &moc_file) const;
83 QString findMocDestination(const QString &src_file) const;
84 QStringList &findDependencies(const QString &file);
85
86 void setNoIO(bool o);
87 bool noIO() const;
88
89 void setMocAware(bool o);
90 bool mocAware() const;
91 void logicWarn(const QString &, const QString &);
92
93 virtual bool doDepends() const { return Option::mkfile::do_deps; }
94 bool writeHeader(QTextStream &);
95 virtual bool writeMakefile(QTextStream &);
96 virtual bool writeMakeQmake(QTextStream &);
97 void initOutPaths();
98 virtual void init();
99
100 //for installs
101 virtual QString defaultInstall(const QString &);
102
103 //for prl
104 bool processPrlFile(QString &);
105 virtual void processPrlVariable(const QString &, const QStringList &);
106 virtual void processPrlFiles();
107 virtual void writePrlFile(QTextStream &);
108
109 //make sure libraries are found
110 virtual bool findLibraries();
111
112 QString var(const QString &var);
113 QString varGlue(const QString &var, const QString &before, const QString &glue, const QString &after);
114 QString varList(const QString &var);
115 QString val(const QStringList &varList);
116 QString valGlue(const QStringList &varList, const QString &before, const QString &glue, const QString &after);
117 QString valList(const QStringList &varList);
118
119
120 QString fileFixify(const QString& file, const QString &out_dir=QString::null,
121 const QString &in_dir=QString::null, bool force_fix=FALSE) const;
122 QStringList fileFixify(const QStringList& files, const QString &out_dir=QString::null,
123 const QString &in_dir=QString::null, bool force_fix=FALSE) const;
124public:
125 MakefileGenerator(QMakeProject *p);
126 virtual ~MakefileGenerator();
127
128 static MakefileGenerator *create(QMakeProject *);
129 bool write();
130 virtual bool openOutput(QFile &) const;
131};
132
133inline QString MakefileGenerator::findMocSource(const QString &moc_file) const
134{
135 QString tmp = cleanFilePath(moc_file);
136 if (mocablesFromMOC.contains(tmp))
137 return mocablesFromMOC[tmp];
138 else
139 return QString("");
140}
141
142inline QString MakefileGenerator::findMocDestination(const QString &src_file) const
143{
144 QString tmp = cleanFilePath(src_file);
145 if (mocablesToMOC.contains(tmp))
146 return mocablesToMOC[tmp];
147 else
148 return QString("");
149}
150
151inline void MakefileGenerator::setMocAware(bool o)
152{ moc_aware = o; }
153
154inline bool MakefileGenerator::mocAware() const
155{ return moc_aware; }
156
157inline void MakefileGenerator::setNoIO(bool o)
158{ no_io = o; }
159
160inline bool MakefileGenerator::noIO() const
161{ return no_io; }
162
163inline QString MakefileGenerator::defaultInstall(const QString &)
164{ return QString(""); }
165
166inline bool MakefileGenerator::findLibraries()
167{ return TRUE; }
168
169inline MakefileGenerator::~MakefileGenerator()
170{ }
171
172
173#endif /* __MAKEFILE_H__ */
diff --git a/qmake/generators/projectgenerator.cpp b/qmake/generators/projectgenerator.cpp
new file mode 100644
index 0000000..5ff6250
--- a/dev/null
+++ b/qmake/generators/projectgenerator.cpp
@@ -0,0 +1,462 @@
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 "projectgenerator.h"
39#include "option.h"
40#include <qdir.h>
41#include <qfile.h>
42#include <qfileinfo.h>
43#include <qregexp.h>
44
45
46ProjectGenerator::ProjectGenerator(QMakeProject *p) : MakefileGenerator(p), init_flag(FALSE)
47{
48}
49
50void
51ProjectGenerator::init()
52{
53 if(init_flag)
54 return;
55 int file_count = 0;
56 init_flag = TRUE;
57
58 QMap<QString, QStringList> &v = project->variables();
59 QString templ = Option::user_template.isEmpty() ? QString("app") : Option::user_template;
60 if(!Option::user_template_prefix.isEmpty())
61 templ.prepend(Option::user_template_prefix);
62 v["TEMPLATE_ASSIGN"] += templ;
63
64 //figure out target
65 if(Option::output.name() == "-" || Option::output.name().isEmpty())
66 v["TARGET"] = QStringList("unknown");
67
68 //the scary stuff
69 if(project->first("TEMPLATE_ASSIGN") != "subdirs") {
70 QString builtin_regex;
71 { //calculate the builtin regular expression..
72 QStringList builtin_exts(".c");
73 builtin_exts << Option::ui_ext << Option::yacc_ext << Option::lex_ext;
74 builtin_exts += Option::h_ext + Option::cpp_ext;
75 for(QStringList::Iterator ext_it = builtin_exts.begin();
76 ext_it != builtin_exts.end(); ++ext_it) {
77 if(!builtin_regex.isEmpty())
78 builtin_regex += "; ";
79 builtin_regex += QString("*") + (*ext_it);
80 }
81 }
82 QStringList dirs = Option::projfile::project_dirs;
83 if(Option::projfile::do_pwd)
84 dirs.prepend(QDir::currentDirPath());
85
86 for(QStringList::Iterator pd = dirs.begin(); pd != dirs.end(); pd++) {
87 QString dir, regex;
88 bool add_depend = FALSE;
89 if(QFile::exists((*pd))) {
90 QFileInfo fi((*pd));
91 if(fi.isDir()) {
92 dir = (*pd);
93 add_depend = TRUE;
94 if(dir.right(1) != Option::dir_sep)
95 dir += Option::dir_sep;
96 if(Option::projfile::do_recursive) {
97 QDir d(dir);
98 d.setFilter(QDir::Dirs);
99 for(int i = 0; i < (int)d.count(); i++) {
100 if(d[i] != "." && d[i] != "..")
101 dirs.append(dir + d[i] + QDir::separator() + builtin_regex);
102 }
103 }
104 regex = builtin_regex;
105 } else {
106 QString file = (*pd);
107 int s = file.findRev(Option::dir_sep);
108 if(s != -1)
109 dir = file.left(s+1);
110 if(addFile(file)) {
111 add_depend = TRUE;
112 file_count++;
113 }
114 }
115 } else { //regexp
116 regex = (*pd);
117 }
118 if(!regex.isEmpty()) {
119 int s = regex.findRev(Option::dir_sep);
120 if(s != -1) {
121 dir = regex.left(s+1);
122 regex = regex.right(regex.length() - (s+1));
123 }
124 if(Option::projfile::do_recursive) {
125 QDir d(dir);
126 d.setFilter(QDir::Dirs);
127 for(int i = 0; i < (int)d.count(); i++) {
128 if(d[i] != "." && d[i] != "..")
129 dirs.append(dir + d[i] + QDir::separator() + regex);
130 }
131 }
132 QDir d(dir, regex);
133 for(int i = 0; i < (int)d.count(); i++) {
134 QString file = dir + d[i];
135 if (addFile(file)) {
136 add_depend = TRUE;
137 file_count++;
138 }
139 }
140 }
141 if(add_depend && !dir.isEmpty() && !v["DEPENDPATH"].contains(dir)) {
142 QFileInfo fi(dir);
143 if(fi.absFilePath() != QDir::currentDirPath()) {
144 v["DEPENDPATH"] += fileFixify(dir);
145 }
146 }
147 }
148 }
149 if(!file_count) { //shall we try a subdir?
150 QStringList dirs = Option::projfile::project_dirs;
151 if(Option::projfile::do_pwd)
152 dirs.prepend(".");
153 for(QStringList::Iterator pd = dirs.begin(); pd != dirs.end(); pd++) {
154 if(QFile::exists((*pd))) {
155 QString newdir = (*pd);
156 QFileInfo fi(newdir);
157 if(fi.isDir()) {
158 newdir = fileFixify(newdir);
159 QStringList &subdirs = v["SUBDIRS"];
160 if(QFile::exists(fi.filePath() + QDir::separator() + fi.fileName() + ".pro") &&
161 !subdirs.contains(newdir)) {
162 subdirs.append(newdir);
163 } else {
164 QDir d(newdir, "*.pro");
165 d.setFilter(QDir::Files);
166 for(int i = 0; i < (int)d.count(); i++) {
167 QString nd = newdir + QDir::separator() + d[i];
168 fileFixify(nd);
169 if(d[i] != "." && d[i] != ".." && !subdirs.contains(nd)) {
170 if(newdir + d[i] != Option::output_dir + Option::output.name())
171 subdirs.append(nd);
172 }
173 }
174 }
175 if(Option::projfile::do_recursive) {
176 QDir d(newdir);
177 d.setFilter(QDir::Dirs);
178 for(int i = 0; i < (int)d.count(); i++) {
179 QString nd = fileFixify(newdir + QDir::separator() + d[i]);
180 if(d[i] != "." && d[i] != ".." && !dirs.contains(nd))
181 dirs.append(nd);
182 }
183 }
184 }
185 } else { //regexp
186 QString regx = (*pd), dir;
187 int s = regx.findRev(Option::dir_sep);
188 if(s != -1) {
189 dir = regx.left(s+1);
190 regx = regx.right(regx.length() - (s+1));
191 }
192 QDir d(dir, regx);
193 d.setFilter(QDir::Dirs);
194 QStringList &subdirs = v["SUBDIRS"];
195 for(int i = 0; i < (int)d.count(); i++) {
196 QString newdir(dir + d[i]);
197 QFileInfo fi(newdir);
198 if(fi.fileName() != "." && fi.fileName() != "..") {
199 newdir = fileFixify(newdir);
200 if(QFile::exists(fi.filePath() + QDir::separator() + fi.fileName() + ".pro") &&
201 !subdirs.contains(newdir)) {
202 subdirs.append(newdir);
203 } else {
204 QDir d(newdir, "*.pro");
205 d.setFilter(QDir::Files);
206 for(int i = 0; i < (int)d.count(); i++) {
207 QString nd = newdir + QDir::separator() + d[i];
208 fileFixify(nd);
209 if(d[i] != "." && d[i] != ".." && !subdirs.contains(nd)) {
210 if(newdir + d[i] != Option::output_dir + Option::output.name())
211 subdirs.append(nd);
212 }
213 }
214 }
215 if(Option::projfile::do_recursive && !dirs.contains(newdir))
216 dirs.append(newdir);
217 }
218 }
219 }
220 }
221 v["TEMPLATE_ASSIGN"] = "subdirs";
222 return;
223 }
224
225 QPtrList<MakefileDependDir> deplist;
226 deplist.setAutoDelete(TRUE);
227 {
228 QStringList &d = v["DEPENDPATH"];
229 for(QStringList::Iterator it = d.begin(); it != d.end(); ++it) {
230 QString r = (*it), l = Option::fixPathToLocalOS((*it));
231 deplist.append(new MakefileDependDir(r, l));
232 }
233 }
234 QStringList &h = v["HEADERS"];
235 bool no_qt_files = TRUE;
236 QString srcs[] = { "SOURCES", "YACCSOURCES", "LEXSOURCES", "INTERFACES", QString::null };
237 for(int i = 0; !srcs[i].isNull(); i++) {
238 QStringList &l = v[srcs[i]];
239 for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) {
240 if(generateDependencies(deplist, (*val_it), TRUE)) {
241 QStringList &tmp = findDependencies((*val_it));
242 if(!tmp.isEmpty()) {
243 for(QStringList::Iterator dep_it = tmp.begin(); dep_it != tmp.end(); ++dep_it) {
244 QString file_no_path = (*dep_it).right(
245 (*dep_it).length() - ((*dep_it).findRev(Option::dir_sep)+1));
246 if(no_qt_files && file_no_path.find(QRegExp("^q[a-z_0-9].h$")) != -1)
247 no_qt_files = FALSE;
248 QString h_ext;
249 for(QStringList::Iterator hit = Option::h_ext.begin(); hit != Option::h_ext.end(); ++hit) {
250 if((*dep_it).endsWith((*hit))) {
251 h_ext = (*hit);
252 break;
253 }
254 }
255 if(!h_ext.isEmpty()) {
256 if((*dep_it).left(1).lower() == "q") {
257 QString qhdr = (*dep_it).lower();
258 if(file_no_path == "qthread.h")
259 addConfig("thread");
260 }
261 for(QStringList::Iterator cppit = Option::cpp_ext.begin();
262 cppit != Option::cpp_ext.end(); ++cppit) {
263 QString src((*dep_it).left((*dep_it).length() - h_ext.length()) + (*cppit));
264 if(QFile::exists(src)) {
265 bool exists = FALSE;
266 QStringList &srcl = v["SOURCES"];
267 for(QStringList::Iterator src_it = srcl.begin(); src_it != srcl.end(); ++src_it) {
268 if((*src_it).lower() == src.lower()) {
269 exists = TRUE;
270 break;
271 }
272 }
273 if(!exists)
274 srcl.append(src);
275 }
276 }
277 } else if((*dep_it).endsWith(Option::lex_ext) &&
278 file_no_path.startsWith(Option::lex_mod)) {
279 addConfig("lex_included");
280 }
281 if(!h.contains((*dep_it))) {
282 if(generateMocList((*dep_it)) && !findMocDestination((*dep_it)).isEmpty())
283 h += (*dep_it);
284 }
285 }
286 }
287 }
288 }
289 }
290 if(h.isEmpty())
291 addConfig("moc", FALSE);
292
293 //if we find a file that matches an forms it needn't be included in the project
294 QStringList &u = v["INTERFACES"];
295 QString no_ui[] = { "SOURCES", "HEADERS", QString::null };
296 {
297 for(int i = 0; !no_ui[i].isNull(); i++) {
298 QStringList &l = v[no_ui[i]];
299 for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ) {
300 bool found = FALSE;
301 for(QStringList::Iterator ui_it = u.begin(); ui_it != u.end(); ++ui_it) {
302 QString s1 = (*val_it).right((*val_it).length() - ((*val_it).findRev(Option::dir_sep) + 1));
303 if(s1.findRev('.') != -1)
304 s1 = s1.left(s1.findRev('.')) + Option::ui_ext;
305 QString u1 = (*ui_it).right((*ui_it).length() - ((*ui_it).findRev(Option::dir_sep) + 1));
306 if(s1 == u1) {
307 found = TRUE;
308 break;
309 }
310 }
311 if(!found && (*val_it).endsWith(Option::moc_ext))
312 found = TRUE;
313 if(found)
314 val_it = l.remove(val_it);
315 else
316 ++val_it;
317 }
318 }
319 }
320}
321
322
323bool
324ProjectGenerator::writeMakefile(QTextStream &t)
325{
326 t << "######################################################################" << endl;
327 t << "# Automatically generated by qmake (" << qmake_version() << ") " << QDateTime::currentDateTime().toString() << endl;
328 t << "######################################################################" << endl << endl;
329 QStringList::Iterator it;
330 for(it = Option::before_user_vars.begin(); it != Option::before_user_vars.end(); ++it)
331 t << (*it) << endl;
332 t << getWritableVar("TEMPLATE_ASSIGN", FALSE);
333 if(project->first("TEMPLATE_ASSIGN") == "subdirs") {
334 t << endl << "# Directories" << "\n"
335 << getWritableVar("SUBDIRS");
336 } else {
337 t << getWritableVar("TARGET")
338 << getWritableVar("CONFIG", FALSE)
339 << getWritableVar("CONFIG_REMOVE", FALSE)
340 << getWritableVar("DEPENDPATH") << endl;
341
342 t << "# Input" << "\n";
343 t << getWritableVar("HEADERS")
344 << getWritableVar("INTERFACES")
345 << getWritableVar("LEXSOURCES")
346 << getWritableVar("YACCSOURCES")
347 << getWritableVar("SOURCES");
348 }
349 for(it = Option::after_user_vars.begin(); it != Option::after_user_vars.end(); ++it)
350 t << (*it) << endl;
351 return TRUE;
352}
353
354bool
355ProjectGenerator::addConfig(const QString &cfg, bool add)
356{
357 QString where = "CONFIG";
358 if(!add)
359 where = "CONFIG_REMOVE";
360 if(!project->variables()[where].contains(cfg)) {
361 project->variables()[where] += cfg;
362 return TRUE;
363 }
364 return FALSE;
365}
366
367
368bool
369ProjectGenerator::addFile(QString file)
370{
371 file = fileFixify(file, QDir::currentDirPath());
372 QString dir;
373 int s = file.findRev(Option::dir_sep);
374 if(s != -1)
375 dir = file.left(s+1);
376 if(file.mid(dir.length(), Option::moc_mod.length()) == Option::moc_mod)
377 return FALSE;
378
379 QString where;
380 for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) {
381 if(file.endsWith((*cppit))) {
382 if(QFile::exists(file.left(file.length() - (*cppit).length()) + Option::ui_ext))
383 return FALSE;
384 else
385 where = "SOURCES";
386 break;
387 }
388 }
389 if(where.isEmpty()) {
390 for(QStringList::Iterator hit = Option::h_ext.begin(); hit != Option::h_ext.end(); ++hit) {
391 if(file.endsWith((*hit))) {
392 where = "HEADERS";
393 break;
394 }
395 }
396 }
397 if(where.isEmpty()) {
398 if(file.endsWith(Option::ui_ext))
399 where = "INTERFACES";
400 else if(file.endsWith(".c"))
401 where = "SOURCES";
402 else if(file.endsWith(Option::lex_ext))
403 where = "LEXSOURCES";
404 else if(file.endsWith(Option::yacc_ext))
405 where = "YACCSOURCES";
406 }
407
408 QString newfile = fileFixify(file);
409 if(!where.isEmpty() && !project->variables()[where].contains(file)) {
410 project->variables()[where] += newfile;
411 return TRUE;
412 }
413 return FALSE;
414}
415
416
417QString
418ProjectGenerator::getWritableVar(const QString &v, bool /*fixPath*/)
419{
420 QStringList &vals = project->variables()[v];
421 if(vals.isEmpty())
422 return "";
423
424 QString ret;
425 if(v.endsWith("_REMOVE"))
426 ret = v.left(v.length() - 7) + " -= ";
427 else if(v.endsWith("_ASSIGN"))
428 ret = v.left(v.length() - 7) + " = ";
429 else
430 ret = v + " += ";
431 QString join = vals.join(" ");
432 if(ret.length() + join.length() > 80) {
433 QString spaces;
434 for(unsigned int i = 0; i < ret.length(); i++)
435 spaces += " ";
436 join = vals.join(" \\\n" + spaces);
437 }
438 // ### Commented out for now so that project generation works.
439 // Sam: can you look at why this was needed?
440 /* if(fixPath)
441 join = join.replace("\\", "/");*/
442 return ret + join + "\n";
443}
444
445bool
446ProjectGenerator::openOutput(QFile &file) const
447{
448 QString outdir;
449 if(!file.name().isEmpty()) {
450 QFileInfo fi(file);
451 if(fi.isDir())
452 outdir = fi.dirPath() + QDir::separator();
453 }
454 if(!outdir.isEmpty() || file.name().isEmpty()) {
455 QString dir = QDir::currentDirPath();
456 int s = dir.findRev('/');
457 if(s != -1)
458 dir = dir.right(dir.length() - (s + 1));
459 file.setName(outdir + dir + ".pro");
460 }
461 return MakefileGenerator::openOutput(file);
462}
diff --git a/qmake/generators/projectgenerator.h b/qmake/generators/projectgenerator.h
new file mode 100644
index 0000000..055a784
--- a/dev/null
+++ b/qmake/generators/projectgenerator.h
@@ -0,0 +1,61 @@
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#ifndef __PROJECTGENERATOR_H__
38#define __PROJECTGENERATOR_H__
39
40#include "makefile.h"
41
42class ProjectGenerator : public MakefileGenerator
43{
44 bool init_flag;
45 bool addFile(QString);
46 bool addConfig(const QString &, bool add=TRUE);
47 QString getWritableVar(const QString &, bool fixPath=TRUE);
48protected:
49 virtual void init();
50 virtual bool writeMakefile(QTextStream &);
51public:
52 ProjectGenerator(QMakeProject *p);
53 ~ProjectGenerator();
54 virtual bool openOutput(QFile &) const;
55};
56
57inline ProjectGenerator::~ProjectGenerator()
58{ }
59
60
61#endif /* __PROJECTGENERATOR_H__ */
diff --git a/qmake/include/qmake/qconfig.h b/qmake/include/qmake/qconfig.h
new file mode 100644
index 0000000..bba8fbd
--- a/dev/null
+++ b/qmake/include/qmake/qconfig.h
@@ -0,0 +1 @@
/* All features enabled while building qmake */
diff --git a/qmake/include/qmake/qmodules.h b/qmake/include/qmake/qmodules.h
new file mode 100644
index 0000000..ce5fcc7
--- a/dev/null
+++ b/qmake/include/qmake/qmodules.h
@@ -0,0 +1 @@
/* All modules enabled while building qmake */