00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "makefile.h"
00037 #include "option.h"
00038 #include "meta.h"
00039 #include <qdir.h>
00040 #include <qfile.h>
00041 #include <qtextstream.h>
00042 #include <qregexp.h>
00043 #include <qdict.h>
00044 #if defined(Q_OS_UNIX)
00045 #include <unistd.h>
00046 #else
00047 #include <io.h>
00048 #endif
00049 #include <stdio.h>
00050 #include <stdlib.h>
00051 #include <time.h>
00052 #include <fcntl.h>
00053 #include <sys/types.h>
00054 #include <sys/stat.h>
00055
00056
00057 #ifndef S_ISDIR
00058 #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
00059 #endif
00060 #define QMAKE_EOL(x) (x == '\r' || x == '\n')
00061
00062 QString mkdir_p_asstring(const QString &dir)
00063 {
00064 QString ret = "@$(CHK_DIR_EXISTS) \"" + dir + "\" ";
00065 if(Option::target_mode == Option::TARG_WIN_MODE)
00066 ret += "$(MKDIR)";
00067 else
00068 ret += "|| $(MKDIR)";
00069 ret += " \"" + dir + "\"";
00070 return ret;
00071 }
00072
00073 static bool createDir(const QString& fullPath)
00074 {
00075 if(QFile::exists(fullPath))
00076 return FALSE;
00077 QDir dirTmp;
00078 bool ret = TRUE;
00079 QString pathComponent, tmpPath;
00080 QStringList hierarchy = QStringList::split(QString(Option::dir_sep), fullPath, TRUE);
00081 for(QStringList::Iterator it = hierarchy.begin(); it != hierarchy.end(); ++it) {
00082 pathComponent = *it + QDir::separator();
00083 tmpPath += pathComponent;
00084 if(!dirTmp.mkdir(tmpPath)) {
00085 ret = FALSE;
00086
00087 }
00088 }
00089 return ret;
00090 }
00091
00092
00093 MakefileGenerator::MakefileGenerator(QMakeProject *p) : init_opath_already(FALSE),
00094 init_already(FALSE), moc_aware(FALSE),
00095 no_io(FALSE), project(p)
00096 {
00097 }
00098
00099 static char *gimme_buffer(off_t s)
00100 {
00101 static char *big_buffer = NULL;
00102 static int big_buffer_size = 0;
00103 if(!big_buffer || big_buffer_size < s)
00104 big_buffer = (char *)realloc(big_buffer, s);
00105 return big_buffer;
00106 }
00107
00108 bool
00109 MakefileGenerator::generateMocList(const QString &fn_target)
00110 {
00111 if(!findMocDestination(fn_target).isEmpty())
00112 return TRUE;
00113
00114 QString fn_local = Option::fixPathToLocalOS(fileFixify(fn_target, QDir::currentDirPath(), Option::output_dir));
00115
00116 int file = open(fn_local.latin1(), O_RDONLY);
00117 if(file == -1)
00118 return FALSE;
00119
00120 struct stat fst;
00121 if(fstat(file, &fst) || S_ISDIR(fst.st_mode))
00122 return FALSE;
00123 char *big_buffer = gimme_buffer(fst.st_size);
00124
00125 int total_size_read;
00126 for(int have_read = total_size_read = 0;
00127 (have_read = read(file, big_buffer + total_size_read,
00128 fst.st_size - total_size_read));
00129 total_size_read += have_read);
00130 close(file);
00131
00132 bool ignore_qobject = FALSE;
00133 int line_count = 1;
00134
00135 #define COMP_LEN 8 //strlen("Q_OBJECT")
00136 #define OBJ_LEN 8 //strlen("Q_OBJECT")
00137 #define DIS_LEN 10 //strlen("Q_DISPATCH")
00138 int x;
00139 for(x = 0; x < (total_size_read-COMP_LEN); x++) {
00140 if(*(big_buffer + x) == '/') {
00141 x++;
00142 if(total_size_read >= x) {
00143 if(*(big_buffer + x) == '/') {
00144 for( ;x < total_size_read && !QMAKE_EOL(*(big_buffer + x)); x++);
00145 line_count++;
00146 } else if(*(big_buffer + x) == '*') {
00147 for( ;x < total_size_read; x++) {
00148 if(*(big_buffer + x) == 't' || *(big_buffer + x) == 'q') {
00149 if(total_size_read >= (x + 20)) {
00150 if(!strncmp(big_buffer + x + 1, "make ignore Q_OBJECT", 20)) {
00151 debug_msg(2, "Mocgen: %s:%d Found \"qmake ignore Q_OBJECT\"",
00152 fn_target.latin1(), line_count);
00153 x += 20;
00154 ignore_qobject = TRUE;
00155 }
00156 }
00157 } else if(*(big_buffer + x) == '*') {
00158 if(total_size_read >= (x+1) && *(big_buffer + (x+1)) == '/') {
00159 x += 2;
00160 break;
00161 }
00162 } else if(QMAKE_EOL(*(big_buffer + x))) {
00163 line_count++;
00164 }
00165 }
00166 }
00167 }
00168 }
00169 #define SYMBOL_CHAR(x) ((x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z') || \
00170 (x <= '0' && x >= '9') || x == '_')
00171
00172 bool interesting = *(big_buffer+x) == 'Q' && (!strncmp(big_buffer+x, "Q_OBJECT", OBJ_LEN) ||
00173 !strncmp(big_buffer+x, "Q_DISPATCH", DIS_LEN));
00174 if(interesting) {
00175 int len = 0;
00176 if(!strncmp(big_buffer+x, "Q_OBJECT", OBJ_LEN)) {
00177 if(ignore_qobject) {
00178 debug_msg(2, "Mocgen: %s:%d Ignoring Q_OBJECT", fn_target.latin1(), line_count);
00179 interesting = FALSE;
00180 }
00181 len=OBJ_LEN;
00182 } else if(!strncmp(big_buffer+x, "Q_DISPATCH", DIS_LEN)) {
00183 len=DIS_LEN;
00184 }
00185 if(SYMBOL_CHAR(*(big_buffer+x+len)))
00186 interesting = FALSE;
00187 if(interesting) {
00188 *(big_buffer+x+len) = '\0';
00189 debug_msg(2, "Mocgen: %s:%d Found MOC symbol %s", fn_target.latin1(),
00190 line_count, big_buffer+x);
00191
00192 int ext_pos = fn_target.findRev('.');
00193 int ext_len = fn_target.length() - ext_pos;
00194 int dir_pos = fn_target.findRev(Option::dir_sep, ext_pos);
00195 QString mocFile;
00196 if(!project->isEmpty("MOC_DIR"))
00197 mocFile = project->first("MOC_DIR");
00198 else if(dir_pos != -1)
00199 mocFile = fn_target.left(dir_pos+1);
00200
00201 bool cpp_ext = FALSE;
00202 for(QStringList::Iterator cppit = Option::cpp_ext.begin();
00203 cppit != Option::cpp_ext.end(); ++cppit) {
00204 if((cpp_ext = (fn_target.right(ext_len) == (*cppit))))
00205 break;
00206 }
00207 if(cpp_ext) {
00208 mocFile += Option::cpp_moc_mod + fn_target.mid(dir_pos+1, ext_pos - dir_pos-1) + Option::cpp_moc_ext;
00209 project->variables()["_SRCMOC"].append(mocFile);
00210 } else if(project->variables()["HEADERS"].findIndex(fn_target) != -1) {
00211 for(QStringList::Iterator hit = Option::h_ext.begin();
00212 hit != Option::h_ext.end(); ++hit) {
00213 if((fn_target.right(ext_len) == (*hit))) {
00214 mocFile += Option::h_moc_mod + fn_target.mid(dir_pos+1, ext_pos - dir_pos-1) +
00215 Option::h_moc_ext;
00216 logicWarn(mocFile, "SOURCES");
00217 project->variables()["_HDRMOC"].append(mocFile);
00218 break;
00219 }
00220 }
00221 }
00222
00223 if(!mocFile.isEmpty()) {
00224 mocFile = Option::fixPathToTargetOS(mocFile);
00225 mocablesToMOC[cleanFilePath(fn_target)] = mocFile;
00226 mocablesFromMOC[cleanFilePath(mocFile)] = fn_target;
00227 }
00228 break;
00229 }
00230 }
00231
00232 while(x < total_size_read && SYMBOL_CHAR(*(big_buffer+x)))
00233 x++;
00234 if(QMAKE_EOL(*(big_buffer+x)))
00235 line_count++;
00236 }
00237 #undef OBJ_LEN
00238 #undef DIS_LEN
00239 return TRUE;
00240 }
00241
00242 bool
00243 MakefileGenerator::generateDependencies(QPtrList<MakefileDependDir> &dirs, const QString &f, bool recurse)
00244 {
00245 if(processedDependencies(f))
00246 return TRUE;
00247 setProcessedDependencies(f, TRUE);
00248
00249 QStringList &fndeps = findDependencies(f);
00250 QString fn = fileFixify(f, QDir::currentDirPath(), Option::output_dir);
00251 fn = Option::fixPathToLocalOS(fn, FALSE);
00252 QString fix_env_fn = Option::fixPathToLocalOS(fn);
00253 int file = open(fix_env_fn.latin1(), O_RDONLY);
00254 if(file == -1)
00255 return FALSE;
00256 struct stat fst;
00257 if(fstat(file, &fst) || S_ISDIR(fst.st_mode))
00258 return FALSE;
00259
00260 QString fndir, fix_env_fndir;
00261 int dl = fn.findRev(Option::dir_sep);
00262 if(dl != -1)
00263 fndir = fn.left(dl+1);
00264 dl = fix_env_fn.findRev(Option::dir_sep);
00265 if(dl != -1)
00266 fix_env_fndir = fix_env_fn.left(dl + 1);
00267
00268 int line_count = 1;
00269 char *big_buffer = gimme_buffer(fst.st_size);
00270
00271 int total_size_read;
00272 for(int have_read = total_size_read = 0;
00273 (have_read = read(file, big_buffer + total_size_read,
00274 fst.st_size - total_size_read));
00275 total_size_read += have_read);
00276 close(file);
00277
00278 bool ui_file = fn.endsWith(Option::ui_ext);
00279 for(int x = 0; x < total_size_read; x++) {
00280 QStringList *outdeps=&fndeps;
00281 QString inc;
00282 if(!ui_file) {
00283 if(*(big_buffer + x) == '/') {
00284 x++;
00285 if(total_size_read >= x) {
00286 if(*(big_buffer + x) == '/') {
00287 for( ; x < total_size_read && !QMAKE_EOL(*(big_buffer + x)); x++);
00288 } else if(*(big_buffer + x) == '*') {
00289 for( ; x < total_size_read; x++) {
00290 if(*(big_buffer + x) == '*') {
00291 if(total_size_read >= (x+1) && *(big_buffer + (x+1)) == '/') {
00292 x += 2;
00293 break;
00294 }
00295 } else if(QMAKE_EOL(*(big_buffer + x))) {
00296 line_count++;
00297 }
00298 }
00299 }
00300 }
00301 }
00302 while(x < total_size_read &&
00303 (*(big_buffer+x) == ' ' || *(big_buffer+x) == '\t'))
00304 x++;
00305 if(*(big_buffer + x) == '#') {
00306 x++;
00307 while(x < total_size_read &&
00308 (*(big_buffer+x) == ' ' || *(big_buffer+x) == '\t'))
00309 x++;
00310 if(total_size_read >= x + 8 && !strncmp(big_buffer + x, "include", 7) &&
00311 (*(big_buffer + x + 7) == ' ' || *(big_buffer + x + 7) == '\t' ||
00312 *(big_buffer + x + 7) == '<' || *(big_buffer + x + 7) == '"')) {
00313 for(x+=7;
00314 x < total_size_read && (*(big_buffer+x) == ' ' || *(big_buffer+x) == '\t');
00315 x++);
00316 char term = *(big_buffer + x);
00317 if(term == '"');
00318 else if(term == '<')
00319 term = '>';
00320 else
00321 continue;
00322 x++;
00323
00324 int inc_len;
00325 for(inc_len = 0; *(big_buffer + x + inc_len) != term &&
00326 !QMAKE_EOL(*(big_buffer + x + inc_len)); inc_len++);
00327 *(big_buffer + x + inc_len) = '\0';
00328 inc = big_buffer + x;
00329 } else if(total_size_read >= x + 14 && !strncmp(big_buffer + x, "qmake_warning ", 14)) {
00330 for(x+=14;
00331 x < total_size_read && (*(big_buffer+x) == ' ' || *(big_buffer+x) == '\t');
00332 x++);
00333 char term = 0;
00334 if(*(big_buffer + x) == '"')
00335 term = '"';
00336 if(*(big_buffer + x) == '\'')
00337 term = '\'';
00338 if(term)
00339 x++;
00340
00341 int msg_len;
00342 for(msg_len = 0; (term && *(big_buffer + x + msg_len) != term) &&
00343 !QMAKE_EOL(*(big_buffer + x + msg_len)); msg_len++);
00344 const char saved_term = *(big_buffer + x + msg_len);
00345 *(big_buffer + x + msg_len) = '\0';
00346 QString msg = big_buffer + x;
00347 debug_msg(0, "%s:%d qmake_warning -- %s", fix_env_fn.latin1(),
00348 line_count, msg.latin1());
00349 *(big_buffer + x + msg_len) = saved_term;
00350 }
00351 }
00352 } else if(ui_file) {
00353
00354 while(x < total_size_read &&
00355 (*(big_buffer+x) == ' ' || *(big_buffer+x) == '\t'))
00356 x++;
00357 if(*(big_buffer + x) == '<') {
00358 x++;
00359 if(total_size_read >= x + 12 && !strncmp(big_buffer + x, "includehint", 11) &&
00360 (*(big_buffer + x + 11) == ' ' || *(big_buffer + x + 11) == '>')) {
00361 for(x += 11; *(big_buffer + x) != '>'; x++);
00362 int inc_len = 0;
00363 for(x += 1 ; *(big_buffer + x + inc_len) != '<'; inc_len++);
00364 *(big_buffer + x + inc_len) = '\0';
00365 inc = big_buffer + x;
00366 } else if(total_size_read >= x + 13 && !strncmp(big_buffer + x, "customwidget", 12) &&
00367 (*(big_buffer + x + 12) == ' ' || *(big_buffer + x + 12) == '>')) {
00368 for(x += 13; *(big_buffer + x) != '>'; x++);
00369 while(x < total_size_read) {
00370 for(x++; *(big_buffer + x) != '<'; x++);
00371 x++;
00372 if(total_size_read >= x + 7 && !strncmp(big_buffer+x, "header", 6) &&
00373 (*(big_buffer + x + 6) == ' ' || *(big_buffer + x + 6) == '>')) {
00374 for(x += 7; *(big_buffer + x) != '>'; x++);
00375 int inc_len = 0;
00376 for(x += 1 ; *(big_buffer + x + inc_len) != '<'; inc_len++);
00377 *(big_buffer + x + inc_len) = '\0';
00378 inc = big_buffer + x;
00379 break;
00380 } else if(total_size_read >= x + 14 && !strncmp(big_buffer+x, "/customwidget", 13) &&
00381 (*(big_buffer + x + 13) == ' ' || *(big_buffer + x + 13) == '>')) {
00382 x += 14;
00383 break;
00384 }
00385 }
00386 } else if(total_size_read >= x + 8 && !strncmp(big_buffer + x, "include", 7) &&
00387 (*(big_buffer + x + 7) == ' ' || *(big_buffer + x + 7) == '>')) {
00388 for(x += 8; *(big_buffer + x) != '>'; x++) {
00389 if(total_size_read >= x + 9 && *(big_buffer + x) == 'i' &&
00390 !strncmp(big_buffer + x, "impldecl", 8)) {
00391 for(x += 8; *(big_buffer + x) != '='; x++);
00392 if(*(big_buffer + x) != '=')
00393 continue;
00394 for(x++; *(big_buffer+x) == '\t' || *(big_buffer+x) == ' '; x++);
00395 char quote = 0;
00396 if(*(big_buffer+x) == '\'' || *(big_buffer+x) == '"') {
00397 quote = *(big_buffer + x);
00398 x++;
00399 }
00400 int val_len;
00401 for(val_len = 0; TRUE; val_len++) {
00402 if(quote) {
00403 if(*(big_buffer+x+val_len) == quote)
00404 break;
00405 } else if(*(big_buffer + x + val_len) == '>' ||
00406 *(big_buffer + x + val_len) == ' ') {
00407 break;
00408 }
00409 }
00410 char saved = *(big_buffer + x + val_len);
00411 *(big_buffer + x + val_len) = '\0';
00412 QString where = big_buffer + x;
00413 *(big_buffer + x + val_len) = saved;
00414 if(where == "in implementation") {
00415 QString cpp = fn.left(fn.length() - Option::ui_ext.length()) +
00416 Option::cpp_ext.first();
00417 outdeps = &findDependencies(cpp);
00418 }
00419 }
00420 }
00421 int inc_len = 0;
00422 for(x += 1 ; *(big_buffer + x + inc_len) != '<'; inc_len++);
00423 *(big_buffer + x + inc_len) = '\0';
00424 inc = big_buffer + x;
00425 }
00426 }
00427 }
00428
00429 if(!inc.isEmpty()) {
00430 bool from_source_dir = TRUE;
00431 debug_msg(5, "%s:%d Found dependency to %s", fix_env_fn.latin1(),
00432 line_count, inc.latin1());
00433 if(!project->isEmpty("SKIP_DEPENDS")) {
00434 bool found = FALSE;
00435 QStringList &nodeplist = project->values("SKIP_DEPENDS");
00436 for(QStringList::Iterator it = nodeplist.begin();
00437 it != nodeplist.end(); ++it) {
00438 QRegExp regx((*it));
00439 if(regx.search(inc) != -1) {
00440 found = TRUE;
00441 break;
00442 }
00443 }
00444 if(found)
00445 continue;
00446 }
00447 QString fqn;
00448 if(project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH") &&
00449 !stat(fix_env_fndir + inc, &fst) && !S_ISDIR(fst.st_mode)) {
00450 fqn = fndir + inc;
00451 goto handle_fqn;
00452 } else if(project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH") &&
00453 !stat(inc, &fst) && !S_ISDIR(fst.st_mode)) {
00454 fqn = inc;
00455 goto handle_fqn;
00456 } else {
00457 if((Option::target_mode == Option::TARG_MAC9_MODE && inc.find(':')) ||
00458 (Option::target_mode == Option::TARG_WIN_MODE && inc[1] != ':') ||
00459 ((Option::target_mode == Option::TARG_UNIX_MODE ||
00460 Option::target_mode == Option::TARG_QNX6_MODE ||
00461 Option::target_mode == Option::TARG_MACX_MODE) &&
00462 inc[0] != '/')) {
00463 for(MakefileDependDir *mdd = dirs.first(); mdd; mdd = dirs.next() ) {
00464 if(!stat(mdd->local_dir + QDir::separator() + inc, &fst) &&
00465 !S_ISDIR(fst.st_mode)) {
00466 fqn = mdd->real_dir + QDir::separator() + inc;
00467 goto handle_fqn;
00468 }
00469 }
00470 }
00471 }
00472 if(fqn.isEmpty() && Option::mkfile::do_dep_heuristics) {
00473
00474
00475
00476
00477 if(depHeuristics.contains(inc)) {
00478 fqn = depHeuristics[inc];
00479 from_source_dir = FALSE;
00480 } else if(Option::mkfile::do_dep_heuristics) {
00481
00482 QString inc_file = inc.section(Option::dir_sep, -1);
00483 int extn = inc_file.findRev('.');
00484 if(extn != -1 &&
00485 (inc_file.right(inc_file.length()-extn) == Option::cpp_ext.first() ||
00486 inc_file.right(inc_file.length()-extn) == Option::h_ext.first())) {
00487 QString uip = inc_file.left(extn) + Option::ui_ext;
00488 QStringList uil = project->variables()["FORMS"];
00489 for(QStringList::Iterator it = uil.begin(); it != uil.end(); ++it) {
00490 if((*it).section(Option::dir_sep, -1) == uip) {
00491 if(!project->isEmpty("UI_DIR"))
00492 fqn = project->first("UI_DIR");
00493 else if(!project->isEmpty("UI_HEADERS_DIR"))
00494 fqn = project->first("UI_HEADERS_DIR");
00495 else
00496 fqn = (*it).section(Option::dir_sep, 0, -2);
00497 if(!fqn.isEmpty() && !fqn.endsWith(Option::dir_sep))
00498 fqn += Option::dir_sep;
00499 fqn += inc_file;
00500 from_source_dir = FALSE;
00501 fqn = fileFixify(fqn, QDir::currentDirPath(), Option::output_dir);
00502 goto cache_fqn;
00503 }
00504 }
00505 }
00506 if(project->isActiveConfig("lex_included")) {
00507 QString rhs = Option::lex_mod + Option::cpp_ext.first();
00508 if(inc.endsWith(rhs)) {
00509 QString lhs = inc.left(inc.length() - rhs.length()) + Option::lex_ext;
00510 QStringList ll = project->variables()["LEXSOURCES"];
00511 for(QStringList::Iterator it = ll.begin(); it != ll.end(); ++it) {
00512 QString s = (*it), d;
00513 int slsh = s.findRev(Option::dir_sep);
00514 if(slsh != -1) {
00515 d = s.left(slsh + 1);
00516 s = s.right(s.length() - slsh - 1);
00517 }
00518 if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH"))
00519 d = project->first("QMAKE_ABSOLUTE_SOURCE_PATH");
00520 if(s == lhs) {
00521 fqn = d + inc;
00522 from_source_dir = FALSE;
00523 fqn = fileFixify(fqn, QDir::currentDirPath(), Option::output_dir);
00524 goto cache_fqn;
00525 }
00526 }
00527 }
00528 }
00529 {
00530 QString rhs = Option::yacc_mod + Option::h_ext.first();
00531 if(inc.endsWith(rhs)) {
00532 QString lhs = inc.left(inc.length() - rhs.length()) + Option::yacc_ext;
00533 QStringList yl = project->variables()["YACCSOURCES"];
00534 for(QStringList::Iterator it = yl.begin(); it != yl.end(); ++it) {
00535 QString s = (*it), d;
00536 int slsh = s.findRev(Option::dir_sep);
00537 if(slsh != -1) {
00538 d = s.left(slsh + 1);
00539 s = s.right(s.length() - slsh - 1);
00540 }
00541 if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH"))
00542 d = project->first("QMAKE_ABSOLUTE_SOURCE_PATH");
00543 if(s == lhs) {
00544 fqn = d + inc;
00545 from_source_dir = FALSE;
00546 fqn = fileFixify(fqn, QDir::currentDirPath(), Option::output_dir);
00547 goto cache_fqn;
00548 }
00549 }
00550 }
00551 }
00552 if( mocAware() &&
00553 ( inc.endsWith(Option::cpp_ext.first()) || inc.endsWith(Option::cpp_moc_ext) )
00554 || ( (Option::cpp_ext.first() != Option::h_moc_ext) && inc.endsWith(Option::h_moc_ext) )) {
00555 QString mocs[] = { QString("_HDRMOC"), QString("_SRCMOC"), QString::null };
00556 for(int moc = 0; !mocs[moc].isNull(); moc++) {
00557 QStringList &l = project->variables()[mocs[moc]];
00558 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
00559 QString file = Option::fixPathToTargetOS((*it));
00560 if(file.section(Option::dir_sep, -(inc.contains('/')+1)) == inc) {
00561 fqn = (*it);
00562 if(mocs[moc] == "_HDRMOC") {
00563
00564 project->variables()["_SRCMOC"].append((*it));
00565 l.remove(it);
00566 } else if(!findMocSource(fqn).endsWith(fileFixify(fn))) {
00567
00568
00569
00570 warn_msg(WarnLogic,
00571 "Found potential multiple MOC include %s (%s) in '%s'",
00572 inc.latin1(), fqn.latin1(), fix_env_fn.latin1());
00573 }
00574 from_source_dir = FALSE;
00575 goto cache_fqn;
00576 }
00577 }
00578 }
00579 }
00580 fqn = findDependency(inc);
00581 cache_fqn:
00582 if(from_source_dir) {
00583 fqn = fileFixify(fqn);
00584 from_source_dir = FALSE;
00585 }
00586 depHeuristics.insert(inc, fqn);
00587 }
00588 }
00589 handle_fqn:
00590 if(fqn.isEmpty())
00591 continue;
00592 fqn = Option::fixPathToTargetOS(fqn, FALSE);
00593 if(from_source_dir)
00594 fqn = fileFixify(fqn);
00595 debug_msg(4, "Resolved dependency of %s to %s", inc.latin1(), fqn.latin1());
00596 if(outdeps && outdeps->findIndex(fqn) == -1)
00597 outdeps->append(fqn);
00598 }
00599
00600 for( ; x < total_size_read && !QMAKE_EOL(*(big_buffer + x)); x++);
00601 line_count++;
00602 }
00603
00604 if(recurse) {
00605 for(QStringList::Iterator fnit = fndeps.begin(); fnit != fndeps.end(); ++fnit) {
00606 generateDependencies(dirs, (*fnit), recurse);
00607 QStringList &deplist = findDependencies((*fnit));
00608 for(QStringList::Iterator it = deplist.begin(); it != deplist.end(); ++it)
00609 if(fndeps.findIndex((*it)) == -1 && (*it) != fn)
00610 fndeps.append((*it));
00611 }
00612 }
00613 debug_msg(2, "Dependencies: %s -> %s", fn.latin1(), fndeps.join(" :: ").latin1());
00614 return TRUE;
00615 }
00616
00617 void
00618 MakefileGenerator::initOutPaths()
00619 {
00620 if(init_opath_already)
00621 return;
00622 init_opath_already = TRUE;
00623 QMap<QString, QStringList> &v = project->variables();
00624 if(!v.contains("QMAKE_ABSOLUTE_SOURCE_PATH")) {
00625 if(Option::mkfile::do_cache && !Option::mkfile::cachefile.isEmpty() &&
00626 v.contains("QMAKE_ABSOLUTE_SOURCE_ROOT")) {
00627 QString root = v["QMAKE_ABSOLUTE_SOURCE_ROOT"].first();
00628 root = Option::fixPathToTargetOS( root );
00629 if(!root.isEmpty()) {
00630 QFileInfo fi(Option::mkfile::cachefile);
00631 if(!fi.convertToAbs()) {
00632 QString cache_r = fi.dirPath(), pwd = Option::output_dir;
00633 if ( pwd.startsWith(cache_r) && !pwd.startsWith(root) ) {
00634 pwd = Option::fixPathToTargetOS(root + pwd.mid(cache_r.length()));
00635 if(QFile::exists(pwd))
00636 v.insert("QMAKE_ABSOLUTE_SOURCE_PATH", pwd);
00637 }
00638 }
00639 }
00640 }
00641 }
00642 if(!v["QMAKE_ABSOLUTE_SOURCE_PATH"].isEmpty()) {
00643 QString &asp = v["QMAKE_ABSOLUTE_SOURCE_PATH"].first();
00644 asp = Option::fixPathToTargetOS( asp );
00645 if(asp.isEmpty() || asp == Option::output_dir)
00646 v["QMAKE_ABSOLUTE_SOURCE_PATH"].clear();
00647 }
00648 QString currentDir = QDir::currentDirPath();
00649 QString dirs[] = { QString("OBJECTS_DIR"), QString("MOC_DIR"), QString("UI_HEADERS_DIR"),
00650 QString("UI_SOURCES_DIR"), QString("UI_DIR"), QString("DESTDIR"),
00651 QString("SUBLIBS_DIR"), QString("DLLDESTDIR"), QString::null };
00652 for(int x = 0; dirs[x] != QString::null; x++) {
00653 if ( !v[dirs[x]].isEmpty() ) {
00654 QString orig_path = v[dirs[x]].first();
00655 #ifdef Q_WS_WIN
00656
00657 if (!(dirs[x] == "DLLDESTDIR"))
00658 #endif
00659 {
00660 QString &path = v[dirs[x]].first();
00661 path = fileFixify(path, Option::output_dir, Option::output_dir);
00662 if(path.right(Option::dir_sep.length()) != Option::dir_sep)
00663 path += Option::dir_sep;
00664 }
00665 if(noIO())
00666 continue;
00667
00668 QString path = project->first(dirs[x]);
00669 path = Option::fixPathToTargetOS(fileFixify(path, QDir::currentDirPath(), Option::output_dir));
00670 debug_msg(3, "Fixed output_dir %s (%s) into %s (%s)", dirs[x].latin1(), orig_path.latin1(),
00671 v[dirs[x]].join("::").latin1(), path.latin1());
00672
00673 QDir d;
00674 if(path.startsWith(Option::dir_sep)) {
00675 d.cd(Option::dir_sep);
00676 path = path.right(path.length() - 1);
00677 }
00678 #ifdef Q_WS_WIN
00679 bool driveExists = TRUE;
00680 if ( !QDir::isRelativePath( path ) ) {
00681 if ( QFile::exists( path.left( 3 ) ) ) {
00682 d.cd( path.left( 3 ) );
00683 path = path.right( path.length() - 3 );
00684 } else {
00685 warn_msg(WarnLogic, "%s: Cannot access drive '%s' (%s)", dirs[x].latin1(),
00686 path.left( 3 ).latin1(), path.latin1() );
00687 driveExists = FALSE;
00688 }
00689 }
00690 if ( driveExists ) {
00691 #endif
00692 QStringList subs = QStringList::split(Option::dir_sep, path);
00693 for(QStringList::Iterator subit = subs.begin(); subit != subs.end(); ++subit) {
00694 if(!d.cd(*subit)) {
00695 d.mkdir((*subit));
00696 if ( d.exists( (*subit) ) )
00697 d.cd((*subit));
00698 else {
00699 warn_msg(WarnLogic, "%s: Cannot access directory '%s' (%s)", dirs[x].latin1(),
00700 (*subit).latin1(), path.latin1() );
00701 break;
00702 }
00703 }
00704 }
00705 #ifdef Q_WS_WIN
00706 }
00707 #endif
00708 }
00709 }
00710 if ( !v["DESTDIR"].isEmpty() ) {
00711 QDir d(v["DESTDIR"].first());
00712 if(Option::fixPathToLocalOS(d.absPath()) == Option::fixPathToLocalOS(Option::output_dir))
00713 v.remove("DESTDIR");
00714 }
00715 QDir::current().cd( currentDir );
00716 }
00717
00718 void
00719 MakefileGenerator::init()
00720 {
00721 initOutPaths();
00722 if(init_already)
00723 return;
00724 init_already = TRUE;
00725
00726 QMap<QString, QStringList> &v = project->variables();
00727 QString paths[] = { QString("SOURCES"), QString("FORMS"), QString("YACCSOURCES"), QString("INCLUDEPATH"),
00728 QString("HEADERS"), QString("HEADERS_ORIG"), QString("LEXSOURCES"),
00729 QString("QMAKE_INTERNAL_INCLUDED_FILES"),
00730 QString("PRECOMPILED_HEADER"), QString::null };
00731 for(int y = 0; paths[y] != QString::null; y++) {
00732 QStringList &l = v[paths[y]];
00733 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
00734 if ((*it).isEmpty())
00735 continue;
00736 if(QFile::exists((*it)))
00737 (*it) = fileFixify((*it));
00738 }
00739 }
00740
00741
00742 QDict<void> cache_found_files;
00743 QString cache_file(".qmake.internal.cache");
00744 if(!project->isEmpty("QMAKE_INTERNAL_CACHE_FILE"))
00745 cache_file = Option::fixPathToLocalOS(project->first("QMAKE_INTERNAL_CACHE_FILE"));
00746 if(cache_file.find(QDir::separator()) == -1)
00747 cache_file.prepend(Option::output_dir + QDir::separator());
00748 if((Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT ||
00749 Option::mkfile::do_deps || Option::mkfile::do_mocs) && !noIO()) {
00750 QPtrList<MakefileDependDir> deplist;
00751 deplist.setAutoDelete(TRUE);
00752 if((Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT || Option::mkfile::do_deps) &&
00753 doDepends()) {
00754 QStringList incDirs = v["DEPENDPATH"] + v["QMAKE_ABSOLUTE_SOURCE_PATH"];
00755 if(project->isActiveConfig("depend_includepath"))
00756 incDirs += v["INCLUDEPATH"];
00757 for(QStringList::Iterator it = incDirs.begin(); it != incDirs.end(); ++it) {
00758 QString r = (*it), l = Option::fixPathToLocalOS((*it));
00759 deplist.append(new MakefileDependDir(r.replace("\"",""),
00760 l.replace("\"","")));
00761 }
00762 debug_msg(1, "Dependency Directories: %s", incDirs.join(" :: ").latin1());
00763 if(Option::output.name() != "-" && project->isActiveConfig("qmake_cache")) {
00764 QFile cachef(cache_file);
00765 if(cachef.open(IO_ReadOnly | IO_Translate)) {
00766 QFileInfo cachefi(cache_file);
00767 debug_msg(2, "Trying internal cache information: %s", cache_file.latin1());
00768 QTextStream cachet(&cachef);
00769 QString line, file;
00770 enum { CacheInfo, CacheDepend, CacheMoc } state = CacheInfo;
00771 while (!cachet.eof()) {
00772 line = cachet.readLine().stripWhiteSpace();
00773 int sep = line.find('=');
00774 if(line == "[depend]") {
00775 state = CacheDepend;
00776 } else if(line == "[mocable]") {
00777 state = CacheMoc;
00778 } else if(line == "[check]") {
00779 state = CacheInfo;
00780 } else if(!line.isEmpty() && sep != -1) {
00781 file = line.left(sep).stripWhiteSpace();
00782 line = line.right(line.length() - sep - 1).stripWhiteSpace();
00783 if(state == CacheInfo) {
00784 if(file == "QMAKE_CACHE_VERSION") {
00785 if(line != qmake_version())
00786 break;
00787 } else {
00788 const QStringList &l = project->variables()[file];
00789 if(!l.isEmpty() && !line.isEmpty() && l.join(" ") != line)
00790 break;
00791 }
00792 } else if(state == CacheDepend) {
00793 bool found = (bool)cache_found_files[file];
00794 QStringList files = QStringList::split(" ", line);
00795 if(!found) {
00796 QFileInfo fi(fileFixify(file, QDir::currentDirPath(), Option::output_dir));
00797 if(fi.exists() && fi.lastModified() < cachefi.lastModified()) {
00798 cache_found_files.insert(file, (void *)1);
00799 found = TRUE;
00800 }
00801 }
00802 if(found) {
00803 for(QStringList::Iterator dep_it = files.begin();
00804 dep_it != files.end(); ++dep_it) {
00805 if(!cache_found_files[(*dep_it)]) {
00806 QFileInfo fi(fileFixify((*dep_it), QDir::currentDirPath(), Option::output_dir));
00807 if(fi.exists() &&
00808 fi.lastModified() < cachefi.lastModified()) {
00809 cache_found_files.insert((*dep_it), (void *)1);
00810 } else {
00811 found = FALSE;
00812 break;
00813 }
00814 }
00815 }
00816 if(found) {
00817 debug_msg(2, "Dependencies (cached): %s -> %s", file.latin1(),
00818 files.join(" :: ").latin1());
00819 findDependencies(file) = files;
00820 setProcessedDependencies(file, TRUE);
00821 }
00822 }
00823 } else {
00824 void *found = cache_found_files[file];
00825 if(found != (void *)2) {
00826 if(found) {
00827 cache_found_files.replace(file, (void *)2);
00828 } else {
00829 QFileInfo fi(fileFixify(file, QDir::currentDirPath(), Option::output_dir));
00830 if(fi.exists() && fi.lastModified() < cachefi.lastModified()) {
00831 cache_found_files.insert(file, (void *)2);
00832 found = (void*)1;
00833 }
00834 }
00835 }
00836 if(found && line != "*qmake_ignore*") {
00837 int ext_len = file.length() - file.findRev('.');
00838 bool cpp_ext = FALSE;
00839 for(QStringList::Iterator cppit = Option::cpp_ext.begin();
00840 cppit != Option::cpp_ext.end(); ++cppit) {
00841 if((cpp_ext = (file.right(ext_len) == (*cppit))))
00842 break;
00843 }
00844 if(cpp_ext) {
00845 project->variables()["_SRCMOC"].append(line);
00846 } else if(project->variables()["HEADERS"].findIndex(file) != -1) {
00847 for(QStringList::Iterator hit = Option::h_ext.begin();
00848 hit != Option::h_ext.end(); ++hit) {
00849 if((file.right(ext_len) == (*hit))) {
00850 project->variables()["_HDRMOC"].append(line);
00851 break;
00852 }
00853 }
00854 }
00855 debug_msg(2, "Mocgen (cached): %s -> %s", file.latin1(),
00856 line.latin1());
00857 mocablesToMOC[file] = line;
00858 mocablesFromMOC[line] = file;
00859 }
00860 }
00861 }
00862 }
00863 cachef.close();
00864 }
00865 }
00866 }
00867 if(!noIO()) {
00868 QString sources[] = { QString("OBJECTS"), QString("LEXSOURCES"), QString("YACCSOURCES"),
00869 QString("HEADERS"), QString("SOURCES"), QString("FORMS"),
00870 QString("PRECOMPILED_HEADER"), QString::null };
00871 depHeuristics.clear();
00872 bool write_cache = FALSE, read_cache = QFile::exists(cache_file);
00873 int x;
00874 for(x = 0; sources[x] != QString::null; x++) {
00875 QStringList vpath, &l = v[sources[x]];
00876 for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) {
00877 if(!(*val_it).isEmpty()) {
00878 QString file = fileFixify((*val_it), QDir::currentDirPath(), Option::output_dir);
00879 if(!QFile::exists(file)) {
00880 bool found = FALSE;
00881 if(QDir::isRelativePath((*val_it))) {
00882 if(vpath.isEmpty())
00883 vpath = v["VPATH_" + sources[x]] + v["VPATH"] +
00884 v["QMAKE_ABSOLUTE_SOURCE_PATH"] + v["DEPENDPATH"];
00885
00886 for(QStringList::Iterator vpath_it = vpath.begin();
00887 vpath_it != vpath.end(); ++vpath_it) {
00888 QString real_dir = Option::fixPathToLocalOS((*vpath_it));
00889 if(QFile::exists(real_dir + QDir::separator() + (*val_it))) {
00890 QString dir = (*vpath_it);
00891 if(dir.right(Option::dir_sep.length()) != Option::dir_sep)
00892 dir += Option::dir_sep;
00893 (*val_it) = fileFixify(dir + (*val_it));
00894 found = TRUE;
00895 debug_msg(1, "Found file through vpath %s -> %s",
00896 file.latin1(), (*val_it).latin1());
00897 break;
00898 }
00899 }
00900 }
00901 if(!found) {
00902 QString dir, regex = (*val_it), real_dir;
00903 if(regex.findRev(Option::dir_sep) != -1) {
00904 dir = regex.left(regex.findRev(Option::dir_sep) + 1);
00905 real_dir = fileFixify(Option::fixPathToLocalOS(dir),
00906 QDir::currentDirPath(), Option::output_dir);
00907 regex = regex.right(regex.length() - dir.length());
00908 }
00909 if(real_dir.isEmpty() || QFile::exists(real_dir)) {
00910 QDir d(real_dir, regex);
00911 if(!d.count()) {
00912 debug_msg(1, "%s:%d Failure to find %s in vpath (%s)",
00913 __FILE__, __LINE__,
00914 (*val_it).latin1(), vpath.join("::").latin1());
00915 warn_msg(WarnLogic, "Failure to find: %s", (*val_it).latin1());
00916 continue;
00917 } else {
00918 for(int i = 0; i < (int)d.count(); i++) {
00919 QString file = fileFixify(dir + d[i]);
00920 if(i == (int)d.count() - 1)
00921 (*val_it) = file;
00922 else
00923 l.insert(val_it, file);
00924 }
00925 }
00926 } else {
00927 debug_msg(1, "%s:%d Cannot match %s%c%s, as %s does not exist.",
00928 __FILE__, __LINE__,
00929 real_dir.latin1(), QDir::separator(), regex.latin1(),
00930 real_dir.latin1());
00931 warn_msg(WarnLogic, "Failure to find: %s", (*val_it).latin1());
00932 }
00933 }
00934 }
00935 }
00936 }
00937 }
00938 for(x = 0; sources[x] != QString::null; x++) {
00939 QStringList &l = v[sources[x]];
00940 for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) {
00941 bool found_cache_moc = FALSE, found_cache_dep = FALSE;
00942 if(read_cache && Option::output.name() != "-" &&
00943 project->isActiveConfig("qmake_cache")) {
00944 if(processedDependencies((*val_it)))
00945 found_cache_dep = TRUE;
00946 if(cache_found_files[(*val_it)] == (void *)2)
00947 found_cache_moc = TRUE;
00948 if(!found_cache_moc || !found_cache_dep)
00949 write_cache = TRUE;
00950 }
00951
00952
00953 if(found_cache_moc) {
00954 QString fixed_file(fileFixify((*val_it), QDir::currentDirPath(), Option::output_dir));
00955 QString moc = findMocDestination(fixed_file);
00956 if(!moc.isEmpty()) {
00957 for(QStringList::Iterator cppit = Option::cpp_ext.begin();
00958 cppit != Option::cpp_ext.end(); ++cppit) {
00959 if(fixed_file.endsWith((*cppit))) {
00960 QStringList &deps = findDependencies(fixed_file);
00961 if(!deps.contains(moc))
00962 deps.append(moc);
00963 break;
00964 }
00965 }
00966 }
00967 } else if(mocAware() && (sources[x] == "SOURCES" || sources[x] == "HEADERS") &&
00968 (Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT ||
00969 Option::mkfile::do_mocs)) {
00970 generateMocList((*val_it));
00971 }
00972 if(!found_cache_dep && sources[x] != "OBJECTS") {
00973 debug_msg(5, "Looking for dependencies for %s", (*val_it).latin1());
00974 generateDependencies(deplist, (*val_it), doDepends());
00975 }
00976 }
00977 }
00978 if(project->isActiveConfig("qmake_cache") && (write_cache || !read_cache)) {
00979 QFile cachef(cache_file);
00980 if(cachef.open(IO_WriteOnly | IO_Translate)) {
00981 debug_msg(2, "Writing internal cache information: %s", cache_file.latin1());
00982 QTextStream cachet(&cachef);
00983 cachet << "[check]" << "\n"
00984 << "QMAKE_CACHE_VERSION = " << qmake_version() << "\n"
00985 << "QMAKE_ABSOLUTE_SOURCE_PATH = " << var("QMAKE_ABSOLUTE_SOURCE_PATH") << "\n"
00986 << "MOC_DIR = " << var("MOC_DIR") << "\n"
00987 << "UI_DIR = " << var("UI_DIR") << "\n"
00988 << "UI_HEADERS_DIR = " << var("UI_HEADERS_DIR") << "\n"
00989 << "UI_SOURCES_DIR = " << var("UI_SOURCES_DIR") << "\n";
00990 cachet << "[depend]" << endl;
00991 for(QMap<QString, QStringList>::Iterator it = depends.begin();
00992 it != depends.end(); ++it)
00993 cachet << dependencyKey(it.key()) << " = " << it.data().join(" ") << endl;
00994 cachet << "[mocable]" << endl;
00995 QString mc, moc_sources[] = { QString("HEADERS"), QString("SOURCES"), QString::null };
00996 for(int x = 0; moc_sources[x] != QString::null; x++) {
00997 QStringList &l = v[moc_sources[x]];
00998 for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) {
00999 QString f = fileFixify((*val_it));
01000 if(!f.isEmpty()) {
01001 mc = mocablesToMOC[f];
01002 if(mc.isEmpty())
01003 mc = "*qmake_ignore*";
01004 cachet << f << " = " << mc << endl;
01005 }
01006 }
01007 }
01008 cachef.close();
01009 }
01010 }
01011 }
01012 }
01013 v["OBJECTS"] = createObjectList("SOURCES") + v["OBJECTS"];
01014
01015
01016 {
01017 QStringList &impls = v["LEXIMPLS"];
01018 QStringList &l = v["LEXSOURCES"];
01019 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
01020 QString dir;
01021 QFileInfo fi((*it));
01022 if(fi.dirPath() != ".")
01023 dir = fi.dirPath() + Option::dir_sep;
01024 dir = fileFixify(dir, QDir::currentDirPath(), Option::output_dir);
01025 if(!dir.isEmpty() && dir.right(Option::dir_sep.length()) != Option::dir_sep)
01026 dir += Option::dir_sep;
01027 QString impl = dir + fi.baseName(TRUE) + Option::lex_mod + Option::cpp_ext.first();
01028 logicWarn(impl, "SOURCES");
01029 logicWarn(impl, "SOURCES");
01030 impls.append(impl);
01031 if( ! project->isActiveConfig("lex_included")) {
01032 v["SOURCES"].append(impl);
01033
01034 QStringList &lexdeps = findDependencies((*it));
01035 QStringList &impldeps = findDependencies(impl);
01036 for(QStringList::ConstIterator d = lexdeps.begin(); d != lexdeps.end(); ++d) {
01037 if(!impldeps.contains(*d))
01038 impldeps.append(*d);
01039 }
01040 lexdeps.clear();
01041 }
01042 }
01043 if( ! project->isActiveConfig("lex_included"))
01044 v["OBJECTS"] += (v["LEXOBJECTS"] = createObjectList("LEXIMPLS"));
01045 }
01046
01047 {
01048 QStringList &decls = v["YACCCDECLS"], &impls = v["YACCIMPLS"];
01049 QStringList &l = v["YACCSOURCES"];
01050 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
01051 QString dir;
01052 QFileInfo fi((*it));
01053 if(fi.dirPath() != ".")
01054 dir = fi.dirPath() + Option::dir_sep;
01055 dir = fileFixify(dir, QDir::currentDirPath(), Option::output_dir);
01056 if(!dir.isEmpty() && dir.right(Option::dir_sep.length()) != Option::dir_sep)
01057 dir += Option::dir_sep;
01058 QString impl = dir + fi.baseName(TRUE) + Option::yacc_mod + Option::cpp_ext.first();
01059 logicWarn(impl, "SOURCES");
01060 QString decl = dir + fi.baseName(TRUE) + Option::yacc_mod + Option::h_ext.first();
01061 logicWarn(decl, "HEADERS");
01062
01063 decls.append(decl);
01064 impls.append(impl);
01065 v["SOURCES"].append(impl);
01066 QStringList &impldeps = findDependencies(impl);
01067 impldeps.append(decl);
01068
01069 QStringList &yaccdeps = findDependencies((*it));
01070 for(QStringList::ConstIterator d = yaccdeps.begin(); d != yaccdeps.end(); ++d) {
01071 if(!impldeps.contains(*d))
01072 impldeps.append(*d);
01073 }
01074 if( project->isActiveConfig("lex_included")) {
01075
01076 QString lexsrc = fi.baseName(TRUE) + Option::lex_ext;
01077 if(fi.dirPath() != ".")
01078 lexsrc.prepend(fi.dirPath() + Option::dir_sep);
01079 if(v["LEXSOURCES"].findIndex(lexsrc) != -1) {
01080 QString trg = dir + fi.baseName(TRUE) + Option::lex_mod + Option::cpp_ext.first();
01081 impldeps.append(trg);
01082 impldeps += findDependencies(lexsrc);
01083 depends[lexsrc].clear();
01084 }
01085 }
01086 yaccdeps.clear();
01087 }
01088 v["OBJECTS"] += (v["YACCOBJECTS"] = createObjectList("YACCIMPLS"));
01089 }
01090
01091
01092 {
01093 QStringList &includepath = project->variables()["INCLUDEPATH"];
01094 if(!project->isEmpty("UI_DIR"))
01095 includepath.append(project->first("UI_DIR"));
01096 else if(!project->isEmpty("UI_HEADERS_DIR"))
01097 includepath.append(project->first("UI_HEADERS_DIR"));
01098 QStringList &decls = v["UICDECLS"], &impls = v["UICIMPLS"];
01099 QStringList &l = v["FORMS"];
01100 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
01101 QString impl, decl;
01102 QFileInfo fi(Option::fixPathToLocalOS((*it)));
01103 if ( !project->isEmpty("UI_DIR") ) {
01104 impl = decl = project->first("UI_DIR");
01105 QString d = fi.dirPath();
01106 if( d == ".")
01107 d = QDir::currentDirPath();
01108 d = fileFixify(d, QDir::currentDirPath(), Option::output_dir);
01109 if(!includepath.contains(d))
01110 includepath.append(d);
01111 } else {
01112 if(decl.isEmpty() && !project->isEmpty("UI_HEADERS_DIR"))
01113 decl = project->first("UI_HEADERS_DIR");
01114 if(!decl.isEmpty() || (project->isEmpty("UI_HEADERS_DIR") &&
01115 !project->isEmpty("UI_SOURCES_DIR")) ) {
01116 QString d = fi.dirPath();
01117 if( d == ".")
01118 d = QDir::currentDirPath();
01119 d = fileFixify(d, QDir::currentDirPath(), Option::output_dir);
01120 if(includepath.contains(d))
01121 includepath.append(d);
01122 }
01123 if(impl.isEmpty() && !project->isEmpty("UI_SOURCES_DIR"))
01124 impl = project->first("UI_SOURCES_DIR");
01125 if(fi.dirPath() != ".") {
01126 if(impl.isEmpty())
01127 impl = fi.dirPath() + Option::dir_sep;
01128 if(decl.isEmpty())
01129 decl = fi.dirPath() + Option::dir_sep;
01130 }
01131 }
01132 impl = fileFixify(impl, QDir::currentDirPath(), Option::output_dir);
01133 if(!impl.isEmpty() && !impl.endsWith(Option::dir_sep))
01134 impl += Option::dir_sep;
01135 impl += fi.baseName(TRUE) + Option::cpp_ext.first();
01136 if(Option::output_dir != QDir::currentDirPath() &&
01137 project->isEmpty("UI_DIR") && project->isEmpty("UI_HEADERS_DIR")) {
01138 QString decl_fixed = fileFixify(decl, QDir::currentDirPath(), Option::output_dir);
01139 if(!includepath.contains(decl_fixed))
01140 includepath.append(decl_fixed);
01141 if(!includepath.contains(decl))
01142 project->variables()["INCLUDEPATH"].append(decl);
01143 }
01144 decl = fileFixify(decl, QDir::currentDirPath(), Option::output_dir);
01145 if(!decl.isEmpty() && !decl.endsWith(Option::dir_sep))
01146 decl += Option::dir_sep;
01147 decl += fi.baseName(TRUE) + Option::h_ext.first();
01148 logicWarn(impl, "SOURCES");
01149 logicWarn(decl, "HEADERS");
01150 decls.append(decl);
01151 impls.append(impl);
01152 findDependencies(impl).append(decl);
01153
01154 QString mocable = Option::h_moc_mod + fi.baseName(TRUE) + Option::h_moc_ext;
01155 if(!v["MOC_DIR"].isEmpty())
01156 mocable.prepend(v["MOC_DIR"].first());
01157 else if(fi.dirPath() != ".")
01158 mocable.prepend(fi.dirPath() + Option::dir_sep);
01159 logicWarn(mocable, "SOURCES");
01160 mocablesToMOC[cleanFilePath(decl)] = mocable;
01161 mocablesFromMOC[cleanFilePath(mocable)] = decl;
01162 v["_UIMOC"].append(mocable);
01163 }
01164 v["OBJECTS"] += (v["UICOBJECTS"] = createObjectList("UICDECLS"));
01165 }
01166
01167
01168 if(!project->isEmpty("TRANSLATIONS")) {
01169 QStringList &trf = project->variables()["TRANSLATIONS"];
01170 for(QStringList::Iterator it = trf.begin(); it != trf.end(); ++it) {
01171 (*it) = Option::fixPathToLocalOS((*it));
01172 }
01173 }
01174
01175
01176 if(!project->isEmpty("IMAGES")) {
01177 if(project->isEmpty("QMAKE_IMAGE_COLLECTION"))
01178 v["QMAKE_IMAGE_COLLECTION"].append("qmake_image_collection" + Option::cpp_ext.first());
01179 QString imgfile = project->first("QMAKE_IMAGE_COLLECTION");
01180 Option::fixPathToTargetOS(imgfile);
01181 if(!project->isEmpty("UI_DIR") || !project->isEmpty("UI_SOURCES_DIR")) {
01182 if(imgfile.find(Option::dir_sep) != -1)
01183 imgfile = imgfile.right(imgfile.findRev(Option::dir_sep) + 1);
01184 imgfile.prepend( (project->isEmpty("UI_DIR") ? project->first("UI_SOURCES_DIR") :
01185 project->first("UI_DIR")) );
01186 v["QMAKE_IMAGE_COLLECTION"] = QStringList(imgfile);
01187 }
01188 logicWarn(imgfile, "SOURCES");
01189 if(!noIO()) {
01190 QStringList &l = v["IMAGES"];
01191 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
01192 if(!QFile::exists((*it))) {
01193 warn_msg(WarnLogic, "Failure to open: %s", (*it).latin1());
01194 continue;
01195 }
01196 findDependencies(imgfile).append(fileFixify((*it)));
01197 }
01198 }
01199 v["OBJECTS"] += (v["IMAGEOBJECTS"] = createObjectList("QMAKE_IMAGE_COLLECTION"));
01200 }
01201 if(Option::output_dir != QDir::currentDirPath())
01202 project->variables()["INCLUDEPATH"].append(fileFixify(Option::output_dir, Option::output_dir,
01203 Option::output_dir));
01204
01205
01206 if ( mocAware() ) {
01207 if(!project->isEmpty("MOC_DIR"))
01208 project->variables()["INCLUDEPATH"].append(project->first("MOC_DIR"));
01209 if ( Option::h_moc_ext == Option::cpp_ext.first() )
01210 v["OBJMOC"] = createObjectList("_HDRMOC") + createObjectList("_UIMOC");
01211
01212 QStringList &l = v["SRCMOC"];
01213 l = v["_HDRMOC"] + v["_UIMOC"] + v["_SRCMOC"];
01214 for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) {
01215 if(!(*val_it).isEmpty())
01216 (*val_it) = Option::fixPathToTargetOS((*val_it), FALSE);
01217 }
01218 }
01219
01220 QString fixpaths[] = { QString("PRE_TARGETDEPS"), QString("POST_TARGETDEPS"), QString::null };
01221 for(int path = 0; !fixpaths[path].isNull(); path++) {
01222 QStringList &l = v[fixpaths[path]];
01223 for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) {
01224 if(!(*val_it).isEmpty())
01225 (*val_it) = Option::fixPathToTargetOS((*val_it), FALSE);
01226 }
01227 }
01228
01229
01230 QStringList &ipl = project->variables()["INCLUDEPATH"];
01231 for(QStringList::Iterator ipl_it = ipl.begin(); ipl_it != ipl.end();) {
01232 if ((*ipl_it).isEmpty())
01233 ipl_it = ipl.remove(ipl_it);
01234 else
01235 ++ipl_it;
01236 }
01237 }
01238
01239 bool
01240 MakefileGenerator::processPrlFile(QString &file)
01241 {
01242 bool ret = FALSE, try_replace_file=FALSE;
01243 QString meta_file, orig_file = file;
01244 if(QMakeMetaInfo::libExists(file)) {
01245 try_replace_file = TRUE;
01246 meta_file = file;
01247 file = "";
01248 } else {
01249 QString tmp = file;
01250 int ext = tmp.findRev('.');
01251 if(ext != -1)
01252 tmp = tmp.left(ext);
01253 meta_file = tmp;
01254 }
01255 meta_file = fileFixify(meta_file);
01256 if(!QMakeMetaInfo::libExists(fileFixify(meta_file, QDir::currentDirPath(), Option::output_dir)) &&
01257 project->isActiveConfig("qt")) {
01258 QString stem = meta_file, dir, extn;
01259 int slsh = stem.findRev('/'), hadlib = 0;
01260 if(slsh != -1) {
01261 dir = stem.left(slsh + 1);
01262 stem = stem.right(stem.length() - slsh - 1);
01263 }
01264 if(stem.startsWith("lib")) {
01265 hadlib = 1;
01266 stem = stem.right(stem.length() - 3);
01267 }
01268 int dot = stem.find('.');
01269 if(dot != -1) {
01270 extn = stem.right(stem.length() - dot);
01271 stem = stem.left(dot);
01272 }
01273 if(stem == "qt" || stem == "qte" || stem == "qte-mt" || stem == "qt-mt") {
01274 if(stem.endsWith("-mt"))
01275 stem = stem.left(stem.length() - 3);
01276 else
01277 stem += "-mt";
01278 meta_file = dir;
01279 if(hadlib)
01280 meta_file += "lib";
01281 meta_file += stem + extn;
01282 try_replace_file = TRUE;
01283 }
01284 }
01285 QString real_meta_file = Option::fixPathToLocalOS(meta_file);
01286 if(project->variables()["QMAKE_PRL_INTERNAL_FILES"].findIndex(QMakeMetaInfo::findLib(meta_file)) != -1) {
01287 ret = TRUE;
01288 } else if(!meta_file.isEmpty()) {
01289 QString f = fileFixify(real_meta_file, QDir::currentDirPath(), Option::output_dir);
01290 if(QMakeMetaInfo::libExists(f)) {
01291 QMakeMetaInfo libinfo;
01292 debug_msg(1, "Processing PRL file: %s", real_meta_file.latin1());
01293 if(!libinfo.readLib(f)) {
01294 fprintf(stderr, "Error processing meta file: %s\n", real_meta_file.latin1());
01295 } else if(project->isActiveConfig("no_read_prl_" + libinfo.type().lower())) {
01296 debug_msg(2, "Ignored meta file %s [%s]", real_meta_file.latin1(), libinfo.type().latin1());
01297 } else {
01298 ret = TRUE;
01299 QMap<QString, QStringList> &vars = libinfo.variables();
01300 for( QMap<QString, QStringList>::Iterator it = vars.begin(); it != vars.end(); ++it)
01301 processPrlVariable(it.key(), it.data());
01302 if(try_replace_file && !libinfo.isEmpty("QMAKE_PRL_TARGET")) {
01303 QString dir;
01304 int slsh = real_meta_file.findRev(Option::dir_sep);
01305 if(slsh != -1)
01306 dir = real_meta_file.left(slsh+1);
01307 file = libinfo.first("QMAKE_PRL_TARGET");
01308 if(QDir::isRelativePath(file))
01309 file.prepend(dir);
01310 }
01311 }
01312 }
01313 if(ret) {
01314 QString mf = QMakeMetaInfo::findLib(meta_file);
01315 project->variables()["QMAKE_PRL_INTERNAL_FILES"].append(mf);
01316 project->variables()["QMAKE_INTERNAL_INCLUDED_FILES"].append(mf);
01317 }
01318 }
01319 if(try_replace_file && file.isEmpty()) {
01320 #if 0
01321 warn_msg(WarnLogic, "Found prl [%s] file with no target [%s]!", meta_file.latin1(),
01322 orig_file.latin1());
01323 #endif
01324 file = orig_file;
01325 }
01326 return ret;
01327 }
01328
01329 void
01330 MakefileGenerator::processPrlVariable(const QString &var, const QStringList &l)
01331 {
01332 if(var == "QMAKE_PRL_LIBS") {
01333 QString where = "QMAKE_LIBS";
01334 if(!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS"))
01335 where = project->first("QMAKE_INTERNAL_PRL_LIBS");
01336 QStringList &out = project->variables()[where];
01337 for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
01338 if( out.findIndex((*it)) == -1)
01339 out.append((*it));
01340 }
01341 } else if(var == "QMAKE_PRL_DEFINES") {
01342 QStringList &out = project->variables()["DEFINES"];
01343 for(QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
01344 if(out.findIndex((*it)) == -1 &&
01345 project->variables()["PRL_EXPORT_DEFINES"].findIndex((*it)) == -1)
01346 out.append((*it));
01347 }
01348 }
01349 }
01350
01351 void
01352 MakefileGenerator::processPrlFiles()
01353 {
01354 QDict<void> processed;
01355 for(bool ret = FALSE; TRUE; ret = FALSE) {
01356
01357 QStringList l_out;
01358 QString where = "QMAKE_LIBS";
01359 if(!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS"))
01360 where = project->first("QMAKE_INTERNAL_PRL_LIBS");
01361 QStringList &l = project->variables()[where];
01362 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
01363 QString file = (*it);
01364 if(!processed[file] && processPrlFile(file)) {
01365 processed.insert(file, (void*)1);
01366 ret = TRUE;
01367 }
01368 if(!file.isEmpty())
01369 l_out.append(file);
01370 }
01371 if(ret)
01372 l = l_out;
01373 else
01374 break;
01375 }
01376 }
01377
01378 void
01379 MakefileGenerator::writePrlFile(QTextStream &t)
01380 {
01381 QString target = project->first("TARGET");
01382 int slsh = target.findRev(Option::dir_sep);
01383 if(slsh != -1)
01384 target = target.right(target.length() - slsh - 1);
01385 QString bdir = Option::output_dir;
01386 if(bdir.isEmpty())
01387 bdir = QDir::currentDirPath();
01388 t << "QMAKE_PRL_BUILD_DIR = " << bdir << endl;
01389
01390 if(!project->projectFile().isEmpty() && project->projectFile() != "-")
01391 t << "QMAKE_PRO_INPUT = " << project->projectFile().section('/', -1) << endl;
01392
01393 if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH"))
01394 t << "QMAKE_PRL_SOURCE_DIR = " << project->first("QMAKE_ABSOLUTE_SOURCE_PATH") << endl;
01395 t << "QMAKE_PRL_TARGET = " << target << endl;
01396 if(!project->isEmpty("PRL_EXPORT_DEFINES"))
01397 t << "QMAKE_PRL_DEFINES = " << project->variables()["PRL_EXPORT_DEFINES"].join(" ") << endl;
01398 if(!project->isEmpty("PRL_EXPORT_CFLAGS"))
01399 t << "QMAKE_PRL_CFLAGS = " << project->variables()["PRL_EXPORT_CFLAGS"].join(" ") << endl;
01400 if(!project->isEmpty("PRL_EXPORT_CXXFLAGS"))
01401 t << "QMAKE_PRL_CXXFLAGS = " << project->variables()["PRL_EXPORT_CXXFLAGS"].join(" ") << endl;
01402 if(!project->isEmpty("CONFIG"))
01403 t << "QMAKE_PRL_CONFIG = " << project->variables()["CONFIG"].join(" ") << endl;
01404 if(!project->isEmpty("VERSION"))
01405 t << "QMAKE_PRL_VERSION = " << project->first("VERSION") << endl;
01406 if(project->isActiveConfig("staticlib") || project->isActiveConfig("explicitlib")) {
01407 QStringList libs;
01408 if(!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS"))
01409 libs = project->variables()["QMAKE_INTERNAL_PRL_LIBS"];
01410 else
01411 libs << "QMAKE_LIBS";
01412 t << "QMAKE_PRL_LIBS = ";
01413 for(QStringList::Iterator it = libs.begin(); it != libs.end(); ++it)
01414 t << project->variables()[(*it)].join(" ") << " ";
01415 t << endl;
01416 }
01417 }
01418
01419 bool
01420 MakefileGenerator::write()
01421 {
01422 usePlatformDir();
01423 init();
01424 findLibraries();
01425 if((Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
01426 Option::qmake_mode == Option::QMAKE_GENERATE_PRL) &&
01427 project->variables()["QMAKE_FAILED_REQUIREMENTS"].isEmpty() &&
01428 project->isActiveConfig("create_prl") && project->first("TEMPLATE") == "lib" &&
01429 !project->isActiveConfig("plugin")) {
01430 QString prl = var("TARGET");
01431 int slsh = prl.findRev(Option::dir_sep);
01432 if(slsh != -1)
01433 prl = prl.right(prl.length() - slsh);
01434 int dot = prl.find('.');
01435 if(dot != -1)
01436 prl = prl.left(dot);
01437 prl += Option::prl_ext;
01438 if(!project->isEmpty("DESTDIR"))
01439 prl.prepend(var("DESTDIR"));
01440 QString local_prl = Option::fixPathToLocalOS(fileFixify(prl, QDir::currentDirPath(), Option::output_dir));
01441 QFile ft(local_prl);
01442 if(ft.open(IO_WriteOnly)) {
01443 project->variables()["ALL_DEPS"].append(prl);
01444 project->variables()["QMAKE_INTERNAL_PRL_FILE"].append(prl);
01445 QTextStream t(&ft);
01446 writePrlFile(t);
01447 ft.close();
01448 }
01449 }
01450 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE &&
01451 project->isActiveConfig("link_prl"))
01452 processPrlFiles();
01453
01454 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
01455 Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) {
01456 QTextStream t(&Option::output);
01457 writeMakefile(t);
01458 }
01459 return TRUE;
01460 }
01461
01462
01463
01464 void
01465 MakefileGenerator::usePlatformDir()
01466 {
01467 QString pltDir(project->first("QMAKE_PLATFORM_DIR"));
01468 if(pltDir.isEmpty())
01469 return;
01470 char sep = QDir::separator();
01471 QString slashPltDir = sep + pltDir;
01472
01473 QString filePath = project->first("DESTDIR");
01474 project->variables()["DESTDIR"] = filePath
01475 + (filePath.isEmpty() ? pltDir : slashPltDir);
01476
01477 filePath = project->first("DLLDESTDIR");
01478 project->variables()["DLLDESTDIR"] = filePath
01479 + (filePath.isEmpty() ? pltDir : slashPltDir);
01480
01481 filePath = project->first("OBJECTS_DIR");
01482 project->variables()["OBJECTS_DIR"] = filePath
01483 + (filePath.isEmpty() ? pltDir : slashPltDir);
01484
01485 filePath = project->first("QMAKE_LIBDIR_QT");
01486 project->variables()["QMAKE_LIBDIR_QT"] = filePath
01487 + (filePath.isEmpty() ? pltDir : slashPltDir);
01488
01489 filePath = project->first("QMAKE_LIBS_QT");
01490 int fpi = filePath.findRev(sep);
01491 if (fpi == -1)
01492 project->variables()["QMAKE_LIBS_QT"].prepend(pltDir + sep);
01493 else
01494 project->variables()["QMAKE_LIBS_QT"] = filePath.left(fpi)
01495 + slashPltDir
01496 + filePath.mid(fpi);
01497
01498 filePath = project->first("QMAKE_LIBS_QT_THREAD");
01499 fpi = filePath.findRev(sep);
01500 if (fpi == -1)
01501 project->variables()["QMAKE_LIBS_QT_THREAD"].prepend(pltDir + sep);
01502 else
01503 project->variables()["QMAKE_LIBS_QT_THREAD"] = filePath.left(fpi)
01504 + slashPltDir
01505 + filePath.mid(fpi);
01506
01507 filePath = project->first("QMAKE_LIBS_QT_ENTRY");
01508 fpi = filePath.findRev(sep);
01509 if (fpi == -1)
01510 project->variables()["QMAKE_LIBS_QT_ENTRY"].prepend(pltDir + sep);
01511 else
01512 project->variables()["QMAKE_LIBS_QT_ENTRY"] = filePath.left(fpi)
01513 + slashPltDir
01514 + filePath.mid(fpi);
01515 }
01516
01517 void
01518 MakefileGenerator::writeObj(QTextStream &t, const QString &obj, const QString &src)
01519 {
01520 QStringList &objl = project->variables()[obj];
01521 QStringList &srcl = project->variables()[src];
01522
01523 QStringList::Iterator oit = objl.begin();
01524 QStringList::Iterator sit = srcl.begin();
01525 QString stringSrc("$src");
01526 QString stringObj("$obj");
01527 for( ;sit != srcl.end() && oit != objl.end(); oit++, sit++) {
01528 if((*sit).isEmpty())
01529 continue;
01530
01531 if(!doDepends()) {
01532 QString sdep, odep = (*sit) + " ";
01533 QStringList deps = findDependencies((*sit));
01534 for(QStringList::Iterator dit = deps.begin(); dit != deps.end(); dit++) {
01535 if((*dit).endsWith(Option::cpp_moc_ext))
01536 odep += (*dit) + " ";
01537 else
01538 sdep += (*dit) + " ";
01539 }
01540 t << (*sit) << ": " << sdep << endl
01541 << (*oit) << ": " << odep ;
01542 } else {
01543 t << (*oit) << ": " << (*sit) << " " << findDependencies((*sit)).join(" \\\n\t\t");
01544 }
01545
01546 QString comp, cimp;
01547 for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) {
01548 if((*sit).endsWith((*cppit))) {
01549 comp = "QMAKE_RUN_CXX";
01550 cimp = "QMAKE_RUN_CXX_IMP";
01551 break;
01552 }
01553 }
01554 if(comp.isEmpty()) {
01555 comp = "QMAKE_RUN_CC";
01556 cimp = "QMAKE_RUN_CC_IMP";
01557 }
01558 bool use_implicit_rule = !project->isEmpty(cimp);
01559 if(use_implicit_rule) {
01560 if(!project->isEmpty("OBJECTS_DIR")) {
01561 use_implicit_rule = FALSE;
01562 } else {
01563 int dot = (*sit).findRev('.');
01564 if(dot == -1 || ((*sit).left(dot) + Option::obj_ext != (*oit)))
01565 use_implicit_rule = FALSE;
01566 }
01567 }
01568 if (!use_implicit_rule && !project->isEmpty(comp)) {
01569 QString p = var(comp), srcf(*sit);
01570 p.replace(stringSrc, srcf);
01571 p.replace(stringObj, (*oit));
01572 t << "\n\t" << p;
01573 }
01574 t << endl << endl;
01575 }
01576 }
01577
01578
01579 void
01580 MakefileGenerator::writeUicSrc(QTextStream &t, const QString &ui)
01581 {
01582 QStringList &uil = project->variables()[ui];
01583 for(QStringList::Iterator it = uil.begin(); it != uil.end(); it++) {
01584 QString decl, impl;
01585 {
01586 QString tmp = (*it), impl_dir, decl_dir;
01587 decl = tmp.replace(QRegExp("\\" + Option::ui_ext + "$"), Option::h_ext.first());
01588 int dlen = decl.findRev(Option::dir_sep) + 1;
01589 tmp = (*it);
01590 impl = tmp.replace(QRegExp("\\" + Option::ui_ext + "$"), Option::cpp_ext.first());
01591 int ilen = decl.findRev(Option::dir_sep) + 1;
01592 if(!project->isEmpty("UI_DIR")) {
01593 impl_dir = project->first("UI_DIR");
01594 decl = project->first("UI_DIR") + decl.right(decl.length() - dlen);
01595 impl = project->first("UI_DIR") + impl.right(impl.length() - ilen);
01596 } else {
01597 if(!project->isEmpty("UI_HEADERS_DIR")) {
01598 decl_dir = project->first("UI_HEADERS_DIR");
01599 decl = project->first("UI_HEADERS_DIR") + decl.right(decl.length() - dlen);
01600 }
01601 if(!project->isEmpty("UI_SOURCES_DIR")) {
01602 impl_dir = project->first("UI_SOURCES_DIR");
01603 impl = project->first("UI_SOURCES_DIR") + impl.right(impl.length() - ilen);
01604 }
01605 }
01606 impl = fileFixify(impl, QDir::currentDirPath(), Option::output_dir);
01607 decl = fileFixify(decl, QDir::currentDirPath(), Option::output_dir);
01608 if(decl_dir.isEmpty())
01609 decl_dir = decl.section(Option::dir_sep,0,-2);
01610 if(impl_dir.isEmpty())
01611 impl_dir = impl.section(Option::dir_sep,0,-2);
01612 if (QDir::isRelativePath(impl_dir))
01613 impl_dir.prepend(Option::output_dir + Option::dir_sep);
01614 if (QDir::isRelativePath(decl_dir))
01615 decl_dir.prepend(Option::output_dir + Option::dir_sep);
01616 createDir(impl_dir);
01617 createDir(decl_dir);
01618 }
01619 QStringList deps = findDependencies((*it));
01620 deps.remove(decl);
01621 t << decl << ": " << (*it) << " " << deps.join(" \\\n\t\t") << "\n\t"
01622 << "$(UIC) " << (*it) << " -o " << decl << endl << endl;
01623
01624 QString mildDecl = decl;
01625 int k = mildDecl.findRev(Option::dir_sep);
01626 if ( k != -1 )
01627 mildDecl = mildDecl.mid( k + 1 );
01628 t << impl << ": " << decl << " " << (*it) << " " << deps.join(" \\\n\t\t") << "\n\t"
01629 << "$(UIC)";
01630 t << " " << (*it) << " -i " << mildDecl << " -o " << impl << endl << endl;
01631 }
01632 }
01633
01634
01635 void
01636 MakefileGenerator::writeMocObj(QTextStream &t, const QString &obj, const QString &src)
01637 {
01638 QStringList &objl = project->variables()[obj],
01639 &srcl = project->variables()[src];
01640 QStringList::Iterator oit = objl.begin(), sit = srcl.begin();
01641 QString stringSrc("$src"), stringObj("$obj");
01642 for( ;sit != srcl.end() && oit != objl.end(); oit++, sit++) {
01643 QString hdr = findMocSource((*sit));
01644 t << (*oit) << ": "
01645 << (*sit) << " " << findDependencies((*sit)).join(" \\\n\t\t") << " "
01646 << hdr << " " << findDependencies(hdr).join(" \\\n\t\t");
01647 bool use_implicit_rule = !project->isEmpty("QMAKE_RUN_CXX_IMP");
01648 if(use_implicit_rule) {
01649 if(!project->isEmpty("OBJECTS_DIR") || !project->isEmpty("MOC_DIR")) {
01650 use_implicit_rule = FALSE;
01651 } else {
01652 int dot = (*sit).findRev('.');
01653 if(dot == -1 || ((*sit).left(dot) + Option::obj_ext != (*oit)))
01654 use_implicit_rule = FALSE;
01655 }
01656 }
01657 if (!use_implicit_rule && !project->isEmpty("QMAKE_RUN_CXX")) {
01658 QString p = var("QMAKE_RUN_CXX"), srcf(*sit);
01659 p.replace(stringSrc, srcf);
01660 p.replace(stringObj, (*oit));
01661 t << "\n\t" << p;
01662 }
01663 t << endl << endl;
01664 }
01665 }
01666
01667
01668 void
01669 MakefileGenerator::writeMocSrc(QTextStream &t, const QString &src)
01670 {
01671 QStringList &l = project->variables()[src];
01672 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
01673 QString m = Option::fixPathToTargetOS(findMocDestination(*it));
01674 if ( !m.isEmpty()) {
01675 QString deps;
01676 if(!project->isActiveConfig("no_mocdepend"))
01677 deps += "$(MOC) ";
01678 deps += (*it);
01679 t << m << ": " << deps << "\n\t"
01680 << "$(MOC)";
01681 t << " " << (*it) << " -o " << m << endl << endl;
01682 }
01683 }
01684 }
01685
01686 void
01687 MakefileGenerator::writeYaccSrc(QTextStream &t, const QString &src)
01688 {
01689 QStringList &l = project->variables()[src];
01690 if(project->isActiveConfig("yacc_no_name_mangle") && l.count() > 1)
01691 warn_msg(WarnLogic, "yacc_no_name_mangle specified, but multiple parsers expected."
01692 "This can lead to link problems.\n");
01693 QString default_out_h = "y.tab.h", default_out_c = "y.tab.c";
01694 if(!project->isEmpty("QMAKE_YACC_HEADER"))
01695 default_out_h = project->first("QMAKE_YACC_HEADER");
01696 if(!project->isEmpty("QMAKE_YACC_SOURCE"))
01697 default_out_c = project->first("QMAKE_YACC_SOURCE");
01698 QString stringBase("$base");
01699 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
01700 QFileInfo fi((*it));
01701 QString dir;
01702 if(fi.dirPath() != ".")
01703 dir = fi.dirPath() + Option::dir_sep;
01704 dir = fileFixify(dir, QDir::currentDirPath(), Option::output_dir);
01705 if(!dir.isEmpty() && dir.right(Option::dir_sep.length()) != Option::dir_sep)
01706 dir += Option::dir_sep;
01707
01708 QString impl = dir + fi.baseName(TRUE) + Option::yacc_mod + Option::cpp_ext.first();
01709 QString decl = dir + fi.baseName(TRUE) + Option::yacc_mod + Option::h_ext.first();
01710
01711 QString yaccflags = "$(YACCFLAGS)", mangle = "y";
01712 if(!project->isActiveConfig("yacc_no_name_mangle")) {
01713 mangle = fi.baseName(TRUE);
01714 if(!project->isEmpty("QMAKE_YACCFLAGS_MANGLE"))
01715 yaccflags += " " + var("QMAKE_YACCFLAGS_MANGLE").replace(stringBase, mangle);
01716 else
01717 yaccflags += " -p " + mangle;
01718 }
01719 QString out_h = default_out_h, out_c = default_out_c;
01720 if(!mangle.isEmpty()) {
01721 out_h.replace(stringBase, mangle);
01722 out_c.replace(stringBase, mangle);
01723 }
01724
01725 t << impl << ": " << (*it) << "\n\t"
01726 << "$(YACC) " << yaccflags << " " << (*it) << "\n\t"
01727 << "-$(DEL_FILE) " << impl << " " << decl << "\n\t"
01728 << "-$(MOVE) " << out_h << " " << decl << "\n\t"
01729 << "-$(MOVE) " << out_c << " " << impl << endl << endl;
01730 t << decl << ": " << impl << endl << endl;
01731 }
01732 }
01733
01734 void
01735 MakefileGenerator::writeLexSrc(QTextStream &t, const QString &src)
01736 {
01737 QStringList &l = project->variables()[src];
01738 if(project->isActiveConfig("yacc_no_name_mangle") && l.count() > 1)
01739 warn_msg(WarnLogic, "yacc_no_name_mangle specified, but multiple parsers expected.\n"
01740 "This can lead to link problems.\n");
01741 QString default_out_c = "lex.$base.c";
01742 if(!project->isEmpty("QMAKE_LEX_SOURCE"))
01743 default_out_c = project->first("QMAKE_LEX_SOURCE");
01744 QString stringBase("$base");
01745 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
01746 QFileInfo fi((*it));
01747 QString dir;
01748 if(fi.dirPath() != ".")
01749 dir = fi.dirPath() + Option::dir_sep;
01750 dir = fileFixify(dir, QDir::currentDirPath(), Option::output_dir);
01751 if(!dir.isEmpty() && dir.right(Option::dir_sep.length()) != Option::dir_sep)
01752 dir += Option::dir_sep;
01753 QString impl = dir + fi.baseName(TRUE) + Option::lex_mod + Option::cpp_ext.first();
01754
01755 QString lexflags = "$(LEXFLAGS)", stub="yy";
01756 if(!project->isActiveConfig("yacc_no_name_mangle")) {
01757 stub = fi.baseName(TRUE);
01758 lexflags += " -P" + stub;
01759 }
01760 QString out_c = default_out_c;
01761 if(!stub.isEmpty())
01762 out_c.replace(stringBase, stub);
01763
01764 t << impl << ": " << (*it) << " " << findDependencies((*it)).join(" \\\n\t\t") << "\n\t"
01765 << ( "$(LEX) " + lexflags + " " ) << (*it) << "\n\t"
01766 << "-$(DEL_FILE) " << impl << " " << "\n\t"
01767 << "-$(MOVE) " << out_c << " " << impl << endl << endl;
01768 }
01769 }
01770
01771 void
01772 MakefileGenerator::writeImageObj(QTextStream &t, const QString &obj)
01773 {
01774 QStringList &objl = project->variables()[obj];
01775 QString stringSrc("$src");
01776 QString stringObj("$obj");
01777
01778 QString uidir;
01779 for(QStringList::Iterator oit = objl.begin(); oit != objl.end(); oit++) {
01780 QString src(project->first("QMAKE_IMAGE_COLLECTION"));
01781 t << (*oit) << ": " << src;
01782 bool use_implicit_rule = !project->isEmpty("QMAKE_RUN_CXX_IMP");
01783 if(use_implicit_rule) {
01784 if(!project->isEmpty("OBJECTS_DIR") || !project->isEmpty("UI_DIR") || !project->isEmpty("UI_SOURCES_DIR")) {
01785 use_implicit_rule = FALSE;
01786 } else {
01787 int dot = src.findRev('.');
01788 if(dot == -1 || (src.left(dot) + Option::obj_ext != (*oit)))
01789 use_implicit_rule = FALSE;
01790 }
01791 }
01792 if(!use_implicit_rule && !project->isEmpty("QMAKE_RUN_CXX")) {
01793 QString p = var("QMAKE_RUN_CXX"), srcf(src);
01794 p.replace(stringSrc, srcf);
01795 p.replace(stringObj, (*oit));
01796 t << "\n\t" << p;
01797 }
01798 t << endl << endl;
01799 }
01800 }
01801
01802
01803 void
01804 MakefileGenerator::writeImageSrc(QTextStream &t, const QString &src)
01805 {
01806 QStringList &l = project->variables()[src];
01807 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
01808 QString gen = project->first("MAKEFILE_GENERATOR");
01809 if ( gen == "MSVC" ) {
01810 t << (*it) << ": " << findDependencies((*it)).join(" \\\n\t\t") << "\n\t"
01811 << "$(UIC) -o " << (*it) << " -embed " << project->first("QMAKE_ORIG_TARGET")
01812 << " -f <<\n" << findDependencies((*it)).join(" ") << "\n<<" << endl << endl;
01813 } else if ( gen == "BMAKE" ) {
01814 t << (*it) << ": " << findDependencies((*it)).join(" \\\n\t\t") << "\n\t"
01815 << "$(UIC) " << " -embed " << project->first("QMAKE_ORIG_TARGET")
01816 << " -f &&|\n" << findDependencies((*it)).join(" ") << "\n| -o " << (*it) << endl << endl;
01817 } else {
01818 t << (*it) << ": " << findDependencies((*it)).join(" \\\n\t\t") << "\n\t"
01819 << "$(UIC) " << " -embed " << project->first("QMAKE_ORIG_TARGET")
01820 << " " << findDependencies((*it)).join(" ") << " -o " << (*it) << endl << endl;
01821 }
01822 }
01823 }
01824
01825
01826 void
01827 MakefileGenerator::writeInstalls(QTextStream &t, const QString &installs)
01828 {
01829 QString all_installs, all_uninstalls;
01830 QStringList &l = project->variables()[installs];
01831 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
01832 QString pvar = (*it) + ".path";
01833 if(project->variables()[(*it) + ".CONFIG"].findIndex("no_path") == -1 &&
01834 project->variables()[pvar].isEmpty()) {
01835 warn_msg(WarnLogic, "%s is not defined: install target not created\n", pvar.latin1());
01836 continue;
01837 }
01838
01839 bool do_default = TRUE;
01840 const QString root = "$(INSTALL_ROOT)";
01841 QString target, dst= fileFixify(project->variables()[pvar].first());
01842 if(dst.right(1) != Option::dir_sep)
01843 dst += Option::dir_sep;
01844 QStringList tmp, uninst = project->variables()[(*it) + ".uninstall"];
01845
01846 tmp = project->variables()[(*it) + ".extra"];
01847 if(tmp.isEmpty())
01848 tmp = project->variables()[(*it) + ".commands"];
01849 if(!tmp.isEmpty()) {
01850 do_default = FALSE;
01851 if(!target.isEmpty())
01852 target += "\n\t";
01853 target += tmp.join(" ");
01854 }
01855
01856 tmp = project->variables()[(*it) + ".files"];
01857 if(!tmp.isEmpty()) {
01858 if(!target.isEmpty())
01859 target += "\n";
01860 do_default = FALSE;
01861 for(QStringList::Iterator wild_it = tmp.begin(); wild_it != tmp.end(); ++wild_it) {
01862 QString wild = Option::fixPathToLocalOS((*wild_it), FALSE), wild_var = fileFixify(wild);
01863 QString dirstr = QDir::currentDirPath(), filestr = wild;
01864 int slsh = filestr.findRev(Option::dir_sep);
01865 if(slsh != -1) {
01866 dirstr = filestr.left(slsh+1);
01867 filestr = filestr.right(filestr.length() - slsh - 1);
01868 }
01869 if(dirstr.right(Option::dir_sep.length()) != Option::dir_sep)
01870 dirstr += Option::dir_sep;
01871 if(QFile::exists(wild)) {
01872 QString file = wild;
01873 QFileInfo fi(wild);
01874 if(!target.isEmpty())
01875 target += "\t";
01876 QString cmd = QString(fi.isDir() ? "-$(INSTALL_DIR)" : "-$(INSTALL_FILE)") + " \"" +
01877 Option::fixPathToTargetOS(fileFixify(wild, QString::null,
01878 QString::null, FALSE, FALSE), FALSE) +
01879 "\" \"" + root + dst + "\"\n";
01880 target += cmd;
01881 if(!project->isActiveConfig("debug") &&
01882 !fi.isDir() && fi.isExecutable() && !project->isEmpty("QMAKE_STRIP"))
01883 target += QString("\t-") + var("QMAKE_STRIP") + " \"" +
01884 root + fileFixify(dst + filestr, QString::null, QString::null, FALSE, FALSE) +
01885 "\"\n";
01886 if(!uninst.isEmpty())
01887 uninst.append("\n\t");
01888 uninst.append(
01889 #ifdef Q_WS_WIN
01890 QString("-$(DEL_FILE)")
01891 #else
01892 QString("-$(DEL_FILE) -r")
01893 #endif
01894 + " \"" + root + fileFixify(dst + filestr, QString::null, QString::null, FALSE, FALSE) + "\"");
01895 continue;
01896 }
01897 fixEnvVariables(dirstr);
01898 QDir dir(dirstr, filestr);
01899 for(uint x = 0; x < dir.count(); x++) {
01900 QString file = dir[x];
01901 if(file == "." || file == "..")
01902 continue;
01903 if(!uninst.isEmpty())
01904 uninst.append("\n\t");
01905 uninst.append(
01906 #ifdef Q_WS_WIN
01907 QString("-$(DEL_FILE)")
01908 #else
01909 QString("-$(DEL_FILE) -r")
01910 #endif
01911 + " \"" + root + fileFixify(dst + file, QString::null, QString::null, FALSE, FALSE) +
01912 "\"");
01913 QFileInfo fi(Option::fixPathToTargetOS(fileFixify(dirstr + file), TRUE));
01914 if(!target.isEmpty())
01915 target += "\t";
01916 QString cmd = QString(fi.isDir() ? "-$(INSTALL_DIR)" : "-$(INSTALL_FILE)") + " \"" +
01917 Option::fixPathToTargetOS(fileFixify(dirstr + file, QString::null,
01918 QString::null, FALSE, FALSE), FALSE) +
01919 "\" \"" + root + dst + "\"\n";
01920 target += cmd;
01921 if(!project->isActiveConfig("debug") &&
01922 !fi.isDir() && fi.isExecutable() && !project->isEmpty("QMAKE_STRIP"))
01923 target += QString("\t-") + var("QMAKE_STRIP") + " \"" +
01924 root + fileFixify(dst + file, QString::null, QString::null, FALSE, FALSE) +
01925 "\"\n";
01926 }
01927 }
01928 }
01929
01930 if(do_default) {
01931 target = defaultInstall((*it));
01932 uninst = project->variables()[(*it) + ".uninstall"];
01933 }
01934
01935 if(!target.isEmpty()) {
01936 t << "install_" << (*it) << ": all ";
01937 const QStringList &deps = project->variables()[(*it) + ".depends"];
01938 if(!deps.isEmpty()) {
01939 for(QStringList::ConstIterator dep_it = deps.begin(); dep_it != deps.end(); ++dep_it) {
01940 QString targ = var((*dep_it) + ".target");
01941 if(targ.isEmpty())
01942 targ = (*dep_it);
01943 t << targ;
01944 }
01945 }
01946 t << "\n\t";
01947 const QStringList &dirs = project->variables()[pvar];
01948 for(QStringList::ConstIterator pit = dirs.begin(); pit != dirs.end(); ++pit) {
01949 QString tmp_dst = fileFixify((*pit));
01950 #ifndef Q_WS_WIN
01951 if(tmp_dst.right(1) != Option::dir_sep)
01952 tmp_dst += Option::dir_sep;
01953 #endif
01954 t << mkdir_p_asstring(root+tmp_dst) << "\n\t";
01955 }
01956 t << target << endl << endl;
01957 if(!uninst.isEmpty()) {
01958 t << "uninstall_" << (*it) << ": " << "\n\t"
01959 << uninst.join("") << "\n\t"
01960 << "-$(DEL_DIR) \"" << ( root + dst ) << "\"" << endl << endl;
01961 }
01962 t << endl;
01963
01964 if(project->variables()[(*it) + ".CONFIG"].findIndex("no_default_install") == -1) {
01965 all_installs += QString("install_") + (*it) + " ";
01966 if(!uninst.isEmpty())
01967 all_uninstalls += "uninstall_" + (*it) + " ";
01968 }
01969 } else {
01970 debug_msg(1, "no definition for install %s: install target not created",(*it).latin1());
01971 }
01972 }
01973 t << "install: " << all_installs << " " << var("INSTALLDEPS") << "\n\n";
01974 t << "uninstall: " << all_uninstalls << " " << var("UNINSTALLDEPS") << "\n\n";
01975 }
01976
01977 QString
01978 MakefileGenerator::var(const QString &var)
01979 {
01980 return val(project->variables()[var]);
01981 }
01982
01983 QString
01984 MakefileGenerator::val(const QStringList &varList)
01985 {
01986 return valGlue(varList, "", " ", "");
01987 }
01988
01989 QString
01990 MakefileGenerator::varGlue(const QString &var, const QString &before, const QString &glue, const QString &after)
01991 {
01992 return valGlue(project->variables()[var], before, glue, after);
01993 }
01994
01995 QString
01996 MakefileGenerator::valGlue(const QStringList &varList, const QString &before, const QString &glue, const QString &after)
01997 {
01998 QString ret;
01999 for(QStringList::ConstIterator it = varList.begin(); it != varList.end(); ++it) {
02000 if(!(*it).isEmpty()) {
02001 if(!ret.isEmpty())
02002 ret += glue;
02003 ret += (*it);
02004 }
02005 }
02006 return ret.isEmpty() ? QString("") : before + ret + after;
02007 }
02008
02009
02010 QString
02011 MakefileGenerator::varList(const QString &var)
02012 {
02013 return valList(project->variables()[var]);
02014 }
02015
02016 QString
02017 MakefileGenerator::valList(const QStringList &varList)
02018 {
02019 return valGlue(varList, "", " \\\n\t\t", "");
02020 }
02021
02022
02023 QStringList
02024 MakefileGenerator::createObjectList(const QString &var)
02025 {
02026 QStringList &l = project->variables()[var], ret;
02027 QString objdir, dir;
02028 if(!project->variables()["OBJECTS_DIR"].isEmpty())
02029 objdir = project->first("OBJECTS_DIR");
02030 for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
02031 QFileInfo fi(Option::fixPathToLocalOS((*it)));
02032 if(objdir.isEmpty() && project->isActiveConfig("object_with_source")) {
02033 QString fName = Option::fixPathToTargetOS((*it), FALSE);
02034 int dl = fName.findRev(Option::dir_sep);
02035 if(dl != -1)
02036 dir = fName.left(dl + 1);
02037 } else {
02038 dir = objdir;
02039 }
02040 ret.append(dir + fi.baseName(TRUE) + Option::obj_ext);
02041 }
02042 return ret;
02043 }
02044
02045 bool
02046 MakefileGenerator::writeMakefile(QTextStream &t)
02047 {
02048 t << "####### Compile" << endl << endl;
02049 writeObj(t, "OBJECTS", "SOURCES");
02050 writeUicSrc(t, "FORMS");
02051 writeObj(t, "UICOBJECTS", "UICIMPLS");
02052 writeMocObj(t, "OBJMOC", "SRCMOC" );
02053 writeMocSrc(t, "HEADERS");
02054 writeMocSrc(t, "SOURCES");
02055 writeMocSrc(t, "UICDECLS");
02056 writeYaccSrc(t, "YACCSOURCES");
02057 writeLexSrc(t, "LEXSOURCES");
02058 writeImageObj(t, "IMAGEOBJECTS");
02059 writeImageSrc(t, "QMAKE_IMAGE_COLLECTION");
02060
02061 t << "####### Install" << endl << endl;
02062 writeInstalls(t, "INSTALLS");
02063 return TRUE;
02064 }
02065
02066 QString MakefileGenerator::buildArgs()
02067 {
02068 static QString ret;
02069 if(ret.isEmpty()) {
02070
02071 if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH"))
02072 ret += " QMAKE_ABSOLUTE_SOURCE_PATH=\"" + project->first("QMAKE_ABSOLUTE_SOURCE_PATH") + "\"";
02073
02074
02075 else if(Option::warn_level == WarnNone)
02076 ret += " -Wnone";
02077 else if(Option::warn_level == WarnAll)
02078 ret += " -Wall";
02079 else if(Option::warn_level & WarnParser)
02080 ret += " -Wparser";
02081
02082 if(!Option::user_template.isEmpty())
02083 ret += " -t " + Option::user_template;
02084 if(!Option::mkfile::do_cache)
02085 ret += " -nocache";
02086 if(!Option::mkfile::do_deps)
02087 ret += " -nodepend";
02088 if(!Option::mkfile::do_mocs)
02089 ret += " -nomoc";
02090 if(!Option::mkfile::do_dep_heuristics)
02091 ret += " -nodependheuristics";
02092 if(!Option::mkfile::qmakespec_commandline.isEmpty())
02093 ret += " -spec " + Option::mkfile::qmakespec_commandline;
02094
02095
02096 for(QStringList::Iterator it = Option::before_user_vars.begin();
02097 it != Option::before_user_vars.end(); ++it) {
02098 if((*it).left(qstrlen("QMAKE_ABSOLUTE_SOURCE_PATH")) != "QMAKE_ABSOLUTE_SOURCE_PATH")
02099 ret += " \"" + (*it) + "\"";
02100 }
02101 if(Option::after_user_vars.count()) {
02102 ret += " -after ";
02103 for(QStringList::Iterator it = Option::after_user_vars.begin();
02104 it != Option::after_user_vars.end(); ++it) {
02105 if((*it).left(qstrlen("QMAKE_ABSOLUTE_SOURCE_PATH")) != "QMAKE_ABSOLUTE_SOURCE_PATH")
02106 ret += " \"" + (*it) + "\"";
02107 }
02108 }
02109 }
02110 return ret;
02111 }
02112
02113
02114
02115 QString MakefileGenerator::build_args()
02116 {
02117 static QString ret;
02118 if(ret.isEmpty()) {
02119 ret = "$(QMAKE)";
02120
02121
02122 ret += buildArgs();
02123
02124
02125 QString ofile = Option::fixPathToTargetOS(fileFixify(Option::output.name()));
02126 if (!ofile.isEmpty() && ofile != project->first("QMAKE_MAKEFILE"))
02127 ret += " -o " + ofile;
02128
02129
02130 QStringList files = fileFixify(Option::mkfile::project_files);
02131 ret += " " + files.join(" ");
02132 }
02133 return ret;
02134 }
02135
02136 bool
02137 MakefileGenerator::writeHeader(QTextStream &t)
02138 {
02139 time_t foo = time(NULL);
02140 t << "#############################################################################" << endl;
02141 t << "# Makefile for building: " << var("TARGET") << endl;
02142 t << "# Generated by qmake (" << qmake_version() << ") (Qt " << QT_VERSION_STR << ") on: " << ctime(&foo);
02143 t << "# Project: " << fileFixify(project->projectFile()) << endl;
02144 t << "# Template: " << var("TEMPLATE") << endl;
02145 t << "# Command: " << build_args() << endl;
02146 t << "#############################################################################" << endl;
02147 t << endl;
02148 return TRUE;
02149 }
02150
02151
02152
02153 bool
02154 MakefileGenerator::writeMakeQmake(QTextStream &t)
02155 {
02156 QString ofile = Option::fixPathToTargetOS(fileFixify(Option::output.name()));
02157 if(project->isEmpty("QMAKE_FAILED_REQUIREMENTS") && !project->isActiveConfig("no_autoqmake") &&
02158 !project->isEmpty("QMAKE_INTERNAL_PRL_FILE")) {
02159 QStringList files = fileFixify(Option::mkfile::project_files);
02160 t << project->first("QMAKE_INTERNAL_PRL_FILE") << ": " << "\n\t"
02161 << "@$(QMAKE) -prl " << buildArgs() << " " << files.join(" ") << endl;
02162 }
02163
02164 QString pfile = project->projectFile();
02165 if(pfile != "(stdin)") {
02166 QString qmake = build_args();
02167 if(!ofile.isEmpty() && !project->isActiveConfig("no_autoqmake")) {
02168 t << ofile << ": " << fileFixify(pfile) << " ";
02169 if(Option::mkfile::do_cache)
02170 t << fileFixify(Option::mkfile::cachefile) << " ";
02171 if(!specdir().isEmpty()) {
02172 if (QFile::exists(Option::fixPathToLocalOS(specdir()+QDir::separator()+"qmake.conf")))
02173 t << specdir() << Option::dir_sep << "qmake.conf" << " ";
02174 else if (QFile::exists(Option::fixPathToLocalOS(specdir()+QDir::separator()+"tmake.conf")))
02175 t << specdir() << Option::dir_sep << "tmake.conf" << " ";
02176 }
02177 t << project->variables()["QMAKE_INTERNAL_INCLUDED_FILES"].join(" \\\n\t\t") << "\n\t"
02178 << qmake <<endl;
02179 }
02180 if(project->first("QMAKE_ORIG_TARGET") != "qmake") {
02181 t << "qmake: " <<
02182 project->variables()["QMAKE_INTERNAL_QMAKE_DEPS"].join(" \\\n\t\t") << "\n\t"
02183 << "@" << qmake << endl << endl;
02184 }
02185 }
02186 return TRUE;
02187 }
02188
02189 QStringList
02190 MakefileGenerator::fileFixify(const QStringList& files, const QString &out_dir, const QString &in_dir,
02191 bool force_fix, bool canon) const
02192 {
02193 if(files.isEmpty())
02194 return files;
02195 QStringList ret;
02196 for(QStringList::ConstIterator it = files.begin(); it != files.end(); ++it) {
02197 if(!(*it).isEmpty())
02198 ret << fileFixify((*it), out_dir, in_dir, force_fix, canon);
02199 }
02200 return ret;
02201 }
02202
02203 QString
02204 MakefileGenerator::fileFixify(const QString& file0, const QString &out_d,
02205 const QString &in_d, bool force_fix, bool canon) const
02206 {
02207 if(file0.isEmpty())
02208 return file0;
02209 QString key = file0;
02210 if(QDir::isRelativePath(file0))
02211 key.prepend(QDir::currentDirPath() + "--");
02212 if(!in_d.isEmpty() || !out_d.isEmpty() || force_fix || !canon)
02213 key.prepend(in_d + "--" + out_d + "--" + QString::number((int)force_fix) + "--" +
02214 QString::number((int)canon) + "-");
02215 if(fileFixed.contains(key))
02216 return fileFixed[key];
02217
02218 QString file = file0;
02219 int depth = 4;
02220 if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
02221 Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
02222 if(project && !project->isEmpty("QMAKE_PROJECT_DEPTH"))
02223 depth = project->first("QMAKE_PROJECT_DEPTH").toInt();
02224 else if(Option::mkfile::cachefile_depth != -1)
02225 depth = Option::mkfile::cachefile_depth;
02226 }
02227
02228 QChar quote;
02229 if((file.startsWith("'") || file.startsWith("\"")) && file.startsWith(file.right(1))) {
02230 quote = file.at(0);
02231 file = file.mid(1, file.length() - 2);
02232 }
02233 QString orig_file = file;
02234 if(!force_fix && project->isActiveConfig("no_fixpath")) {
02235 if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH")) {
02236 QString qfile = Option::fixPathToLocalOS(file, TRUE, canon);
02237 if(QDir::isRelativePath(file)) {
02238 QFileInfo fi(qfile);
02239 if(!fi.convertToAbs())
02240 file = fi.filePath();
02241 }
02242 }
02243 } else {
02244 QString qfile(Option::fixPathToLocalOS(file, TRUE, canon)), in_dir(in_d), out_dir(out_d);
02245 {
02246 if(out_dir.isNull() || QDir::isRelativePath(out_dir))
02247 out_dir.prepend(Option::output_dir + QDir::separator());
02248 if(out_dir == ".")
02249 out_dir = QDir::currentDirPath();
02250 if(in_dir.isEmpty() || QDir::isRelativePath(in_dir))
02251 in_dir.prepend(QDir::currentDirPath() + QDir::separator());
02252 if(in_dir == ".")
02253 in_dir = QDir::currentDirPath();
02254
02255 if(!QDir::isRelativePath(in_dir) || !QDir::isRelativePath(out_dir)) {
02256 QFileInfo in_fi(in_dir);
02257 if(!in_fi.convertToAbs())
02258 in_dir = in_fi.filePath();
02259 QFileInfo out_fi(out_dir);
02260 if(!out_fi.convertToAbs())
02261 out_dir = out_fi.filePath();
02262 }
02263 QString in_canonical_dir = QDir(in_dir).canonicalPath(),
02264 out_canonical_dir = QDir(out_dir).canonicalPath();
02265 if(!in_canonical_dir.isEmpty())
02266 in_dir = in_canonical_dir;
02267 if(!out_canonical_dir.isEmpty())
02268 out_dir = out_canonical_dir;
02269 }
02270 if(out_dir != in_dir || !QDir::isRelativePath(qfile)) {
02271 if(QDir::isRelativePath(qfile)) {
02272 if(file.left(Option::dir_sep.length()) != Option::dir_sep &&
02273 in_dir.right(Option::dir_sep.length()) != Option::dir_sep)
02274 file.prepend(Option::dir_sep);
02275 file.prepend(in_dir);
02276 }
02277 file = Option::fixPathToTargetOS(file, FALSE, canon);
02278 if(canon && QFile::exists(file) && file == Option::fixPathToTargetOS(file, TRUE, canon)) {
02279 QString real_file = QDir(file).canonicalPath();
02280 if(!real_file.isEmpty())
02281 file = real_file;
02282 }
02283 QString match_dir = Option::fixPathToTargetOS(out_dir, FALSE, canon);
02284 if(file == match_dir) {
02285 file = "";
02286 } else if(file.startsWith(match_dir) &&
02287 file.mid(match_dir.length(), Option::dir_sep.length()) == Option::dir_sep) {
02288 file = file.right(file.length() - (match_dir.length() + 1));
02289 } else {
02290 for(int i = 1; i <= depth; i++) {
02291 int sl = match_dir.findRev(Option::dir_sep);
02292 if(sl == -1)
02293 break;
02294 match_dir = match_dir.left(sl);
02295 if(match_dir.isEmpty())
02296 break;
02297 if(file.startsWith(match_dir) &&
02298 file.mid(match_dir.length(), Option::dir_sep.length()) == Option::dir_sep) {
02299
02300 int remlen = file.length() - (match_dir.length() + 1);
02301 if (remlen < 0)
02302 remlen = 0;
02303 file = file.right(remlen);
02304
02305 for(int o = 0; o < i; o++)
02306 file.prepend(".." + Option::dir_sep);
02307 }
02308 }
02309 }
02310 }
02311 }
02312 file = Option::fixPathToTargetOS(file, FALSE, canon);
02313 if(file.isEmpty())
02314 file = ".";
02315 if(!quote.isNull())
02316 file = quote + file + quote;
02317 debug_msg(3, "Fixed %s :: to :: %s (%d) [%s::%s]", orig_file.latin1(), file.latin1(), depth,
02318 in_d.latin1(), out_d.latin1());
02319 ((MakefileGenerator*)this)->fileFixed.insert(key, file);
02320 return file;
02321 }
02322
02323 QString
02324 MakefileGenerator::cleanFilePath(const QString &file) const
02325 {
02326 return fileFixify(Option::fixPathToTargetOS(file));
02327 }
02328
02329 void MakefileGenerator::logicWarn(const QString &f, const QString &w)
02330 {
02331 if(!(Option::warn_level & WarnLogic))
02332 return;
02333 QString file = f;
02334 int slsh = f.findRev(Option::dir_sep);
02335 if(slsh != -1)
02336 file = file.right(file.length() - slsh - 1);
02337 QStringList &l = project->variables()[w];
02338 for(QStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) {
02339 QString file2((*val_it));
02340 slsh = file2.findRev(Option::dir_sep);
02341 if(slsh != -1)
02342 file2 = file2.right(file2.length() - slsh - 1);
02343 if(file2 == file) {
02344 warn_msg(WarnLogic, "Found potential symbol conflict of %s (%s) in %s",
02345 file.latin1(), (*val_it).latin1(), w.latin1());
02346 break;
02347 }
02348 }
02349 }
02350
02351 QString
02352 MakefileGenerator::dependencyKey(const QString &file) const
02353 {
02354 QString key = file;
02355 Option::fixPathToTargetOS(key);
02356 if(key.find(Option::dir_sep))
02357 key = key.right(key.length() - key.findRev(Option::dir_sep) - 1);
02358 return key;
02359 }
02360
02361 void
02362 MakefileGenerator::setProcessedDependencies(const QString &file, bool b)
02363 {
02364 depProcessed[dependencyKey(file)] = b;
02365 }
02366
02367 bool
02368 MakefileGenerator::processedDependencies(const QString &file)
02369 {
02370 QString key = dependencyKey(file);
02371 if(!depProcessed.contains(key))
02372 return FALSE;
02373 return depProcessed[key];
02374 }
02375
02376 QStringList
02377 &MakefileGenerator::findDependencies(const QString &file)
02378 {
02379 return depends[dependencyKey(file)];
02380 }
02381
02382
02383 QString
02384 MakefileGenerator::specdir()
02385 {
02386 if(!spec.isEmpty())
02387 return spec;
02388 spec = Option::mkfile::qmakespec;
02389 #if 0
02390 if(const char *d = getenv("QTDIR")) {
02391 QString qdir = Option::fixPathToTargetOS(QString(d));
02392 if(qdir.endsWith(QString(QChar(QDir::separator()))))
02393 qdir.truncate(qdir.length()-1);
02394
02395 QFileInfo fi(spec);
02396 QString absSpec(fi.absFilePath());
02397 absSpec = Option::fixPathToTargetOS(absSpec);
02398
02399 if(absSpec.startsWith(qdir)) {
02400 absSpec.replace(0, qdir.length(), "$(QTDIR)");
02401 spec = absSpec;
02402 }
02403 }
02404 #else
02405 spec = Option::fixPathToTargetOS(spec);
02406 #endif
02407 return spec;
02408 }
02409
02410 bool
02411 MakefileGenerator::openOutput(QFile &file) const
02412 {
02413 {
02414 QString outdir;
02415 if(!file.name().isEmpty()) {
02416 if(QDir::isRelativePath(file.name()))
02417 file.setName(Option::output_dir + file.name());
02418 QFileInfo fi(file);
02419 if(fi.isDir())
02420 outdir = file.name() + QDir::separator();
02421 }
02422 if(!outdir.isEmpty() || file.name().isEmpty()) {
02423 QString fname = "Makefile";
02424 if(!project->isEmpty("MAKEFILE"))
02425 fname = project->first("MAKEFILE");
02426 file.setName(outdir + fname);
02427 }
02428 }
02429 if(QDir::isRelativePath(file.name()))
02430 file.setName(Option::output_dir + file.name());
02431 if(project->isEmpty("QMAKE_MAKEFILE"))
02432 project->variables()["QMAKE_MAKEFILE"].append(file.name());
02433 int slsh = file.name().findRev(Option::dir_sep);
02434 if(slsh != -1)
02435 createDir(file.name().left(slsh));
02436 if(file.open(IO_WriteOnly | IO_Translate)) {
02437 QFileInfo fi(Option::output);
02438 QString od = Option::fixPathToTargetOS((fi.isSymLink() ? fi.readLink() : fi.dirPath()) );
02439 if(QDir::isRelativePath(od))
02440 od.prepend(Option::output_dir);
02441 Option::output_dir = od;
02442 return TRUE;
02443 }
02444 return FALSE;
02445 }
02446
02447
02448
02449
02450 #include "unixmake.h"
02451 #include "msvc_nmake.h"
02452 #include "borland_bmake.h"
02453 #include "mingw_make.h"
02454 #include "msvc_dsp.h"
02455 #include "msvc_vcproj.h"
02456 #include "metrowerks_xml.h"
02457 #include "pbuilder_pbx.h"
02458 #include "projectgenerator.h"
02459
02460 MakefileGenerator *
02461 MakefileGenerator::create(QMakeProject *proj)
02462 {
02463 if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT)
02464 return new ProjectGenerator(proj);
02465
02466 MakefileGenerator *mkfile = NULL;
02467 QString gen = proj->first("MAKEFILE_GENERATOR");
02468 if(gen.isEmpty()) {
02469 fprintf(stderr, "No generator specified in config file: %s\n",
02470 proj->projectFile().latin1());
02471 } else if(gen == "UNIX") {
02472 mkfile = new UnixMakefileGenerator(proj);
02473 } else if(gen == "MSVC") {
02474
02475 if(proj->first("TEMPLATE").find(QRegExp("^vc.*")) != -1)
02476 mkfile = new DspMakefileGenerator(proj);
02477 else
02478 mkfile = new NmakeMakefileGenerator(proj);
02479 } else if(gen == "MSVC.NET") {
02480
02481 if(proj->first("TEMPLATE").find(QRegExp("^vc.*")) != -1)
02482 mkfile = new VcprojGenerator(proj);
02483 else
02484 mkfile = new NmakeMakefileGenerator(proj);
02485 } else if(gen == "BMAKE") {
02486 mkfile = new BorlandMakefileGenerator(proj);
02487 } else if(gen == "MINGW") {
02488 mkfile = new MingwMakefileGenerator(proj);
02489 } else if(gen == "METROWERKS") {
02490 mkfile = new MetrowerksMakefileGenerator(proj);
02491 } else if(gen == "PROJECTBUILDER") {
02492 mkfile = new ProjectBuilderMakefileGenerator(proj);
02493 } else {
02494 fprintf(stderr, "Unknown generator specified: %s\n", gen.latin1());
02495 }
02496 return mkfile;
02497 }