-rw-r--r-- | qmake/project.cpp | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/qmake/project.cpp b/qmake/project.cpp index ae24193..96cdad8 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -252,405 +252,412 @@ QMakeProject::parse(QString t, QMap<QString, QStringList> &place) if(!var.isEmpty()) qmake_error_msg("Parse Error ('" + s + "')"); return var.isEmpty(); /* allow just a scope */ } SKIP_WS(d); for( ; *d && op.find('=') == -1; op += *(d++)); op.replace(QRegExp("\\s"), ""); SKIP_WS(d); QString vals(d); /* vals now contains the space separated list of values */ int rbraces = vals.contains('}'), lbraces = vals.contains('{'); if(scope_block && rbraces - lbraces == 1) { debug_msg(1, "Project Parser: %s:%d : Leaving block %d", parser.file.latin1(), parser.line_no, scope_block); test_status = ((scope_flag & (0x01 << scope_block)) ? TestFound : TestSeek); scope_block--; vals.truncate(vals.length()-1); } else if(rbraces != lbraces) { warn_msg(WarnParser, "Possible braces mismatch {%s} %s:%d", vals.latin1(), parser.file.latin1(), parser.line_no); } doVariableReplace(vals, place); var = var.stripWhiteSpace(); #undef SKIP_WS if(!var.isEmpty() && Option::mkfile::do_preprocess) { static QString last_file("*none*"); if(parser.file != last_file) { fprintf(stderr, "#file %s:%d\n", parser.file.latin1(), parser.line_no); last_file = parser.file; } fprintf(stderr, "%s %s %s\n", var.latin1(), op.latin1(), vals.latin1()); } var = varMap(var); //backwards compatability /* vallist is the broken up list of values */ QStringList vallist = split_value_list(vals, (var == "DEPENDPATH" || var == "INCLUDEPATH")); if(!vallist.grep("=").isEmpty()) warn_msg(WarnParser, "Detected possible line continuation: {%s} %s:%d", var.latin1(), parser.file.latin1(), parser.line_no); QStringList &varlist = place[var]; /* varlist is the list in the symbol table */ debug_msg(1, "Project Parser: %s:%d :%s: :%s: (%s)", parser.file.latin1(), parser.line_no, var.latin1(), op.latin1(), vallist.join(" :: ").latin1()); /* now do the operation */ if(op == "~=") { if(vallist.count() != 1) { qmake_error_msg("~= operator only accepts one right hand paramater ('" + s + "')"); return FALSE; } QString val(vallist.first()); if(val.length() < 4 || val.at(0) != 's') { qmake_error_msg("~= operator only can handle s/// function ('" + s + "')"); return FALSE; } QChar sep = val.at(1); QStringList func = QStringList::split(sep, val, TRUE); if(func.count() < 3 || func.count() > 4) { qmake_error_msg("~= operator only can handle s/// function ('" + s + "')"); return FALSE; } bool global = FALSE, case_sense = TRUE; if(func.count() == 4) { global = func[3].find('g') != -1; case_sense = func[3].find('i') == -1; } QRegExp regexp(func[1], case_sense); for(QStringList::Iterator varit = varlist.begin(); varit != varlist.end(); ++varit) { if((*varit).contains(regexp)) { (*varit) = (*varit).replace(regexp, func[2]); if(!global) break; } } } else { if(op == "=") { if(!varlist.isEmpty()) warn_msg(WarnParser, "Operator=(%s) clears variables previously set: %s:%d", var.latin1(), parser.file.latin1(), parser.line_no); varlist.clear(); } for(QStringList::Iterator valit = vallist.begin(); valit != vallist.end(); ++valit) { if((*valit).isEmpty()) continue; if((op == "*=" && !(*varlist.find((*valit)))) || op == "=" || op == "+=") varlist.append((*valit)); else if(op == "-=") varlist.remove((*valit)); } } if(var == "REQUIRES") /* special case to get communicated to backends! */ doProjectCheckReqs(vallist, place); return TRUE; } bool QMakeProject::read(QString file, QMap<QString, QStringList> &place) { parser_info pi = parser; /* scope blocks start at true */ test_status = TestNone; scope_flag = 0x01; scope_block = 0; file = Option::fixPathToLocalOS(file); doVariableReplace(file, place); bool ret = FALSE, using_stdin = FALSE; QFile qfile; if(!strcmp(file, "-")) { qfile.setName(""); ret = qfile.open(IO_ReadOnly, stdin); using_stdin = TRUE; } else { qfile.setName(file); ret = qfile.open(IO_ReadOnly); } if ( ret ) { QTextStream t( &qfile ); QString s, line; parser.file = file; parser.line_no = 0; while ( !t.eof() ) { parser.line_no++; line = t.readLine().stripWhiteSpace(); int prelen = line.length(); line.replace(QRegExp("#.*$"), ""); // bye comments if(!line.isEmpty() && line.right(1) == "\\") { line.truncate(line.length() - 1); s += line + " "; } else if(!line.isEmpty() || (line.isEmpty() && !prelen)) { if(s.isEmpty() && line.isEmpty()) continue; if(!line.isEmpty()) s += line; if(!s.isEmpty()) { if(!(ret = parse(s, place))) break; s = ""; } } } if(!using_stdin) qfile.close(); } parser = pi; return ret; } bool QMakeProject::read(QString project, QString) { if(cfile.isEmpty()) { // hack to get the Option stuff in there base_vars["QMAKE_EXT_CPP"] = Option::cpp_ext; base_vars["QMAKE_EXT_H"] = Option::h_ext; /* parse the cache */ if(Option::mkfile::do_cache) { if(Option::mkfile::cachefile.isEmpty()) { //find it as it has not been specified QString dir = QDir::convertSeparators(Option::output_dir); while(!QFile::exists((Option::mkfile::cachefile = dir + QDir::separator() + ".qmake.cache"))) { dir = dir.left(dir.findRev(QDir::separator())); if(dir.isEmpty() || dir.find(QDir::separator()) == -1) { Option::mkfile::cachefile = ""; break; } if(Option::mkfile::cachefile_depth == -1) Option::mkfile::cachefile_depth = 1; else Option::mkfile::cachefile_depth++; } } if(!Option::mkfile::cachefile.isEmpty()) { read(Option::mkfile::cachefile, cache); if(Option::mkfile::qmakespec.isEmpty() && !cache["QMAKESPEC"].isEmpty()) Option::mkfile::qmakespec = cache["QMAKESPEC"].first(); } } /* parse mkspec */ QStringList mkspec_roots; /* prefer $QTDIR if it is set */ - /* minor hack here, prefer QMAKESPECDIR -cl */ + /* prefer QMAKESPECSDIR -cl */ - if (getenv("QMAKESPECDIR")){ - mkspec_roots << getenv("QMAKESPECDIR"); - } else if (getenv("QTDIR")) { + if (getenv("QTDIR")) { mkspec_roots << getenv("QTDIR"); } mkspec_roots << qInstallPathData(); + + if (getenv("QMAKESPECSDIR")){ + QString mkspec = QString(getenv("QMAKESPECSDIR")) + QDir::separator() + + QDir::separator() + "default"; + if(QFile::exists(mkspec)) + Option::mkfile::qmakespec = mkspec; + } + if(Option::mkfile::qmakespec.isEmpty()) { for(QStringList::Iterator it = mkspec_roots.begin(); it != mkspec_roots.end(); ++it) { QString mkspec = (*it) + QDir::separator() + QString("mkspecs") + QDir::separator() + "default"; if(QFile::exists(mkspec)) { Option::mkfile::qmakespec = mkspec; break; } } - if(Option::mkfile::qmakespec.isEmpty()) { - fprintf(stderr, "QMAKESPEC has not been set, so configuration cannot be deduced.\n"); - return FALSE; - } + } + + if(Option::mkfile::qmakespec.isEmpty()) { + fprintf(stderr, "QMAKESPEC has not been set, so configuration cannot be deduced.\n"); + return FALSE; } if(QDir::isRelativePath(Option::mkfile::qmakespec)) { bool found_mkspec = FALSE; for(QStringList::Iterator it = mkspec_roots.begin(); it != mkspec_roots.end(); ++it) { QString mkspec = (*it) + QDir::separator() + QString("mkspecs") + QDir::separator() + Option::mkfile::qmakespec; if(QFile::exists(mkspec)) { found_mkspec = TRUE; Option::mkfile::qmakespec = mkspec; break; } } if(!found_mkspec) { fprintf(stderr, "Could not find mkspecs for your QMAKESPEC after trying:\n\t%s\n", mkspec_roots.join("\n\t").latin1()); return FALSE; } } /* parse qmake configuration */ QString spec = Option::mkfile::qmakespec + QDir::separator() + "qmake.conf"; debug_msg(1, "QMAKESPEC conf: reading %s", spec.latin1()); if(!read(spec, base_vars)) { fprintf(stderr, "Failure to read QMAKESPEC conf file %s.\n", spec.latin1()); return FALSE; } if(Option::mkfile::do_cache && !Option::mkfile::cachefile.isEmpty()) { debug_msg(1, "QMAKECACHE file: reading %s", Option::mkfile::cachefile.latin1()); read(Option::mkfile::cachefile, base_vars); } /* commandline */ cfile = project; parser.line_no = 1; //really arg count now.. duh parser.file = "(internal)"; for(QStringList::Iterator it = Option::before_user_vars.begin(); it != Option::before_user_vars.end(); ++it) { if(!parse((*it), base_vars)) { fprintf(stderr, "Argument failed to parse: %s\n", (*it).latin1()); return FALSE; } parser.line_no++; } } /* parse project file */ debug_msg(1, "Project file: reading %s", project.latin1()); vars = base_vars; /* start with the base */ pfile = project; if(pfile != "-" && !QFile::exists(pfile) && pfile.right(4) != ".pro") pfile += ".pro"; if(!read(pfile, vars)) return FALSE; parser.line_no = 1; //really arg count now.. duh parser.file = "(internal)"; for(QStringList::Iterator it = Option::after_user_vars.begin(); it != Option::after_user_vars.end(); ++it) { if(!parse((*it), vars)) { fprintf(stderr, "Argument failed to parse: %s\n", (*it).latin1()); return FALSE; } parser.line_no++; } /* now let the user override the template from an option.. */ if(!Option::user_template.isEmpty()) { debug_msg(1, "Overriding TEMPLATE (%s) with: %s", vars["TEMPLATE"].first().latin1(), Option::user_template.latin1()); vars["TEMPLATE"].clear(); vars["TEMPLATE"].append(Option::user_template); } if(vars["TEMPLATE"].isEmpty()) vars["TEMPLATE"].append(QString("app")); else vars["TEMPLATE"].first().replace(QRegExp("\\.t$"), ""); if(!Option::user_template_prefix.isEmpty()) vars["TEMPLATE"].first().prepend(Option::user_template_prefix); if(vars["TARGET"].isEmpty()) { // ### why not simply use: // QFileInfo fi(pfile); // fi.baseName(); QString tmp = pfile; if(tmp.findRev('/') != -1) tmp = tmp.right( tmp.length() - tmp.findRev('/') - 1 ); if(tmp.findRev('.') != -1) tmp = tmp.left(tmp.findRev('.')); vars["TARGET"].append(tmp); } QString test_version = getenv("QTESTVERSION"); if (!test_version.isEmpty()) { QString s = vars["TARGET"].first(); if (s == "qt" || s == "qt-mt" || s == "qte" || s == "qte-mt") { QString &ver = vars["VERSION"].first(); // fprintf(stderr,"Current QT version number: " + ver + "\n"); if (ver != "" && ver != test_version) { ver = test_version; fprintf(stderr,"Changed QT version number to " + test_version + "!\n"); } } } return TRUE; } bool QMakeProject::isActiveConfig(const QString &x) { if(x.isEmpty()) return TRUE; QRegExp re(x, FALSE, TRUE); if((Option::target_mode == Option::TARG_MACX_MODE || Option::target_mode == Option::TARG_QNX6_MODE || Option::target_mode == Option::TARG_UNIX_MODE) && x == "unix") return TRUE; else if(Option::target_mode == Option::TARG_MACX_MODE && x == "macx") return TRUE; else if(Option::target_mode == Option::TARG_QNX6_MODE && x == "qnx6") return TRUE; else if(Option::target_mode == Option::TARG_MAC9_MODE && x == "mac9") return TRUE; else if((Option::target_mode == Option::TARG_MAC9_MODE || Option::target_mode == Option::TARG_MACX_MODE) && x == "mac") return TRUE; else if(Option::target_mode == Option::TARG_WIN_MODE && x == "win32") return TRUE; QString spec = Option::mkfile::qmakespec.right(Option::mkfile::qmakespec.length() - (Option::mkfile::qmakespec.findRev(QDir::separator())+1)); if(re.exactMatch(spec)) return TRUE; #ifdef Q_OS_UNIX else if(spec == "default") { static char *buffer = NULL; if(!buffer) buffer = (char *)malloc(1024); int l = readlink(Option::mkfile::qmakespec, buffer, 1024); if(l != -1) { buffer[l] = '\0'; QString r = buffer; if(r.findRev('/') != -1) r = r.mid(r.findRev('/') + 1); if(re.exactMatch(r)) return TRUE; } } #endif QStringList &configs = vars["CONFIG"]; for(QStringList::Iterator it = configs.begin(); it != configs.end(); ++it) { if(re.exactMatch((*it))) return TRUE; } return FALSE; } bool QMakeProject::doProjectTest(QString func, const QString ¶ms, QMap<QString, QStringList> &place) { QStringList args = split_arg_list(params); for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) { QString tmp = (*arit).stripWhiteSpace(); if((tmp[0] == '\'' || tmp[0] == '"') && tmp.right(1) == tmp.left(1)) tmp = tmp.mid(1, tmp.length() - 2); } return doProjectTest(func.stripWhiteSpace(), args, place); } bool QMakeProject::doProjectTest(QString func, QStringList args, QMap<QString, QStringList> &place) { for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit) { (*arit) = (*arit).stripWhiteSpace(); // blah, get rid of space doVariableReplace((*arit), place); } debug_msg(1, "Running project test: %s( %s )", func.latin1(), args.join("::").latin1()); if(func == "requires") { return doProjectCheckReqs(args, place); } else if(func == "exists") { if(args.count() != 1) { fprintf(stderr, "%s:%d: exists(file) requires one argument.\n", parser.file.latin1(), parser.line_no); return FALSE; } QString file = args.first(); |