📄 makefile.cpp
字号:
QString &val = l[val_it];
if(!val.isEmpty()) {
QString file = fixEnvVariables(val);
if(!(flags & VPATH_NoFixify))
file = fileFixify(file, qmake_getpwd(), Option::output_dir);
if (file.at(0) == '\"' && file.at(file.length() - 1) == '\"')
file = file.mid(1, file.length() - 2);
if(exists(file)) {
++val_it;
continue;
}
bool found = false;
if(QDir::isRelativePath(val)) {
if(vpath.isEmpty()) {
if(!vpath_var.isEmpty())
vpath = v[vpath_var];
vpath += v["VPATH"] + v["QMAKE_ABSOLUTE_SOURCE_PATH"] + v["DEPENDPATH"];
if(Option::output_dir != qmake_getpwd())
vpath += Option::output_dir;
}
for(QStringList::Iterator vpath_it = vpath.begin();
vpath_it != vpath.end(); ++vpath_it) {
QString real_dir = Option::fixPathToLocalOS((*vpath_it));
if(exists(real_dir + QDir::separator() + val)) {
QString dir = (*vpath_it);
if(dir.right(Option::dir_sep.length()) != Option::dir_sep)
dir += Option::dir_sep;
val = dir + val;
if(!(flags & VPATH_NoFixify))
val = fileFixify(val);
found = true;
debug_msg(1, "Found file through vpath %s -> %s",
file.toLatin1().constData(), val.toLatin1().constData());
break;
}
}
}
if(!found) {
QString dir, regex = val, real_dir;
if(regex.lastIndexOf(Option::dir_sep) != -1) {
dir = regex.left(regex.lastIndexOf(Option::dir_sep) + 1);
real_dir = dir;
if(!(flags & VPATH_NoFixify))
real_dir = fileFixify(real_dir, qmake_getpwd(), Option::output_dir);
regex = regex.right(regex.length() - dir.length());
}
if(real_dir.isEmpty() || exists(real_dir)) {
QStringList files = QDir(real_dir).entryList(QStringList(regex));
if(files.isEmpty()) {
debug_msg(1, "%s:%d Failure to find %s in vpath (%s)",
__FILE__, __LINE__,
val.toLatin1().constData(), vpath.join("::").toLatin1().constData());
if(flags & VPATH_RemoveMissingFiles)
remove_file = true;
else if(flags & VPATH_WarnMissingFiles)
warn_msg(WarnLogic, "Failure to find: %s", val.toLatin1().constData());
} else {
l.removeAt(val_it);
QString a;
for(int i = (int)files.count()-1; i >= 0; i--) {
if(files[i] == "." || files[i] == "..")
continue;
a = dir + files[i];
if(!(flags & VPATH_NoFixify))
a = fileFixify(a);
l.insert(val_it, a);
}
}
} else {
debug_msg(1, "%s:%d Cannot match %s%c%s, as %s does not exist.",
__FILE__, __LINE__, real_dir.toLatin1().constData(),
QDir::separator().toLatin1(),
regex.toLatin1().constData(), real_dir.toLatin1().constData());
if(flags & VPATH_RemoveMissingFiles)
remove_file = true;
else if(flags & VPATH_WarnMissingFiles)
warn_msg(WarnLogic, "Failure to find: %s", val.toLatin1().constData());
}
}
}
if(remove_file)
l.removeAt(val_it);
else
++val_it;
}
return l;
}
void
MakefileGenerator::initCompiler(const MakefileGenerator::Compiler &comp)
{
QMap<QString, QStringList> &v = project->variables();
QStringList &l = v[comp.variable_in];
// find all the relevant file inputs
if(!init_compiler_already.contains(comp.variable_in)) {
init_compiler_already.insert(comp.variable_in, true);
if(!noIO())
l = findFilesInVPATH(l, (comp.flags & Compiler::CompilerRemoveNoExist) ?
VPATH_RemoveMissingFiles : VPATH_WarnMissingFiles, "VPATH_" + comp.variable_in);
}
}
void
MakefileGenerator::init()
{
initOutPaths();
if(init_already)
return;
verifyCompilers();
init_already = true;
QMap<QString, QStringList> &v = project->variables();
QStringList &quc = v["QMAKE_EXTRA_COMPILERS"];
//make sure the COMPILERS are in the correct input/output chain order
for(int comp_out = 0, jump_count = 0; comp_out < quc.size(); ++comp_out) {
continue_compiler_chain:
if(jump_count > quc.size()) //just to avoid an infinite loop here
break;
if(project->variables().contains(quc.at(comp_out) + ".variable_out")) {
const QStringList &outputs = project->variables().value(quc.at(comp_out) + ".variable_out");
for(int out = 0; out < outputs.size(); ++out) {
for(int comp_in = 0; comp_in < quc.size(); ++comp_in) {
if(comp_in == comp_out)
continue;
if(project->variables().contains(quc.at(comp_in) + ".input")) {
const QStringList &inputs = project->variables().value(quc.at(comp_in) + ".input");
for(int in = 0; in < inputs.size(); ++in) {
if(inputs.at(in) == outputs.at(out) && comp_out > comp_in) {
++jump_count;
//move comp_out to comp_in and continue the compiler chain
quc.move(comp_out, comp_in);
comp_out = comp_in;
goto continue_compiler_chain;
}
}
}
}
}
}
}
if(!project->isEmpty("QMAKE_SUBSTITUTES")) {
const QStringList &subs = v["QMAKE_SUBSTITUTES"];
for(int i = 0; i < subs.size(); ++i) {
if(!subs.at(i).endsWith(".in")) {
warn_msg(WarnLogic, "Substitute '%s' does not end with '.in'",
subs.at(i).toLatin1().constData());
continue;
}
QFile in(fileFixify(subs.at(i))), out(fileInfo(subs.at(i)).fileName());
if(out.fileName().endsWith(".in"))
out.setFileName(out.fileName().left(out.fileName().length()-3));
if(in.open(QFile::ReadOnly)) {
QString contents;
QStack<int> state;
enum { IN_CONDITION, MET_CONDITION, PENDING_CONDITION };
for(int count = 1; !in.atEnd(); ++count) {
QString line = QString::fromUtf8(in.readLine());
if(line.startsWith("!!IF ")) {
if(state.isEmpty() || state.top() == IN_CONDITION) {
QString test = line.mid(5, line.length()-(5+1));
if(project->test(test))
state.push(IN_CONDITION);
else
state.push(PENDING_CONDITION);
} else {
state.push(MET_CONDITION);
}
} else if(line.startsWith("!!ELIF ")) {
if(state.isEmpty()) {
warn_msg(WarnLogic, "(%s:%d): Unexpected else condition",
in.fileName().toLatin1().constData(), count);
} else if(state.top() == PENDING_CONDITION) {
QString test = line.mid(7, line.length()-(7+1));
if(project->test(test)) {
state.pop();
state.push(IN_CONDITION);
}
} else if(state.top() == IN_CONDITION) {
state.pop();
state.push(MET_CONDITION);
}
} else if(line.startsWith("!!ELSE")) {
if(state.isEmpty()) {
warn_msg(WarnLogic, "(%s:%d): Unexpected else condition",
in.fileName().toLatin1().constData(), count);
} else if(state.top() == PENDING_CONDITION) {
state.pop();
state.push(IN_CONDITION);
} else if(state.top() == IN_CONDITION) {
state.pop();
state.push(MET_CONDITION);
}
} else if(line.startsWith("!!ENDIF")) {
if(state.isEmpty())
warn_msg(WarnLogic, "(%s:%d): Unexpected endif",
in.fileName().toLatin1().constData(), count);
else
state.pop();
} else if(state.isEmpty() || state.top() == IN_CONDITION) {
contents += project->expand(line);
}
}
if(out.exists() && out.open(QFile::ReadOnly)) {
QString old = QString::fromUtf8(out.readAll());
if(contents == old) {
v["QMAKE_INTERNAL_INCLUDED_FILES"].append(subs.at(i));
continue;
}
out.close();
if(!out.remove()) {
warn_msg(WarnLogic, "Cannot clear substitute '%s'",
out.fileName().toLatin1().constData());
continue;
}
}
if(out.open(QFile::WriteOnly)) {
v["QMAKE_INTERNAL_INCLUDED_FILES"].append(subs.at(i));
out.write(contents.toUtf8());
} else {
warn_msg(WarnLogic, "Cannot open substitute for output '%s'",
out.fileName().toLatin1().constData());
}
} else {
warn_msg(WarnLogic, "Cannot open substitute for input '%s'",
in.fileName().toLatin1().constData());
}
}
}
int x;
//build up a list of compilers
QList<Compiler> compilers;
{
const char *builtins[] = { "OBJECTS", "LEXSOURCES", "YACCSOURCES", "SOURCES", "PRECOMPILED_HEADER", 0 };
for(x = 0; builtins[x]; ++x) {
Compiler compiler;
compiler.variable_in = builtins[x];
compiler.flags = Compiler::CompilerBuiltin;
compiler.type = QMakeSourceFileInfo::TYPE_C;
if(!strcmp(builtins[x], "OBJECTS"))
compiler.flags |= Compiler::CompilerNoCheckDeps;
compilers.append(compiler);
}
for(QStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) {
if(!v[(*it) + ".output"].isEmpty()) {
const QStringList &inputs = v[(*it) + ".input"];
for(x = 0; x < inputs.size(); ++x) {
Compiler compiler;
compiler.variable_in = inputs.at(x);
compiler.flags = Compiler::CompilerNoFlags;
if(v[(*it) + ".CONFIG"].indexOf("ignore_no_exist") != -1)
compiler.flags |= Compiler::CompilerRemoveNoExist;
if(v[(*it) + ".CONFIG"].indexOf("no_dependencies") != -1)
compiler.flags |= Compiler::CompilerNoCheckDeps;
QString dep_type;
if(!project->isEmpty((*it) + ".dependency_type"))
dep_type = project->first((*it) + ".dependency_type");
if (dep_type.isEmpty())
compiler.type = QMakeSourceFileInfo::TYPE_UNKNOWN;
else if(dep_type == "TYPE_UI")
compiler.type = QMakeSourceFileInfo::TYPE_UI;
else
compiler.type = QMakeSourceFileInfo::TYPE_C;
compilers.append(compiler);
}
}
}
}
{ //do the path fixifying
QStringList paths;
for(x = 0; x < compilers.count(); ++x) {
if(!paths.contains(compilers.at(x).variable_in))
paths << compilers.at(x).variable_in;
}
paths << "INCLUDEPATH" << "QMAKE_INTERNAL_INCLUDED_FILES" << "PRECOMPILED_HEADER";
for(int y = 0; y < paths.count(); y++) {
QStringList &l = v[paths[y]];
for(QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
if((*it).isEmpty())
continue;
if(exists((*it)))
(*it) = fileFixify((*it));
}
}
}
if(noIO() || !doDepends())
QMakeSourceFileInfo::setDependencyMode(QMakeSourceFileInfo::NonRecursive);
for(x = 0; x < compilers.count(); ++x)
initCompiler(compilers.at(x));
//merge actual compiler outputs into their variable_out. This is done last so that
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -