📄 metamakefile.cpp
字号:
/****************************************************************************
**
** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.
**
** This file is part of the qmake application of the Qt Toolkit.
**
** This file may be used under the terms of the GNU General Public
** License version 2.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
** http://www.trolltech.com/products/qt/opensource.html
**
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://www.trolltech.com/products/qt/licensing.html or contact the
** sales department at sales@trolltech.com.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
#include "metamakefile.h"
#include "qregexp.h"
#include "qdir.h"
#include "makefile.h"
#include "project.h"
#include "cachekeys.h"
#define BUILDSMETATYPE 1
#define SUBDIRSMETATYPE 2
MetaMakefileGenerator::~MetaMakefileGenerator()
{
if(own_project)
delete project;
}
class BuildsMetaMakefileGenerator : public MetaMakefileGenerator
{
bool init_flag;
private:
struct Build {
QString name;
MakefileGenerator *makefile;
};
QList<Build *> makefiles;
void clearBuilds();
MakefileGenerator *processBuild(const QString &);
public:
BuildsMetaMakefileGenerator(QMakeProject *p, bool op) : MetaMakefileGenerator(p, op), init_flag(false) { }
virtual ~BuildsMetaMakefileGenerator() { clearBuilds(); }
virtual bool init();
virtual int type() const { return BUILDSMETATYPE; }
virtual bool write(const QString &);
};
void
BuildsMetaMakefileGenerator::clearBuilds()
{
for(int i = 0; i < makefiles.count(); i++) {
Build *build = makefiles[i];
if(QMakeProject *p = build->makefile->projectFile()) {
if(p != project)
delete p;
}
delete build->makefile;
delete build;
}
makefiles.clear();
}
bool
BuildsMetaMakefileGenerator::init()
{
if(init_flag)
return false;
init_flag = true;
const QStringList &builds = project->variables()["BUILDS"];
bool use_single_build = builds.isEmpty();
if(builds.count() > 1 && Option::output.fileName() == "-") {
use_single_build = true;
warn_msg(WarnLogic, "Cannot direct to stdout when using multiple BUILDS.");
} else if(0 && !use_single_build && project->first("TEMPLATE") == "subdirs") {
use_single_build = true;
warn_msg(WarnLogic, "Cannot specify multiple builds with TEMPLATE subdirs.");
}
if(!use_single_build) {
for(int i = 0; i < builds.count(); i++) {
QString build = builds[i];
MakefileGenerator *makefile = processBuild(build);
if(!makefile)
return false;
if(!makefile->supportsMetaBuild()) {
warn_msg(WarnLogic, "QMAKESPEC does not support multiple BUILDS.");
clearBuilds();
use_single_build = true;
break;
} else {
Build *b = new Build;
if(builds.count() != 1)
b->name = build;
b->makefile = makefile;
makefiles += b;
}
}
}
if(use_single_build) {
Build *build = new Build;
build->makefile = createMakefileGenerator(project, false);
makefiles += build;
}
return true;
}
bool
BuildsMetaMakefileGenerator::write(const QString &oldpwd)
{
Build *glue = 0;
if(!makefiles.isEmpty() && !makefiles.first()->name.isNull()) {
glue = new Build;
glue->makefile = createMakefileGenerator(project, true);
makefiles += glue;
}
bool ret = true;
const QString &output_name = Option::output.fileName();
for(int i = 0; ret && i < makefiles.count(); i++) {
Option::output.setFileName(output_name);
Build *build = makefiles[i];
bool using_stdout = false;
if(build->makefile && (Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT)
&& (!build->makefile->supportsMergedBuilds()
|| (build->makefile->supportsMergedBuilds() && (!glue || build == glue)))) {
//open output
if(!(Option::output.isOpen())) {
if(Option::output.fileName() == "-") {
Option::output.setFileName("");
Option::output_dir = qmake_getpwd();
Option::output.open(stdout, QIODevice::WriteOnly | QIODevice::Text);
using_stdout = true;
} else {
if(Option::output.fileName().isEmpty() && Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE)
Option::output.setFileName(project->first("QMAKE_MAKEFILE"));
Option::output_dir = oldpwd;
if(!build->makefile->openOutput(Option::output, build->name)) {
fprintf(stderr, "Failure to open file: %s\n",
Option::output.fileName().isEmpty() ? "(stdout)" :
Option::output.fileName().toLatin1().constData());
return false;
}
}
}
} else {
using_stdout = true; //kind of..
}
if(!build->makefile) {
ret = false;
} else if(build == glue) {
ret = build->makefile->writeProjectMakefile();
} else {
ret = build->makefile->write();
if (glue && glue->makefile->supportsMergedBuilds())
ret = glue->makefile->mergeBuildProject(build->makefile);
}
if(!using_stdout) {
Option::output.close();
if(!ret)
Option::output.remove();
}
// debugging
if(Option::debug_level) {
QMap<QString, QStringList> &vars = project->variables();
for(QMap<QString, QStringList>::Iterator it = vars.begin(); it != vars.end(); ++it) {
if(!it.key().startsWith(".") && !it.value().isEmpty())
debug_msg(1, "%s === %s", it.key().toLatin1().constData(),
it.value().join(" :: ").toLatin1().constData());
}
}
}
return ret;
}
MakefileGenerator
*BuildsMetaMakefileGenerator::processBuild(const QString &build)
{
if(project) {
debug_msg(1, "Meta Generator: Parsing '%s' for build [%s].",
project->projectFile().toLatin1().constData(),build.toLatin1().constData());
//initialize the base
QMap<QString, QStringList> basevars;
if(!project->isEmpty(build + ".CONFIG"))
basevars["CONFIG"] += project->values(build + ".CONFIG");
basevars["CONFIG"] += build;
basevars["CONFIG"] += "build_pass";
basevars["BUILD_PASS"] = QStringList(build);
QStringList buildname = project->values(build + ".name");
basevars["BUILD_NAME"] = (buildname.isEmpty() ? QStringList(build) : buildname);
//create project
QMakeProject *build_proj = new QMakeProject(project->properities(), basevars);
//all the user configs must be set again afterwards (for .pro tests and for .prf tests)
const QStringList old_after_user_config = Option::after_user_configs;
const QStringList old_user_config = Option::user_configs;
Option::after_user_configs += basevars["CONFIG"];
Option::user_configs += basevars["CONFIG"];
build_proj->read(project->projectFile());
Option::after_user_configs = old_after_user_config;
Option::user_configs = old_user_config;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -