📄 project.cpp
字号:
finished = false;
break;
}
}
}
if(finished)
break;
}
}
// now let the user override the template from an option..
if(!Option::user_template.isEmpty()) {
QString s;
if (!vars["TEMPLATE"].isEmpty())
s = vars["TEMPLATE"].first();
debug_msg(1, "Overriding TEMPLATE (%s) with: %s", s.toLatin1().constData(),
Option::user_template.toLatin1().constData());
vars["TEMPLATE"].clear();
vars["TEMPLATE"].append(Option::user_template);
}
QStringList &templ = vars["TEMPLATE"];
if(templ.isEmpty())
templ.append(QString("app"));
else if(vars["TEMPLATE"].first().endsWith(".t"))
templ = QStringList(templ.first().left(templ.first().length() - 2));
if(!Option::user_template_prefix.isEmpty() && !templ.first().startsWith(Option::user_template_prefix))
templ.first().prepend(Option::user_template_prefix);
QString test_version = QString::fromLocal8Bit(qgetenv("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.isEmpty() && ver != test_version) {
ver = test_version;
fprintf(stderr,("Changed QT version number to " + test_version + "!\n").toLatin1());
}
}
}
Option::postProcessProject(this); // let Option post-process
return true;
}
bool
QMakeProject::isActiveConfig(const QString &x, bool regex, QMap<QString, QStringList> *place)
{
if(x.isEmpty())
return true;
//magic types for easy flipping
if(x == "true")
return true;
else if(x == "false")
return false;
//mkspecs
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;
QRegExp re(x, Qt::CaseSensitive, QRegExp::Wildcard);
QString spec = Option::mkfile::qmakespec.right(Option::mkfile::qmakespec.length() -
(Option::mkfile::qmakespec.lastIndexOf(QDir::separator())+1));
if((regex && re.exactMatch(spec)) || (!regex && spec == x))
return true;
#ifdef Q_OS_UNIX
else if(spec == "default") {
static char *buffer = NULL;
if(!buffer) {
buffer = (char *)malloc(1024);
qmakeAddCacheClear(qmakeFreeCacheClear, (void**)&buffer);
}
int l = readlink(Option::mkfile::qmakespec.toLatin1(), buffer, 1024);
if(l != -1) {
buffer[l] = '\0';
QString r = buffer;
if(r.lastIndexOf('/') != -1)
r = r.mid(r.lastIndexOf('/') + 1);
if((regex && re.exactMatch(r)) || (!regex && r == x))
return true;
}
}
#endif
//simple matching
const QStringList &configs = (place ? (*place)["CONFIG"] : vars["CONFIG"]);
for(QStringList::ConstIterator it = configs.begin(); it != configs.end(); ++it) {
if(((regex && re.exactMatch((*it))) || (!regex && (*it) == x)) && re.exactMatch((*it)))
return true;
}
return false;
}
bool
QMakeProject::doProjectTest(QString str, QMap<QString, QStringList> &place)
{
QString chk = remove_quotes(str);
if(chk.isEmpty())
return true;
bool invert_test = (chk.left(1) == "!");
if(invert_test)
chk = chk.right(chk.length() - 1);
bool test=false;
int lparen = chk.indexOf('(');
if(lparen != -1) { // if there is an lparen in the chk, it IS a function
int rparen = chk.indexOf(')', lparen);
if(rparen == -1) {
QByteArray error;
error.reserve(256);
#if defined(_MSC_VER) && _MSC_VER >= 1400
sprintf_s(error.data(), 256, "Function (in REQUIRES) missing right paren: %s",
chk.toLatin1().constData());
#else
sprintf(error.data(), "Function (in REQUIRES) missing right paren: %s",
chk.toLatin1().constData());
#endif
qmake_error_msg(error);
} else {
QString func = chk.left(lparen);
test = doProjectTest(func, chk.mid(lparen+1, rparen - lparen - 1), place);
}
} else {
test = isActiveConfig(chk, true, &place);
}
if(invert_test)
return !test;
return test;
}
bool
QMakeProject::doProjectTest(QString func, const QString ¶ms,
QMap<QString, QStringList> &place)
{
return doProjectTest(func, split_arg_list(params), place);
}
QMakeProject::IncludeStatus
QMakeProject::doProjectInclude(QString file, uchar flags, QMap<QString, QStringList> &place)
{
if(flags & IncludeFlagFeature) {
if(!file.endsWith(Option::prf_ext))
file += Option::prf_ext;
if(file.indexOf(Option::dir_sep) == -1 || !QFile::exists(file)) {
bool found = false;
static QStringList *feature_roots = 0;
if(!feature_roots) {
feature_roots = new QStringList(qmake_feature_paths(prop));
qmakeAddCacheClear(qmakeDeleteCacheClear_QStringList, (void**)&feature_roots);
}
debug_msg(2, "Looking for feature '%s' in (%s)", file.toLatin1().constData(),
feature_roots->join("::").toLatin1().constData());
int start_root = 0;
if(parser.from_file) {
QFileInfo currFile(parser.file), prfFile(file);
if(currFile.fileName() == prfFile.fileName()) {
currFile = QFileInfo(currFile.canonicalFilePath());
for(int root = 0; root < feature_roots->size(); ++root) {
prfFile = QFileInfo(feature_roots->at(root) +
QDir::separator() + file).canonicalFilePath();
if(prfFile == currFile) {
start_root = root+1;
break;
}
}
}
}
for(int root = start_root; root < feature_roots->size(); ++root) {
QString prf(feature_roots->at(root) + QDir::separator() + file);
if(QFile::exists(prf)) {
found = true;
file = prf;
break;
}
}
if(!found)
return IncludeNoExist;
if(place["QMAKE_INTERNAL_INCLUDED_FEATURES"].indexOf(file) != -1)
return IncludeFeatureAlreadyLoaded;
place["QMAKE_INTERNAL_INCLUDED_FEATURES"].append(file);
}
}
if(QDir::isRelativePath(file)) {
QStringList include_roots;
include_roots << Option::output_dir;
if(Option::output_dir != qmake_getpwd())
include_roots << qmake_getpwd();
for(int root = 0; root < include_roots.size(); ++root) {
QString testName = QDir::convertSeparators(include_roots[root]);
if (!testName.endsWith(QString(QDir::separator())))
testName += QDir::separator();
testName += file;
if(QFile::exists(testName)) {
file = testName;
break;
}
}
}
if(!QFile::exists(file))
return IncludeNoExist;
if(Option::mkfile::do_preprocess) //nice to see this first..
fprintf(stderr, "#switching file %s(%s) - %s:%d\n", (flags & IncludeFlagFeature) ? "load" : "include",
file.toLatin1().constData(),
parser.file.toLatin1().constData(), parser.line_no);
debug_msg(1, "Project Parser: %s'ing file %s.", (flags & IncludeFlagFeature) ? "load" : "include",
file.toLatin1().constData());
QString orig_file = file;
int di = file.lastIndexOf(QDir::separator());
QString oldpwd = qmake_getpwd();
if(di != -1) {
if(!qmake_setpwd(file.left(file.lastIndexOf(QDir::separator())))) {
fprintf(stderr, "Cannot find directory: %s\n", file.left(di).toLatin1().constData());
return IncludeFailure;
}
file = file.right(file.length() - di - 1);
}
parser_info pi = parser;
QStack<ScopeBlock> sc = scope_blocks;
IteratorBlock *it = iterator;
FunctionBlock *fu = function;
bool parsed = false;
if(flags & IncludeFlagNewProject) {
// The "project's variables" are used in other places (eg. export()) so it's not
// possible to use "place" everywhere. Instead just set variables and grab them later
QMakeProject proj;
proj.variables() = place;
if(proj.doProjectInclude("default_pre", IncludeFlagFeature, proj.variables()) == IncludeNoExist)
proj.doProjectInclude("default", IncludeFlagFeature, proj.variables());
parsed = proj.read(file, proj.variables());
place = proj.variables();
} else {
parsed = read(file, place);
}
if(parsed) {
if(place["QMAKE_INTERNAL_INCLUDED_FILES"].indexOf(orig_file) == -1)
place["QMAKE_INTERNAL_INCLUDED_FILES"].append(orig_file);
} else {
warn_msg(WarnParser, "%s:%d: Failure to include file %s.",
pi.file.toLatin1().constData(), pi.line_no, orig_file.toLatin1().constData());
}
iterator = it;
function = fu;
parser = pi;
scope_blocks = sc;
qmake_setpwd(oldpwd);
if(!parsed)
return IncludeParseFailure;
return IncludeSuccess;
}
QString
QMakeProject::doProjectExpand(QString func, const QString ¶ms,
QMap<QString, QStringList> &place)
{
return doProjectExpand(func, split_arg_list(params), place);
}
QString
QMakeProject::doProjectExpand(QString func, QStringList args,
QMap<QString, QStringList> &place)
{
func = func.trimmed();
for(QStringList::Iterator arit = args.begin(); arit != args.end(); ++arit)
doVariableReplace((*arit), place);
enum ExpandFunc { E_MEMBER=1, E_FIRST, E_LAST, E_CAT, E_FROMFILE, E_EVAL, E_LIST,
E_SPRINTF, E_JOIN, E_SPLIT, E_BASENAME, E_DIRNAME, E_SECTION,
E_FIND, E_SYSTEM, E_UNIQUE, E_QUOTE, E_UPPER, E_LOWER, E_FILES,
E_PROMPT, E_RE_ESCAPE };
static QMap<QString, int> *expands = 0;
if(!expands) {
expands = new QMap<QString, int>;
qmakeAddCacheClear(qmakeDeleteCacheClear_QMapStringInt, (void**)&expands);
expands->insert("member", E_MEMBER);
expands->insert("first", E_FIRST);
expands->insert("last", E_LAST);
expands->insert("cat", E_CAT);
expands->insert("fromfile", E_FROMFILE);
expands->insert("eval", E_EVAL);
expands->insert("list", E_LIST);
expands->insert("sprintf", E_SPRINTF);
expands->insert("join", E_JOIN);
expands->insert("split", E_SPLIT);
expands->insert("basename", E_BASENAME);
expands->insert("dirname", E_DIRNAME);
expands->insert("section", E_SECTION);
expands->insert("find", E_FIND);
expands->insert("system", E_SYSTEM);
expands->insert("unique", E_UNIQUE);
expands->insert("quote", E_QUOTE);
expands->insert("upper", E_UPPER);
expands->insert("lower", E_LOWER);
expands->insert("re_escape", E_RE_ESCAPE);
expands->insert("files", E_FILES);
expands->insert("prompt", E_PROMPT);
}
ExpandFunc func_t = (ExpandFunc)expands->value(func.toLower());
debug_msg(1, "Running project expand: %s(%s) [%d]",
func.toLatin1().constData(), args.join("::").toLatin1().constData(), func_t);
QString ret;
switch(func_t) {
case E_MEMBER: {
if(args.count() < 1 || args.count() > 3) {
fprintf(stderr, "%s:%d: member(var, start, end) requires three arguments.\n",
parser.file.toLatin1().constData(), parser.line_no);
} else {
bool ok = true;
const QStringList &var = place[varMap(args.first())];
int start = 0, end = 0;
if(args.count() >= 2) {
QString start_str = args[1];
start = start_str.toInt(&ok);
if(!ok) {
if(args.count() == 2)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -