📄 makefile.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 "makefile.h"
#include "option.h"
#include "cachekeys.h"
#include "meta.h"
#include <qdir.h>
#include <qfile.h>
#include <qtextstream.h>
#include <qregexp.h>
#include <qhash.h>
#include <qbuffer.h>
#include <qsettings.h>
#include <qdatetime.h>
#if defined(Q_OS_UNIX)
#include <unistd.h>
#else
#include <io.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
// Well, Windows doesn't have this, so here's the macro
#ifndef S_ISDIR
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
/**
* If \a in contains spaces, make sure that it is quoted on windows,
* and escape the spaces on unix.
* If \a in is already quoted or escaped, it will return \a in unmodified.
*/
static QString fixFilenameForMakefileOutput(const QString &in)
{
if (in.indexOf(' ') != -1) {
#ifdef Q_OS_WIN
if (!((in.startsWith('\"') && in.endsWith('\"')) || (in.startsWith('\'') && in.endsWith('\''))))
{
return QLatin1String("\"") + in + QLatin1String("\"");
}
#else
QString out;
out.reserve(in.count());
for (int i = 0; i < in.count(); ++i) {
QChar c = in.at(i);
if (c == QLatin1Char(' ')) {
// Only escape it if isn't already escaped
if (i == 0 || in.at(i - 1) != QLatin1Char('\\')) {
out += QLatin1Char('\\');
}
}
out += c;
}
return out;
#endif
}
return in;
}
QString mkdir_p_asstring(const QString &dir)
{
QString ret = "@$(CHK_DIR_EXISTS) \"" + dir + "\" ";
if(Option::target_mode == Option::TARG_WIN_MODE)
ret += "$(MKDIR)";
else
ret += "|| $(MKDIR)";
ret += " \"" + dir + "\"";
return ret;
}
static bool createDir(QString path)
{
path = Option::fixPathToLocalOS(path);
if(QFile::exists(path))
return true;
QDir d;
if(path.startsWith(QDir::separator())) {
d.cd(QString(QDir::separator()));
path = path.right(path.length() - 1);
}
bool ret = true;
#ifdef Q_WS_WIN
bool driveExists = true;
if(!QDir::isRelativePath(path)) {
if(QFile::exists(path.left(3))) {
d.cd(path.left(3));
path = path.right(path.length() - 3);
} else {
warn_msg(WarnLogic, "Cannot access drive '%s' (%s)",
path.left(3).toLatin1().data(), path.toLatin1().data());
driveExists = false;
}
}
if(driveExists)
#endif
{
QStringList subs = path.split(QDir::separator());
for(QStringList::Iterator subit = subs.begin(); subit != subs.end(); ++subit) {
if(!d.cd(*subit)) {
d.mkdir((*subit));
if(d.exists((*subit))) {
d.cd((*subit));
} else {
ret = false;
break;
}
}
}
}
return ret;
}
// ** base makefile generator
MakefileGenerator::MakefileGenerator() :
init_opath_already(false), init_already(false), no_io(false), project(0)
{
}
void
MakefileGenerator::verifyCompilers()
{
QMap<QString, QStringList> &v = project->variables();
QStringList &quc = v["QMAKE_EXTRA_COMPILERS"];
for(int i = 0; i < quc.size(); ) {
bool error = false;
QString comp = quc.at(i);
if(v[comp + ".output"].isEmpty()) {
error = true;
warn_msg(WarnLogic, "Compiler: %s: No output file specified", comp.toLatin1().constData());
} else if(v[comp + ".input"].isEmpty()) {
error = true;
warn_msg(WarnLogic, "Compiler: %s: No input variable specified", comp.toLatin1().constData());
}
if(error)
quc.removeAt(i);
else
++i;
}
}
void
MakefileGenerator::initOutPaths()
{
if(init_opath_already)
return;
verifyCompilers();
init_opath_already = true;
QMap<QString, QStringList> &v = project->variables();
//for shadow builds
if(!v.contains("QMAKE_ABSOLUTE_SOURCE_PATH")) {
if(Option::mkfile::do_cache && !Option::mkfile::cachefile.isEmpty() &&
v.contains("QMAKE_ABSOLUTE_SOURCE_ROOT")) {
QString root = v["QMAKE_ABSOLUTE_SOURCE_ROOT"].first();
root = Option::fixPathToTargetOS(root);
if(!root.isEmpty()) {
QFileInfo fi = fileInfo(Option::mkfile::cachefile);
if(!fi.makeAbsolute()) {
QString cache_r = fi.path(), pwd = Option::output_dir;
if(pwd.startsWith(cache_r) && !pwd.startsWith(root)) {
pwd = Option::fixPathToTargetOS(root + pwd.mid(cache_r.length()));
if(exists(pwd))
v.insert("QMAKE_ABSOLUTE_SOURCE_PATH", QStringList(pwd));
}
}
}
}
}
if(!v["QMAKE_ABSOLUTE_SOURCE_PATH"].isEmpty()) {
QString &asp = v["QMAKE_ABSOLUTE_SOURCE_PATH"].first();
asp = Option::fixPathToTargetOS(asp);
if(asp.isEmpty() || asp == Option::output_dir) //if they're the same, why bother?
v["QMAKE_ABSOLUTE_SOURCE_PATH"].clear();
}
QString currentDir = qmake_getpwd(); //just to go back to
//some builtin directories
QString dirs[] = { QString("OBJECTS_DIR"), QString("DESTDIR"),
QString("SUBLIBS_DIR"), QString("DLLDESTDIR"),
QString("PRECOMPILED_DIR"), QString() };
for(int x = 0; true; x++) {
if(dirs[x].isNull())
break;
if(!v[dirs[x]].isEmpty()) {
const QString orig_path = v[dirs[x]].first();
QString &pathRef = v[dirs[x]].first();
pathRef = fileFixify(pathRef, Option::output_dir, Option::output_dir);
#ifdef Q_WS_WIN
// We don't want to add a separator for DLLDESTDIR on Windows
if(!(dirs[x] == "DLLDESTDIR"))
#endif
{
if(pathRef.right(Option::dir_sep.length()) != Option::dir_sep)
pathRef += Option::dir_sep;
}
if(noIO())
continue;
QString path = project->first(dirs[x]); //not to be changed any further
path = fileFixify(path, currentDir, Option::output_dir);
debug_msg(3, "Fixed output_dir %s (%s) into %s", dirs[x].toLatin1().constData(),
orig_path.toLatin1().constData(), path.toLatin1().constData());
if(!createDir(path))
warn_msg(WarnLogic, "%s: Cannot access directory '%s'", dirs[x].toLatin1().constData(),
path.toLatin1().constData());
}
}
//out paths from the extra compilers
const QStringList &quc = project->variables()["QMAKE_EXTRA_COMPILERS"];
for(QStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) {
QString tmp_out = project->variables()[(*it) + ".output"].first();
if(tmp_out.isEmpty())
continue;
const QStringList &tmp = project->variables()[(*it) + ".input"];
for(QStringList::ConstIterator it2 = tmp.begin(); it2 != tmp.end(); ++it2) {
QStringList &inputs = project->variables()[(*it2)];
for(QStringList::Iterator input = inputs.begin(); input != inputs.end(); ++input) {
(*input) = fileFixify((*input), Option::output_dir, Option::output_dir);
QString path = replaceExtraCompilerVariables(tmp_out, (*input), QString());
path = Option::fixPathToTargetOS(path);
int slash = path.lastIndexOf(Option::dir_sep);
if(slash != -1) {
path = path.left(slash);
if(path != "." &&
!createDir(fileFixify(path, qmake_getpwd(), Option::output_dir)))
warn_msg(WarnLogic, "%s: Cannot access directory '%s'",
(*it).toLatin1().constData(), path.toLatin1().constData());
}
}
}
}
if(!v["DESTDIR"].isEmpty()) {
QDir d(v["DESTDIR"].first());
if(Option::fixPathToLocalOS(d.absolutePath()) == Option::fixPathToLocalOS(Option::output_dir))
v.remove("DESTDIR");
}
QDir::current().cd(currentDir);
}
QMakeProject
*MakefileGenerator::projectFile() const
{
return project;
}
void
MakefileGenerator::setProjectFile(QMakeProject *p)
{
if(project)
return;
project = p;
init();
usePlatformDir();
findLibraries();
if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE &&
project->isActiveConfig("link_prl")) //load up prl's'
processPrlFiles();
}
QStringList
MakefileGenerator::findFilesInVPATH(QStringList l, uchar flags, const QString &vpath_var)
{
QStringList vpath;
QMap<QString, QStringList> &v = project->variables();
for(int val_it = 0; val_it < l.count(); ) {
bool remove_file = false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -