qmake/project.cpp
changeset 30 5dc02b23752f
parent 18 2f34d5167611
child 33 3e2da88830cd
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
    41 
    41 
    42 #include "project.h"
    42 #include "project.h"
    43 #include "property.h"
    43 #include "property.h"
    44 #include "option.h"
    44 #include "option.h"
    45 #include "cachekeys.h"
    45 #include "cachekeys.h"
       
    46 #include "generators/metamakefile.h"
    46 
    47 
    47 #include <qdatetime.h>
    48 #include <qdatetime.h>
    48 #include <qfile.h>
    49 #include <qfile.h>
    49 #include <qfileinfo.h>
    50 #include <qfileinfo.h>
    50 #include <qdir.h>
    51 #include <qdir.h>
   119 //replace functions
   120 //replace functions
   120 enum TestFunc { T_REQUIRES=1, T_GREATERTHAN, T_LESSTHAN, T_EQUALS,
   121 enum TestFunc { T_REQUIRES=1, T_GREATERTHAN, T_LESSTHAN, T_EQUALS,
   121                 T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM,
   122                 T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM,
   122                 T_RETURN, T_BREAK, T_NEXT, T_DEFINED, T_CONTAINS, T_INFILE,
   123                 T_RETURN, T_BREAK, T_NEXT, T_DEFINED, T_CONTAINS, T_INFILE,
   123                 T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, T_DEBUG, T_ERROR,
   124                 T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, T_DEBUG, T_ERROR,
   124                 T_MESSAGE, T_WARNING, T_IF };
   125                 T_MESSAGE, T_WARNING, T_IF, T_OPTION };
   125 QMap<QString, TestFunc> qmake_testFunctions()
   126 QMap<QString, TestFunc> qmake_testFunctions()
   126 {
   127 {
   127     static QMap<QString, TestFunc> *qmake_test_functions = 0;
   128     static QMap<QString, TestFunc> *qmake_test_functions = 0;
   128     if(!qmake_test_functions) {
   129     if(!qmake_test_functions) {
   129         qmake_test_functions = new QMap<QString, TestFunc>;
   130         qmake_test_functions = new QMap<QString, TestFunc>;
   153         qmake_test_functions->insert("load", T_LOAD);
   154         qmake_test_functions->insert("load", T_LOAD);
   154         qmake_test_functions->insert("debug", T_DEBUG);
   155         qmake_test_functions->insert("debug", T_DEBUG);
   155         qmake_test_functions->insert("error", T_ERROR);
   156         qmake_test_functions->insert("error", T_ERROR);
   156         qmake_test_functions->insert("message", T_MESSAGE);
   157         qmake_test_functions->insert("message", T_MESSAGE);
   157         qmake_test_functions->insert("warning", T_WARNING);
   158         qmake_test_functions->insert("warning", T_WARNING);
       
   159         qmake_test_functions->insert("option", T_OPTION);
   158     }
   160     }
   159     return *qmake_test_functions;
   161     return *qmake_test_functions;
   160 }
   162 }
   161 
   163 
   162 struct parser_info {
   164 struct parser_info {
   182 }
   184 }
   183 
   185 
   184 static QString varMap(const QString &x)
   186 static QString varMap(const QString &x)
   185 {
   187 {
   186     QString ret(x);
   188     QString ret(x);
   187     if(ret.startsWith("TMAKE")) //tmake no more!
   189     if(ret == "INTERFACES")
   188         ret = "QMAKE" + ret.mid(5);
       
   189     else if(ret == "INTERFACES")
       
   190         ret = "FORMS";
   190         ret = "FORMS";
   191     else if(ret == "QMAKE_POST_BUILD")
   191     else if(ret == "QMAKE_POST_BUILD")
   192         ret = "QMAKE_POST_LINK";
   192         ret = "QMAKE_POST_LINK";
   193     else if(ret == "TARGETDEPS")
   193     else if(ret == "TARGETDEPS")
   194         ret = "POST_TARGETDEPS";
   194         ret = "POST_TARGETDEPS";
   218         ret = "QMAKE_LFLAGS_RPATH";
   218         ret = "QMAKE_LFLAGS_RPATH";
   219     else if(ret == "QMAKE_FRAMEWORKDIR")
   219     else if(ret == "QMAKE_FRAMEWORKDIR")
   220         ret = "QMAKE_FRAMEWORKPATH";
   220         ret = "QMAKE_FRAMEWORKPATH";
   221     else if(ret == "QMAKE_FRAMEWORKDIR_FLAGS")
   221     else if(ret == "QMAKE_FRAMEWORKDIR_FLAGS")
   222         ret = "QMAKE_FRAMEWORKPATH_FLAGS";
   222         ret = "QMAKE_FRAMEWORKPATH_FLAGS";
       
   223     else
       
   224         return ret;
       
   225     warn_msg(WarnDeprecated, "%s:%d: Variable %s is deprecated; use %s instead.",
       
   226              parser.file.toLatin1().constData(), parser.line_no,
       
   227              x.toLatin1().constData(), ret.toLatin1().constData());
   223     return ret;
   228     return ret;
   224 }
   229 }
   225 
   230 
   226 static QStringList split_arg_list(QString params)
   231 static QStringList split_arg_list(QString params)
   227 {
   232 {
   276         }
   281         }
   277     }
   282     }
   278     return args;
   283     return args;
   279 }
   284 }
   280 
   285 
   281 static QStringList split_value_list(const QString &vals, bool do_semicolon=false)
   286 static QStringList split_value_list(const QString &vals)
   282 {
   287 {
   283     QString build;
   288     QString build;
   284     QStringList ret;
   289     QStringList ret;
   285     QStack<char> quote;
   290     QStack<char> quote;
   286 
   291 
   287     const ushort LPAREN = '(';
   292     const ushort LPAREN = '(';
   288     const ushort RPAREN = ')';
   293     const ushort RPAREN = ')';
   289     const ushort SINGLEQUOTE = '\'';
   294     const ushort SINGLEQUOTE = '\'';
   290     const ushort DOUBLEQUOTE = '"';
   295     const ushort DOUBLEQUOTE = '"';
   291     const ushort BACKSLASH = '\\';
   296     const ushort BACKSLASH = '\\';
   292     const ushort SEMICOLON = ';';
       
   293 
   297 
   294     ushort unicode;
   298     ushort unicode;
   295     const QChar *vals_data = vals.data();
   299     const QChar *vals_data = vals.data();
   296     const int vals_len = vals.length();
   300     const int vals_len = vals.length();
   297     for(int x = 0, parens = 0; x < vals_len; x++) {
   301     for(int x = 0, parens = 0; x < vals_len; x++) {
   307             --parens;
   311             --parens;
   308         } else if(unicode == LPAREN) {
   312         } else if(unicode == LPAREN) {
   309             ++parens;
   313             ++parens;
   310         }
   314         }
   311 
   315 
   312         if(!parens && quote.isEmpty() && ((do_semicolon && unicode == SEMICOLON) ||
   316         if(!parens && quote.isEmpty() && (vals_data[x] == Option::field_sep)) {
   313                                            vals_data[x] == Option::field_sep)) {
       
   314             ret << build;
   317             ret << build;
   315             build.clear();
   318             build.clear();
   316         } else {
   319         } else {
   317             build += vals_data[x];
   320             build += vals_data[x];
   318         }
   321         }
   507 {
   510 {
   508     fprintf(stderr, "%s:%d: %s\n", parser.file.toLatin1().constData(), parser.line_no,
   511     fprintf(stderr, "%s:%d: %s\n", parser.file.toLatin1().constData(), parser.line_no,
   509             msg.toLatin1().constData());
   512             msg.toLatin1().constData());
   510 }
   513 }
   511 
   514 
   512 enum isForSymbian_enum {
       
   513     isForSymbian_NOT_SET = -1,
       
   514     isForSymbian_FALSE = 0,
       
   515     isForSymbian_ABLD = 1,
       
   516     isForSymbian_SBSV2 = 2,
       
   517 };
       
   518 
       
   519 static isForSymbian_enum isForSymbian_value = isForSymbian_NOT_SET;
       
   520 
       
   521 // Checking for symbian build is primarily determined from the qmake spec,
       
   522 // but if that is not specified, detect if symbian is the default spec
       
   523 // by checking the MAKEFILE_GENERATOR variable value.
       
   524 static void init_symbian(const QMap<QString, QStringList>& vars)
       
   525 {
       
   526     if (isForSymbian_value != isForSymbian_NOT_SET)
       
   527         return;
       
   528 
       
   529     QString spec = QFileInfo(Option::mkfile::qmakespec).fileName();
       
   530     if (spec.startsWith("symbian-abld", Qt::CaseInsensitive)) {
       
   531         isForSymbian_value = isForSymbian_ABLD;
       
   532     } else if (spec.startsWith("symbian-sbsv2", Qt::CaseInsensitive)) {
       
   533         isForSymbian_value = isForSymbian_SBSV2;
       
   534     } else {
       
   535         QStringList generatorList = vars["MAKEFILE_GENERATOR"];
       
   536 
       
   537         if (!generatorList.isEmpty()) {
       
   538             QString generator = generatorList.first();
       
   539             if (generator.startsWith("SYMBIAN_ABLD"))
       
   540                 isForSymbian_value = isForSymbian_ABLD;
       
   541             else if (generator.startsWith("SYMBIAN_SBSV2"))
       
   542                 isForSymbian_value = isForSymbian_SBSV2;
       
   543             else
       
   544                 isForSymbian_value = isForSymbian_FALSE;
       
   545         } else {
       
   546             isForSymbian_value = isForSymbian_FALSE;
       
   547         }
       
   548     }
       
   549 
       
   550     // Force recursive on Symbian, as non-recursive is not really a viable option there
       
   551     if (isForSymbian_value != isForSymbian_FALSE)
       
   552         Option::recursive = true;
       
   553 }
       
   554 
       
   555 bool isForSymbian()
       
   556 {
       
   557     // If isForSymbian_value has not been initialized explicitly yet,
       
   558     // call initializer with dummy map to check qmake spec.
       
   559     if (isForSymbian_value == isForSymbian_NOT_SET)
       
   560         init_symbian(QMap<QString, QStringList>());
       
   561 
       
   562     return (isForSymbian_value != isForSymbian_FALSE);
       
   563 }
       
   564 
       
   565 bool isForSymbianSbsv2()
       
   566 {
       
   567     // If isForSymbian_value has not been initialized explicitly yet,
       
   568     // call initializer with dummy map to check qmake spec.
       
   569     if (isForSymbian_value == isForSymbian_NOT_SET)
       
   570         init_symbian(QMap<QString, QStringList>());
       
   571 
       
   572     return (isForSymbian_value == isForSymbian_SBSV2);
       
   573 }
       
   574 
       
   575 /*
   515 /*
   576    1) environment variable QMAKEFEATURES (as separated by colons)
   516    1) environment variable QMAKEFEATURES (as separated by colons)
   577    2) property variable QMAKEFEATURES (as separated by colons)
   517    2) property variable QMAKEFEATURES (as separated by colons)
   578    3) <project_root> (where .qmake.cache lives) + FEATURES_DIR
   518    3) <project_root> (where .qmake.cache lives) + FEATURES_DIR
   579    4) environment variable QMAKEPATH (as separated by colons) + /mkspecs/FEATURES_DIR
   519    4) environment variable QMAKEPATH (as separated by colons) + /mkspecs/FEATURES_DIR
   595         case Option::TARG_MACX_MODE:                     //also a unix
   535         case Option::TARG_MACX_MODE:                     //also a unix
   596             concat << base_concat + QDir::separator() + "mac";
   536             concat << base_concat + QDir::separator() + "mac";
   597             concat << base_concat + QDir::separator() + "macx";
   537             concat << base_concat + QDir::separator() + "macx";
   598             concat << base_concat + QDir::separator() + "unix";
   538             concat << base_concat + QDir::separator() + "unix";
   599             break;
   539             break;
       
   540         default: // Can't happen, just make the compiler shut up
   600         case Option::TARG_UNIX_MODE:
   541         case Option::TARG_UNIX_MODE:
   601             {
   542             concat << base_concat + QDir::separator() + "unix";
   602                 if (isForSymbian())
   543             break;
   603                     concat << base_concat + QDir::separator() + "symbian";
       
   604                 else
       
   605                     concat << base_concat + QDir::separator() + "unix";
       
   606                 break;
       
   607             }
       
   608         case Option::TARG_WIN_MODE:
   544         case Option::TARG_WIN_MODE:
   609             {
   545             concat << base_concat + QDir::separator() + "win32";
   610                 if (isForSymbian())
   546             break;
   611                     concat << base_concat + QDir::separator() + "symbian";
   547         case Option::TARG_SYMBIAN_MODE:
   612                 else
   548             concat << base_concat + QDir::separator() + "symbian";
   613                     concat << base_concat + QDir::separator() + "win32";
       
   614                 break;
       
   615             }
       
   616         case Option::TARG_MAC9_MODE:
       
   617             concat << base_concat + QDir::separator() + "mac";
       
   618             concat << base_concat + QDir::separator() + "mac9";
       
   619             break;
   549             break;
   620         }
   550         }
   621         concat << base_concat;
   551         concat << base_concat;
   622     }
   552     }
   623     const QString mkspecs_concat = QDir::separator() + QString("mkspecs");
   553     const QString mkspecs_concat = QDir::separator() + QString("mkspecs");
   627         feature_roots += splitPathList(QString::fromLocal8Bit(mkspec_path));
   557         feature_roots += splitPathList(QString::fromLocal8Bit(mkspec_path));
   628     if(prop)
   558     if(prop)
   629         feature_roots += splitPathList(prop->value("QMAKEFEATURES"));
   559         feature_roots += splitPathList(prop->value("QMAKEFEATURES"));
   630     if(!Option::mkfile::cachefile.isEmpty()) {
   560     if(!Option::mkfile::cachefile.isEmpty()) {
   631         QString path;
   561         QString path;
   632         int last_slash = Option::mkfile::cachefile.lastIndexOf(Option::dir_sep);
   562         int last_slash = Option::mkfile::cachefile.lastIndexOf(QDir::separator());
   633         if(last_slash != -1)
   563         if(last_slash != -1)
   634             path = Option::fixPathToLocalOS(Option::mkfile::cachefile.left(last_slash));
   564             path = Option::fixPathToLocalOS(Option::mkfile::cachefile.left(last_slash), false);
   635         for(QStringList::Iterator concat_it = concat.begin();
   565         for(QStringList::Iterator concat_it = concat.begin();
   636             concat_it != concat.end(); ++concat_it)
   566             concat_it != concat.end(); ++concat_it)
   637             feature_roots << (path + (*concat_it));
   567             feature_roots << (path + (*concat_it));
   638     }
   568     }
   639     QByteArray qmakepath = qgetenv("QMAKEPATH");
   569     QByteArray qmakepath = qgetenv("QMAKEPATH");
   685     ret << QLibraryInfo::location(QLibraryInfo::DataPath) + concat;
   615     ret << QLibraryInfo::location(QLibraryInfo::DataPath) + concat;
   686 
   616 
   687     return ret;
   617     return ret;
   688 }
   618 }
   689 
   619 
   690 class QMakeProjectEnv
       
   691 {
       
   692     QStringList envs;
       
   693 public:
       
   694     QMakeProjectEnv() { }
       
   695     QMakeProjectEnv(QMakeProject *p) { execute(p->variables()); }
       
   696     QMakeProjectEnv(const QMap<QString, QStringList> &values) { execute(values); }
       
   697 
       
   698     void execute(QMakeProject *p) { execute(p->variables()); }
       
   699     void execute(const QMap<QString, QStringList> &values) {
       
   700 #ifdef Q_OS_UNIX
       
   701         for(QMap<QString, QStringList>::ConstIterator it = values.begin(); it != values.end(); ++it) {
       
   702             const QString var = it.key(), val = it.value().join(" ");
       
   703             if(!var.startsWith(".")) {
       
   704                 const QString env_var = Option::sysenv_mod + var;
       
   705                 if(!putenv(strdup(QString(env_var + "=" + val).toAscii().data())))
       
   706                     envs.append(env_var);
       
   707             }
       
   708         }
       
   709 #else
       
   710         Q_UNUSED(values);
       
   711 #endif
       
   712     }
       
   713     ~QMakeProjectEnv() {
       
   714 #ifdef Q_OS_UNIX
       
   715         for(QStringList::ConstIterator it = envs.begin();it != envs.end(); ++it) {
       
   716             putenv(strdup(QString(*it + "=").toAscii().data()));
       
   717         }
       
   718 #endif
       
   719     }
       
   720 };
       
   721 
       
   722 QMakeProject::~QMakeProject()
   620 QMakeProject::~QMakeProject()
   723 {
   621 {
   724     if(own_prop)
   622     if(own_prop)
   725         delete prop;
   623         delete prop;
   726     for(QMap<QString, FunctionBlock*>::iterator it = replaceFunctions.begin(); it != replaceFunctions.end(); ++it) {
   624     for(QMap<QString, FunctionBlock*>::iterator it = replaceFunctions.begin(); it != replaceFunctions.end(); ++it) {
   746         own_prop = true;
   644         own_prop = true;
   747     } else {
   645     } else {
   748         prop = p;
   646         prop = p;
   749         own_prop = false;
   647         own_prop = false;
   750     }
   648     }
       
   649     recursive = false;
   751     reset();
   650     reset();
   752 }
   651 }
   753 
   652 
   754 QMakeProject::QMakeProject(QMakeProject *p, const QMap<QString, QStringList> *vars)
   653 QMakeProject::QMakeProject(QMakeProject *p, const QMap<QString, QStringList> *vars)
   755 {
   654 {
  1225         }
  1124         }
  1226     } else {
  1125     } else {
  1227         QStringList vallist;
  1126         QStringList vallist;
  1228         {
  1127         {
  1229             //doVariableReplace(vals, place);
  1128             //doVariableReplace(vals, place);
  1230             QStringList tmp = split_value_list(vals, (var == "DEPENDPATH" || var == "INCLUDEPATH"));
  1129             QStringList tmp = split_value_list(vals);
  1231             for(int i = 0; i < tmp.size(); ++i)
  1130             for(int i = 0; i < tmp.size(); ++i)
  1232                 vallist += doVariableReplaceExpand(tmp[i], place);
  1131                 vallist += doVariableReplaceExpand(tmp[i], place);
  1233         }
  1132         }
  1234 
  1133 
  1235         if(op == "=") {
  1134         if(op == "=") {
  1315 {
  1214 {
  1316     parser_info pi = parser;
  1215     parser_info pi = parser;
  1317     reset();
  1216     reset();
  1318 
  1217 
  1319     const QString oldpwd = qmake_getpwd();
  1218     const QString oldpwd = qmake_getpwd();
  1320     QString filename = Option::fixPathToLocalOS(file);
  1219     QString filename = Option::fixPathToLocalOS(file, false);
  1321     doVariableReplace(filename, place);
       
  1322     bool ret = false, using_stdin = false;
  1220     bool ret = false, using_stdin = false;
  1323     QFile qfile;
  1221     QFile qfile;
  1324     if(!strcmp(filename.toLatin1(), "-")) {
  1222     if(!strcmp(filename.toLatin1(), "-")) {
  1325         qfile.setFileName("");
  1223         qfile.setFileName("");
  1326         ret = qfile.open(stdin, QIODevice::ReadOnly);
  1224         ret = qfile.open(stdin, QIODevice::ReadOnly);
  1360 
  1258 
  1361 bool
  1259 bool
  1362 QMakeProject::read(uchar cmd)
  1260 QMakeProject::read(uchar cmd)
  1363 {
  1261 {
  1364     if(cfile.isEmpty()) {
  1262     if(cfile.isEmpty()) {
  1365         //find out where qmake (myself) lives
       
  1366         if (!base_vars.contains("QMAKE_QMAKE")) {
       
  1367             if (!Option::qmake_abslocation.isNull())
       
  1368                 base_vars["QMAKE_QMAKE"] = QStringList(Option::qmake_abslocation);
       
  1369             else
       
  1370                 base_vars["QMAKE_QMAKE"] = QStringList("qmake");
       
  1371         }
       
  1372 
       
  1373         // hack to get the Option stuff in there
  1263         // hack to get the Option stuff in there
  1374         base_vars["QMAKE_EXT_OBJ"] = QStringList(Option::obj_ext);
       
  1375         base_vars["QMAKE_EXT_CPP"] = Option::cpp_ext;
  1264         base_vars["QMAKE_EXT_CPP"] = Option::cpp_ext;
  1376         base_vars["QMAKE_EXT_C"] = Option::c_ext;
  1265         base_vars["QMAKE_EXT_C"] = Option::c_ext;
  1377         base_vars["QMAKE_EXT_H"] = Option::h_ext;
  1266         base_vars["QMAKE_EXT_H"] = Option::h_ext;
  1378         base_vars["QMAKE_SH"] = Option::shellPath;
  1267         base_vars["QMAKE_SH"] = Option::shellPath;
  1379         if(!Option::user_template_prefix.isEmpty())
  1268         if(!Option::user_template_prefix.isEmpty())
  1455 
  1344 
  1456             // parse qmake configuration
  1345             // parse qmake configuration
  1457             while(qmakespec.endsWith(QString(QChar(QDir::separator()))))
  1346             while(qmakespec.endsWith(QString(QChar(QDir::separator()))))
  1458                 qmakespec.truncate(qmakespec.length()-1);
  1347                 qmakespec.truncate(qmakespec.length()-1);
  1459             QString spec = qmakespec + QDir::separator() + "qmake.conf";
  1348             QString spec = qmakespec + QDir::separator() + "qmake.conf";
  1460             if(!QFile::exists(spec) &&
       
  1461                QFile::exists(qmakespec + QDir::separator() + "tmake.conf"))
       
  1462                 spec = qmakespec + QDir::separator() + "tmake.conf";
       
  1463             debug_msg(1, "QMAKESPEC conf: reading %s", spec.toLatin1().constData());
  1349             debug_msg(1, "QMAKESPEC conf: reading %s", spec.toLatin1().constData());
  1464             if(!read(spec, base_vars)) {
  1350             if(!read(spec, base_vars)) {
  1465                 fprintf(stderr, "Failure to read QMAKESPEC conf file %s.\n", spec.toLatin1().constData());
  1351                 fprintf(stderr, "Failure to read QMAKESPEC conf file %s.\n", spec.toLatin1().constData());
  1466                 return false;
  1352                 return false;
  1467             }
  1353             }
  1468 
  1354             validateModes();
  1469             init_symbian(base_vars);
       
  1470 
  1355 
  1471             if(Option::mkfile::do_cache && !Option::mkfile::cachefile.isEmpty()) {
  1356             if(Option::mkfile::do_cache && !Option::mkfile::cachefile.isEmpty()) {
  1472                 debug_msg(1, "QMAKECACHE file: reading %s", Option::mkfile::cachefile.toLatin1().constData());
  1357                 debug_msg(1, "QMAKECACHE file: reading %s", Option::mkfile::cachefile.toLatin1().constData());
  1473                 read(Option::mkfile::cachefile, base_vars);
  1358                 read(Option::mkfile::cachefile, base_vars);
  1474             }
  1359             }
  1588     }
  1473     }
  1589     Option::postProcessProject(this);   // let Option post-process
  1474     Option::postProcessProject(this);   // let Option post-process
  1590     return true;
  1475     return true;
  1591 }
  1476 }
  1592 
  1477 
       
  1478 void QMakeProject::validateModes()
       
  1479 {
       
  1480     if (Option::host_mode == Option::HOST_UNKNOWN_MODE
       
  1481         || Option::target_mode == Option::TARG_UNKNOWN_MODE) {
       
  1482         Option::HOST_MODE host_mode;
       
  1483         Option::TARG_MODE target_mode;
       
  1484         const QStringList &gen = base_vars.value("MAKEFILE_GENERATOR");
       
  1485         if (gen.isEmpty()) {
       
  1486             fprintf(stderr, "%s:%d: Using OS scope before setting MAKEFILE_GENERATOR\n",
       
  1487                             parser.file.toLatin1().constData(), parser.line_no);
       
  1488         } else if (MetaMakefileGenerator::modesForGenerator(gen.first(),
       
  1489                                                             &host_mode, &target_mode)) {
       
  1490             if (Option::host_mode == Option::HOST_UNKNOWN_MODE) {
       
  1491                 Option::host_mode = host_mode;
       
  1492                 Option::applyHostMode();
       
  1493             }
       
  1494 
       
  1495             if (Option::target_mode == Option::TARG_UNKNOWN_MODE) {
       
  1496                 const QStringList &tgt = base_vars.value("TARGET_PLATFORM");
       
  1497                 if (!tgt.isEmpty()) {
       
  1498                     const QString &os = tgt.first();
       
  1499                     if (os == "unix")
       
  1500                         Option::target_mode = Option::TARG_UNIX_MODE;
       
  1501                     else if (os == "macx")
       
  1502                         Option::target_mode = Option::TARG_MACX_MODE;
       
  1503                     else if (os == "symbian")
       
  1504                         Option::target_mode = Option::TARG_SYMBIAN_MODE;
       
  1505                     else if (os == "win32")
       
  1506                         Option::target_mode = Option::TARG_WIN_MODE;
       
  1507                     else
       
  1508                         fprintf(stderr, "Unknown target platform specified: %s\n",
       
  1509                                 os.toLatin1().constData());
       
  1510                 } else {
       
  1511                     Option::target_mode = target_mode;
       
  1512                 }
       
  1513             }
       
  1514         }
       
  1515     }
       
  1516 }
       
  1517 
  1593 bool
  1518 bool
  1594 QMakeProject::isActiveConfig(const QString &x, bool regex, QMap<QString, QStringList> *place)
  1519 QMakeProject::isActiveConfig(const QString &x, bool regex, QMap<QString, QStringList> *place)
  1595 {
  1520 {
  1596     if(x.isEmpty())
  1521     if(x.isEmpty())
  1597         return true;
  1522         return true;
  1600     if(x == "true")
  1525     if(x == "true")
  1601         return true;
  1526         return true;
  1602     else if(x == "false")
  1527     else if(x == "false")
  1603         return false;
  1528         return false;
  1604 
  1529 
       
  1530     if (x == "unix") {
       
  1531         validateModes();
       
  1532         return Option::target_mode == Option::TARG_UNIX_MODE
       
  1533                || Option::target_mode == Option::TARG_MACX_MODE
       
  1534                || Option::target_mode == Option::TARG_SYMBIAN_MODE;
       
  1535     } else if (x == "macx" || x == "mac") {
       
  1536         validateModes();
       
  1537         return Option::target_mode == Option::TARG_MACX_MODE;
       
  1538     } else if (x == "symbian") {
       
  1539         validateModes();
       
  1540         return Option::target_mode == Option::TARG_SYMBIAN_MODE;
       
  1541     } else if (x == "win32") {
       
  1542         validateModes();
       
  1543         return Option::target_mode == Option::TARG_WIN_MODE;
       
  1544     }
       
  1545 
       
  1546     //mkspecs
  1605     static QString spec;
  1547     static QString spec;
  1606     if(spec.isEmpty())
  1548     if(spec.isEmpty())
  1607         spec = QFileInfo(Option::mkfile::qmakespec).fileName();
  1549         spec = QFileInfo(Option::mkfile::qmakespec).fileName();
  1608 
       
  1609     // Symbian is an exception to how scopes are resolved. Since we do not
       
  1610     // have a separate target mode for Symbian, but we expect the scope to resolve
       
  1611     // on other platforms we base it entirely on the mkspec. This means that
       
  1612     // using a mkspec starting with 'symbian*' will resolve both the 'symbian'
       
  1613     // and the 'unix' (because of Open C) scopes to true.
       
  1614     if(isForSymbian() && (x == "symbian" || x == "unix"))
       
  1615         return true;
       
  1616 
       
  1617     //mkspecs
       
  1618     if((Option::target_mode == Option::TARG_MACX_MODE ||
       
  1619         Option::target_mode == Option::TARG_UNIX_MODE) && x == "unix")
       
  1620         return !isForSymbian();
       
  1621     else if(Option::target_mode == Option::TARG_MACX_MODE && x == "macx")
       
  1622         return !isForSymbian();
       
  1623     else if(Option::target_mode == Option::TARG_MAC9_MODE && x == "mac9")
       
  1624         return !isForSymbian();
       
  1625     else if((Option::target_mode == Option::TARG_MAC9_MODE || Option::target_mode == Option::TARG_MACX_MODE) &&
       
  1626             x == "mac")
       
  1627         return !isForSymbian();
       
  1628     else if(Option::target_mode == Option::TARG_WIN_MODE && x == "win32")
       
  1629         return !isForSymbian();
       
  1630     QRegExp re(x, Qt::CaseSensitive, QRegExp::Wildcard);
  1550     QRegExp re(x, Qt::CaseSensitive, QRegExp::Wildcard);
  1631     if((regex && re.exactMatch(spec)) || (!regex && spec == x))
  1551     if((regex && re.exactMatch(spec)) || (!regex && spec == x))
  1632         return true;
  1552         return true;
  1633 #ifdef Q_OS_UNIX
  1553 #ifdef Q_OS_UNIX
  1634     else if(spec == "default") {
  1554     else if(spec == "default") {
  1716         if(!file.endsWith(Option::prf_ext))
  1636         if(!file.endsWith(Option::prf_ext))
  1717             file += Option::prf_ext;
  1637             file += Option::prf_ext;
  1718         if(file.indexOf(Option::dir_sep) == -1 || !QFile::exists(file)) {
  1638         if(file.indexOf(Option::dir_sep) == -1 || !QFile::exists(file)) {
  1719             static QStringList *feature_roots = 0;
  1639             static QStringList *feature_roots = 0;
  1720             if(!feature_roots) {
  1640             if(!feature_roots) {
  1721                 init_symbian(base_vars);
  1641                 validateModes();
  1722                 feature_roots = new QStringList(qmake_feature_paths(prop));
  1642                 feature_roots = new QStringList(qmake_feature_paths(prop));
  1723                 qmakeAddCacheClear(qmakeDeleteCacheClear_QStringList, (void**)&feature_roots);
  1643                 qmakeAddCacheClear(qmakeDeleteCacheClear_QStringList, (void**)&feature_roots);
  1724             }
  1644             }
  1725             debug_msg(2, "Looking for feature '%s' in (%s)", file.toLatin1().constData(),
  1645             debug_msg(2, "Looking for feature '%s' in (%s)", file.toLatin1().constData(),
  1726 			feature_roots->join("::").toLatin1().constData());
  1646 			feature_roots->join("::").toLatin1().constData());
  1885 
  1805 
  1886     QStringList args; //why don't the builtin functions just use args_list? --Sam
  1806     QStringList args; //why don't the builtin functions just use args_list? --Sam
  1887     for(int i = 0; i < args_list.size(); ++i)
  1807     for(int i = 0; i < args_list.size(); ++i)
  1888         args += args_list[i].join(QString(Option::field_sep));
  1808         args += args_list[i].join(QString(Option::field_sep));
  1889 
  1809 
  1890     ExpandFunc func_t = qmake_expandFunctions().value(func.toLower());
  1810     QString lfunc = func.toLower();
       
  1811     if (!lfunc.isSharedWith(func))
       
  1812         warn_msg(WarnDeprecated, "%s:%d: Using uppercased builtin functions is deprecated.",
       
  1813                  parser.file.toLatin1().constData(), parser.line_no);
       
  1814     ExpandFunc func_t = qmake_expandFunctions().value(lfunc);
  1891     debug_msg(1, "Running project expand: %s(%s) [%d]",
  1815     debug_msg(1, "Running project expand: %s(%s) [%d]",
  1892               func.toLatin1().constData(), args.join("::").toLatin1().constData(), func_t);
  1816               func.toLatin1().constData(), args.join("::").toLatin1().constData(), func_t);
  1893 
  1817 
  1894     QStringList ret;
  1818     QStringList ret;
  1895     switch(func_t) {
  1819     switch(func_t) {
  2139     case E_SYSTEM: {
  2063     case E_SYSTEM: {
  2140         if(args.count() < 1 || args.count() > 2) {
  2064         if(args.count() < 1 || args.count() > 2) {
  2141             fprintf(stderr, "%s:%d system(execut) requires one argument.\n",
  2065             fprintf(stderr, "%s:%d system(execut) requires one argument.\n",
  2142                     parser.file.toLatin1().constData(), parser.line_no);
  2066                     parser.file.toLatin1().constData(), parser.line_no);
  2143         } else {
  2067         } else {
  2144             QMakeProjectEnv env(place);
       
  2145             char buff[256];
  2068             char buff[256];
  2146             bool singleLine = true;
  2069             bool singleLine = true;
  2147             if(args.count() > 1)
  2070             if(args.count() > 1)
  2148                 singleLine = (args[1].toLower() == "true");
  2071                 singleLine = (args[1].toLower() == "true");
  2149             QString output;
  2072             QString output;
  2299     case E_SIZE: {
  2222     case E_SIZE: {
  2300         if(args.count() != 1) {
  2223         if(args.count() != 1) {
  2301             fprintf(stderr, "%s:%d: size(var) requires one argument.\n",
  2224             fprintf(stderr, "%s:%d: size(var) requires one argument.\n",
  2302                     parser.file.toLatin1().constData(), parser.line_no);
  2225                     parser.file.toLatin1().constData(), parser.line_no);
  2303         } else {
  2226         } else {
  2304             //QString target = args[0];
  2227             int size = values(args[0], place).size();
  2305             int size = values(args[0]).size();
       
  2306             ret += QString::number(size);
  2228             ret += QString::number(size);
  2307         }
  2229         }
  2308         break; }
  2230         break; }
  2309     case E_GENERATE_UID:
  2231     case E_GENERATE_UID:
  2310         if (args.count() != 1) {
  2232         if (args.count() != 1) {
  2426             }
  2348             }
  2427             if(!parens && quote.isNull() && (*(d+d_off) == QLatin1Char(':') || *(d+d_off) == QLatin1Char('|') || d_off == d_len-1)) {
  2349             if(!parens && quote.isNull() && (*(d+d_off) == QLatin1Char(':') || *(d+d_off) == QLatin1Char('|') || d_off == d_len-1)) {
  2428                 if(d_off == d_len-1)
  2350                 if(d_off == d_len-1)
  2429                     test += *(d+d_off);
  2351                     test += *(d+d_off);
  2430                 if(!test.isEmpty()) {
  2352                 if(!test.isEmpty()) {
  2431                     const bool success = doProjectTest(test, place);
  2353                     if (or_op != ret)
  2432                     test = "";
  2354                         ret = doProjectTest(test, place);
  2433                     if(or_op)
  2355                     test.clear();
  2434                         ret = ret || success;
       
  2435                     else
       
  2436                         ret = ret && success;
       
  2437                 }
  2356                 }
  2438                 if(*(d+d_off) == QLatin1Char(':')) {
  2357                 if(*(d+d_off) == QLatin1Char(':')) {
  2439                     or_op = false;
  2358                     or_op = false;
  2440                 } else if(*(d+d_off) == QLatin1Char('|')) {
  2359                 } else if(*(d+d_off) == QLatin1Char('|')) {
  2441                     or_op = true;
  2360                     or_op = true;
  2534                 if(configs[i] == mutuals[mut].trimmed())
  2453                 if(configs[i] == mutuals[mut].trimmed())
  2535                     return (configs[i] == args[0]);
  2454                     return (configs[i] == args[0]);
  2536             }
  2455             }
  2537         }
  2456         }
  2538         return false; }
  2457         return false; }
  2539     case T_SYSTEM: {
  2458     case T_SYSTEM:
  2540         bool setup_env = true;
       
  2541         if(args.count() < 1 || args.count() > 2) {
  2459         if(args.count() < 1 || args.count() > 2) {
  2542             fprintf(stderr, "%s:%d: system(exec) requires one argument.\n", parser.file.toLatin1().constData(),
  2460             fprintf(stderr, "%s:%d: system(exec) requires one argument.\n", parser.file.toLatin1().constData(),
  2543                     parser.line_no);
  2461                     parser.line_no);
  2544             return false;
  2462             return false;
  2545         }
  2463         }
  2546         if(args.count() == 2) {
  2464         if(args.count() == 2) {
  2547             const QString sarg = args[1];
  2465             const QString sarg = args[1];
  2548             setup_env = (sarg.toLower() == "true" || sarg.toInt());
  2466             if (sarg.toLower() == "true" || sarg.toInt())
  2549         }
  2467                 warn_msg(WarnParser, "%s:%d: system()'s second argument is now hard-wired to false.\n",
  2550         QMakeProjectEnv env;
  2468                          parser.file.toLatin1().constData(), parser.line_no);
  2551         if(setup_env)
  2469         }
  2552             env.execute(place);
  2470         return system(args[0].toLatin1().constData()) == 0;
  2553         bool ret = system(args[0].toLatin1().constData()) == 0;
       
  2554         return ret; }
       
  2555     case T_RETURN:
  2471     case T_RETURN:
  2556         if(function_blocks.isEmpty()) {
  2472         if(function_blocks.isEmpty()) {
  2557             fprintf(stderr, "%s:%d unexpected return()\n",
  2473             fprintf(stderr, "%s:%d unexpected return()\n",
  2558                     parser.file.toLatin1().constData(), parser.line_no);
  2474                     parser.file.toLatin1().constData(), parser.line_no);
  2559         } else {
  2475         } else {
  2564         }
  2480         }
  2565         return true;
  2481         return true;
  2566     case T_BREAK:
  2482     case T_BREAK:
  2567         if(iterator)
  2483         if(iterator)
  2568             iterator->cause_break = true;
  2484             iterator->cause_break = true;
  2569         else if(!scope_blocks.isEmpty())
       
  2570             scope_blocks.top().ignore = true;
       
  2571         else
  2485         else
  2572             fprintf(stderr, "%s:%d unexpected break()\n",
  2486             fprintf(stderr, "%s:%d unexpected break()\n",
  2573                     parser.file.toLatin1().constData(), parser.line_no);
  2487                     parser.file.toLatin1().constData(), parser.line_no);
  2574         return true;
  2488         return true;
  2575     case T_NEXT:
  2489     case T_NEXT:
  2780             return false;
  2694             return false;
  2781 #else
  2695 #else
  2782             exit(2);
  2696             exit(2);
  2783 #endif
  2697 #endif
  2784         return true; }
  2698         return true; }
       
  2699     case T_OPTION:
       
  2700         if (args.count() != 1) {
       
  2701             fprintf(stderr, "%s:%d: option() requires one argument.\n",
       
  2702                     parser.file.toLatin1().constData(), parser.line_no);
       
  2703             return false;
       
  2704         }
       
  2705         if (args.first() == "recursive") {
       
  2706             recursive = true;
       
  2707         } else {
       
  2708             fprintf(stderr, "%s:%d: unrecognized option() argument '%s'.\n",
       
  2709                     parser.file.toLatin1().constData(), parser.line_no,
       
  2710                     args.first().toLatin1().constData());
       
  2711             return false;
       
  2712         }
       
  2713         return true;
  2785     default:
  2714     default:
  2786         fprintf(stderr, "%s:%d: Unknown test function: %s\n", parser.file.toLatin1().constData(), parser.line_no,
  2715         fprintf(stderr, "%s:%d: Unknown test function: %s\n", parser.file.toLatin1().constData(), parser.line_no,
  2787                 func.toLatin1().constData());
  2716                 func.toLatin1().constData());
  2788     }
  2717     }
  2789     return false;
  2718     return false;
  3079             place[var] =  QStringList(Option::user_template);
  3008             place[var] =  QStringList(Option::user_template);
  3080         } else if(!place[var].isEmpty()) {
  3009         } else if(!place[var].isEmpty()) {
  3081             QString orig_template = place["TEMPLATE"].first(), real_template;
  3010             QString orig_template = place["TEMPLATE"].first(), real_template;
  3082             if(!Option::user_template_prefix.isEmpty() && !orig_template.startsWith(Option::user_template_prefix))
  3011             if(!Option::user_template_prefix.isEmpty() && !orig_template.startsWith(Option::user_template_prefix))
  3083                 real_template = Option::user_template_prefix + orig_template;
  3012                 real_template = Option::user_template_prefix + orig_template;
  3084             if(real_template.endsWith(".t"))
       
  3085                 real_template = real_template.left(real_template.length()-2);
       
  3086             if(!real_template.isEmpty()) {
  3013             if(!real_template.isEmpty()) {
  3087                 var = ".BUILTIN." + var;
  3014                 var = ".BUILTIN." + var;
  3088                 place[var] = QStringList(real_template);
  3015                 place[var] = QStringList(real_template);
  3089             }
  3016             }
  3090         } else {
  3017         } else {
  3164         var = ".BUILTIN.HOST." + type;
  3091         var = ".BUILTIN.HOST." + type;
  3165         place[var] = QStringList(ret);
  3092         place[var] = QStringList(ret);
  3166     } else if (var == QLatin1String("QMAKE_DIR_SEP")) {
  3093     } else if (var == QLatin1String("QMAKE_DIR_SEP")) {
  3167         if (place[var].isEmpty())
  3094         if (place[var].isEmpty())
  3168             return values("DIR_SEPARATOR", place);
  3095             return values("DIR_SEPARATOR", place);
       
  3096     } else if (var == QLatin1String("QMAKE_EXT_OBJ")) {
       
  3097         if (place[var].isEmpty()) {
       
  3098             var = ".BUILTIN." + var;
       
  3099             place[var] = QStringList(Option::obj_ext);
       
  3100         }
       
  3101     } else if (var == QLatin1String("QMAKE_QMAKE")) {
       
  3102         if (place[var].isEmpty()) {
       
  3103             if (!Option::qmake_abslocation.isNull())
       
  3104                 place[var] = QStringList(Option::qmake_abslocation);
       
  3105             else
       
  3106                 place[var] = QStringList(Option::fixPathToTargetOS(
       
  3107                         QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmake", false));
       
  3108         }
  3169     } else if (var == QLatin1String("EPOCROOT")) {
  3109     } else if (var == QLatin1String("EPOCROOT")) {
  3170         if (place[var].isEmpty())
  3110         if (place[var].isEmpty())
  3171             place[var] = QStringList(epocRoot());
  3111             place[var] = QStringList(epocRoot());
  3172     }
  3112     }
       
  3113 #if defined(Q_OS_WIN32) && defined(Q_CC_MSVC)
       
  3114       else if(var.startsWith(QLatin1String("QMAKE_TARGET."))) {
       
  3115             QString ret, type = var.mid(13);
       
  3116             if(type == "arch") {
       
  3117                 QString paths = qgetenv("PATH");
       
  3118                 QString vcBin64 = qgetenv("VCINSTALLDIR").append("\\bin\\amd64");
       
  3119                 QString vcBinX86_64 = qgetenv("VCINSTALLDIR").append("\\bin\\x86_amd64");
       
  3120                 if(paths.contains(vcBin64,Qt::CaseInsensitive) || paths.contains(vcBinX86_64,Qt::CaseInsensitive))
       
  3121                     ret = "x86_64";
       
  3122                 else
       
  3123                     ret = "x86";
       
  3124             }
       
  3125             place[var] = QStringList(ret);
       
  3126     }
       
  3127 #endif
  3173     //qDebug("REPLACE [%s]->[%s]", qPrintable(var), qPrintable(place[var].join("::")));
  3128     //qDebug("REPLACE [%s]->[%s]", qPrintable(var), qPrintable(place[var].join("::")));
  3174     return place[var];
  3129     return place[var];
  3175 }
  3130 }
  3176 
  3131 
       
  3132 bool QMakeProject::isEmpty(const QString &v)
       
  3133 {
       
  3134     QMap<QString, QStringList>::ConstIterator it = vars.constFind(varMap(v));
       
  3135     return it == vars.constEnd() || it->isEmpty();
       
  3136 }
       
  3137 
  3177 QT_END_NAMESPACE
  3138 QT_END_NAMESPACE