2011-04-27 10:05:43 +00:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
2013-01-02 11:13:29 +00:00
|
|
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
2012-09-19 12:28:29 +00:00
|
|
|
** Contact: http://www.qt-project.org/legal
|
2011-04-27 10:05:43 +00:00
|
|
|
**
|
|
|
|
** This file is part of the qmake application of the Qt Toolkit.
|
|
|
|
**
|
|
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
2012-09-19 12:28:29 +00:00
|
|
|
** Commercial License Usage
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
|
|
** a written agreement between you and Digia. For licensing terms and
|
|
|
|
** conditions see http://qt.digia.com/licensing. For further information
|
|
|
|
** use the contact form at http://qt.digia.com/contact-us.
|
|
|
|
**
|
2011-04-27 10:05:43 +00:00
|
|
|
** GNU Lesser General Public License Usage
|
2012-09-19 12:28:29 +00:00
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
|
|
** General Public License version 2.1 as published by the Free Software
|
|
|
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
|
|
** packaging of this file. Please review the following information to
|
|
|
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
|
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
|
|
**
|
|
|
|
** In addition, as a special exception, Digia gives you certain additional
|
|
|
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
2011-04-27 10:05:43 +00:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
**
|
2011-05-24 09:34:08 +00:00
|
|
|
** GNU General Public License Usage
|
2012-09-19 12:28:29 +00:00
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
** General Public License version 3.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 the GNU General Public License version 3.0 requirements will be
|
|
|
|
** met: http://www.gnu.org/copyleft/gpl.html.
|
2011-04-27 10:05:43 +00:00
|
|
|
**
|
2012-01-24 06:17:24 +00:00
|
|
|
**
|
2011-04-27 10:05:43 +00:00
|
|
|
** $QT_END_LICENSE$
|
|
|
|
**
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#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 <qdebug.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>
|
|
|
|
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
|
|
|
|
// Well, Windows doesn't have this, so here's the macro
|
|
|
|
#ifndef S_ISDIR
|
|
|
|
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
bool MakefileGenerator::canExecute(const QStringList &cmdline, int *a) const
|
|
|
|
{
|
|
|
|
int argv0 = -1;
|
|
|
|
for(int i = 0; i < cmdline.count(); ++i) {
|
|
|
|
if(!cmdline.at(i).contains('=')) {
|
|
|
|
argv0 = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(a)
|
|
|
|
*a = argv0;
|
|
|
|
if(argv0 != -1) {
|
|
|
|
const QString c = Option::fixPathToLocalOS(cmdline.at(argv0), true);
|
|
|
|
if(exists(c))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString MakefileGenerator::mkdir_p_asstring(const QString &dir, bool escape) const
|
|
|
|
{
|
2013-02-28 11:40:16 +00:00
|
|
|
QString edir = escape ? escapeFilePath(dir) : dir;
|
|
|
|
return "@" + makedir.arg(edir);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool MakefileGenerator::mkdir(const QString &in_path) const
|
|
|
|
{
|
|
|
|
QString path = Option::fixPathToLocalOS(in_path);
|
|
|
|
if(QFile::exists(path))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
QDir d;
|
|
|
|
if(path.startsWith(QDir::separator())) {
|
|
|
|
d.cd(QString(QDir::separator()));
|
|
|
|
path.remove(0, 1);
|
|
|
|
}
|
|
|
|
bool ret = true;
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
bool driveExists = true;
|
|
|
|
if(!QDir::isRelativePath(path)) {
|
|
|
|
if(QFile::exists(path.left(3))) {
|
|
|
|
d.cd(path.left(3));
|
|
|
|
path.remove(0, 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()
|
|
|
|
{
|
2012-09-06 10:21:38 +00:00
|
|
|
ProValueMap &v = project->variables();
|
|
|
|
ProStringList &quc = v["QMAKE_EXTRA_COMPILERS"];
|
2011-04-27 10:05:43 +00:00
|
|
|
for(int i = 0; i < quc.size(); ) {
|
|
|
|
bool error = false;
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProString &comp = quc.at(i);
|
|
|
|
const ProKey okey(comp + ".output");
|
|
|
|
if (v[okey].isEmpty()) {
|
|
|
|
const ProKey ofkey(comp + ".output_function");
|
|
|
|
if (!v[ofkey].isEmpty()) {
|
|
|
|
v[okey].append("${QMAKE_FUNC_FILE_IN_" + v[ofkey].first() + "}");
|
2011-04-27 10:05:43 +00:00
|
|
|
} else {
|
|
|
|
error = true;
|
|
|
|
warn_msg(WarnLogic, "Compiler: %s: No output file specified", comp.toLatin1().constData());
|
|
|
|
}
|
2012-09-06 10:21:38 +00:00
|
|
|
} else if (v[ProKey(comp + ".input")].isEmpty()) {
|
2011-04-27 10:05:43 +00:00
|
|
|
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;
|
2012-09-06 10:21:38 +00:00
|
|
|
ProValueMap &v = project->variables();
|
2011-04-27 10:05:43 +00:00
|
|
|
//for shadow builds
|
|
|
|
if(!v.contains("QMAKE_ABSOLUTE_SOURCE_PATH")) {
|
2012-09-05 16:29:19 +00:00
|
|
|
if (Option::globals->do_cache && !project->cacheFile().isEmpty() &&
|
2011-04-27 10:05:43 +00:00
|
|
|
v.contains("QMAKE_ABSOLUTE_SOURCE_ROOT")) {
|
2012-09-06 10:21:38 +00:00
|
|
|
QString root = v["QMAKE_ABSOLUTE_SOURCE_ROOT"].first().toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
root = QDir::fromNativeSeparators(root);
|
|
|
|
if(!root.isEmpty()) {
|
2012-05-10 08:41:54 +00:00
|
|
|
QFileInfo fi = fileInfo(project->cacheFile());
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!fi.makeAbsolute()) {
|
|
|
|
QString cache_r = fi.path(), pwd = Option::output_dir;
|
|
|
|
if(pwd.startsWith(cache_r) && !pwd.startsWith(root)) {
|
|
|
|
pwd = root + pwd.mid(cache_r.length());
|
|
|
|
if(exists(pwd))
|
2012-09-06 10:21:38 +00:00
|
|
|
v.insert("QMAKE_ABSOLUTE_SOURCE_PATH", ProStringList(pwd));
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!v["QMAKE_ABSOLUTE_SOURCE_PATH"].isEmpty()) {
|
2012-09-06 10:21:38 +00:00
|
|
|
ProString &asp = v["QMAKE_ABSOLUTE_SOURCE_PATH"].first();
|
|
|
|
asp = QDir::fromNativeSeparators(asp.toQString());
|
2011-04-27 10:05:43 +00:00
|
|
|
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
|
|
|
|
if(project->isEmpty("PRECOMPILED_DIR") && !project->isEmpty("OBJECTS_DIR"))
|
|
|
|
v["PRECOMPILED_DIR"] = v["OBJECTS_DIR"];
|
2012-12-21 20:08:00 +00:00
|
|
|
static const char * const dirs[] = { "OBJECTS_DIR", "DESTDIR",
|
|
|
|
"SUBLIBS_DIR", "DLLDESTDIR",
|
2012-08-20 11:04:39 +00:00
|
|
|
"PRECOMPILED_DIR", 0 };
|
|
|
|
for (int x = 0; dirs[x]; x++) {
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProKey dkey(dirs[x]);
|
|
|
|
if (v[dkey].isEmpty())
|
2011-04-27 10:05:43 +00:00
|
|
|
continue;
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProString orig_path = v[dkey].first();
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
ProString &pathRef = v[dkey].first();
|
|
|
|
pathRef = fileFixify(pathRef.toQString(), Option::output_dir, Option::output_dir);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
// We don't want to add a separator for DLLDESTDIR on Windows (###why?)
|
|
|
|
if(!(dirs[x] == "DLLDESTDIR"))
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
if(!pathRef.endsWith(Option::dir_sep))
|
|
|
|
pathRef += Option::dir_sep;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(noIO())
|
|
|
|
continue;
|
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
QString path = project->first(dkey).toQString(); //not to be changed any further
|
2011-04-27 10:05:43 +00:00
|
|
|
path = fileFixify(path, currentDir, Option::output_dir);
|
2012-08-20 11:04:39 +00:00
|
|
|
debug_msg(3, "Fixed output_dir %s (%s) into %s", dirs[x],
|
2011-04-27 10:05:43 +00:00
|
|
|
orig_path.toLatin1().constData(), path.toLatin1().constData());
|
|
|
|
if(!mkdir(path))
|
2012-08-20 11:04:39 +00:00
|
|
|
warn_msg(WarnLogic, "%s: Cannot access directory '%s'", dirs[x],
|
2011-04-27 10:05:43 +00:00
|
|
|
path.toLatin1().constData());
|
|
|
|
}
|
|
|
|
|
|
|
|
//out paths from the extra compilers
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &quc = project->values("QMAKE_EXTRA_COMPILERS");
|
|
|
|
for (ProStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) {
|
|
|
|
QString tmp_out = project->first(ProKey(*it + ".output")).toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
if(tmp_out.isEmpty())
|
|
|
|
continue;
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &tmp = project->values(ProKey(*it + ".input"));
|
|
|
|
for (ProStringList::ConstIterator it2 = tmp.begin(); it2 != tmp.end(); ++it2) {
|
|
|
|
ProStringList &inputs = project->values((*it2).toKey());
|
|
|
|
for (ProStringList::Iterator input = inputs.begin(); input != inputs.end(); ++input) {
|
|
|
|
QString finp = fileFixify((*input).toQString(), Option::output_dir, Option::output_dir);
|
|
|
|
*input = ProString(finp);
|
|
|
|
QString path = unescapeFilePath(replaceExtraCompilerVariables(tmp_out, finp, QString()));
|
2011-04-27 10:05:43 +00:00
|
|
|
path = Option::fixPathToTargetOS(path);
|
|
|
|
int slash = path.lastIndexOf(Option::dir_sep);
|
|
|
|
if(slash != -1) {
|
|
|
|
path = path.left(slash);
|
|
|
|
// Make out path only if it does not contain makefile variables
|
|
|
|
if(!path.contains("${"))
|
|
|
|
if(path != "." &&
|
|
|
|
!mkdir(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()) {
|
2012-09-06 10:21:38 +00:00
|
|
|
QDir d(v["DESTDIR"].first().toQString());
|
2011-04-27 10:05:43 +00:00
|
|
|
if(Option::fixPathToLocalOS(d.absolutePath()) == Option::fixPathToLocalOS(Option::output_dir))
|
|
|
|
v.remove("DESTDIR");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QMakeProject
|
|
|
|
*MakefileGenerator::projectFile() const
|
|
|
|
{
|
|
|
|
return project;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
MakefileGenerator::setProjectFile(QMakeProject *p)
|
|
|
|
{
|
|
|
|
if(project)
|
|
|
|
return;
|
|
|
|
project = p;
|
2012-04-17 10:15:39 +00:00
|
|
|
if (project->isActiveConfig("win32"))
|
|
|
|
target_mode = TARG_WIN_MODE;
|
2013-03-06 13:53:36 +00:00
|
|
|
else if (project->isActiveConfig("mac"))
|
|
|
|
target_mode = TARG_MAC_MODE;
|
2012-04-17 10:15:39 +00:00
|
|
|
else
|
|
|
|
target_mode = TARG_UNIX_MODE;
|
2011-04-27 10:05:43 +00:00
|
|
|
init();
|
|
|
|
findLibraries();
|
|
|
|
if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE &&
|
|
|
|
project->isActiveConfig("link_prl")) //load up prl's'
|
|
|
|
processPrlFiles();
|
|
|
|
}
|
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList
|
|
|
|
MakefileGenerator::findFilesInVPATH(ProStringList l, uchar flags, const QString &vpath_var)
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList vpath;
|
|
|
|
const ProValueMap &v = project->variables();
|
2011-04-27 10:05:43 +00:00
|
|
|
for(int val_it = 0; val_it < l.count(); ) {
|
|
|
|
bool remove_file = false;
|
2012-09-06 10:21:38 +00:00
|
|
|
ProString &val = l[val_it];
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!val.isEmpty()) {
|
2012-09-06 10:21:38 +00:00
|
|
|
QString qval = val.toQString();
|
|
|
|
QString file = fixEnvVariables(qval);
|
2013-07-04 08:40:57 +00:00
|
|
|
if (file.isEmpty()) {
|
|
|
|
++val_it;
|
|
|
|
continue;
|
|
|
|
}
|
2011-04-27 10:05:43 +00:00
|
|
|
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;
|
2012-09-06 10:21:38 +00:00
|
|
|
if (QDir::isRelativePath(qval)) {
|
2011-04-27 10:05:43 +00:00
|
|
|
if(vpath.isEmpty()) {
|
|
|
|
if(!vpath_var.isEmpty())
|
2012-09-06 10:21:38 +00:00
|
|
|
vpath = v[ProKey(vpath_var)];
|
2012-11-01 13:50:03 +00:00
|
|
|
vpath += v["VPATH"] + v["QMAKE_ABSOLUTE_SOURCE_PATH"];
|
2011-04-27 10:05:43 +00:00
|
|
|
if(Option::output_dir != qmake_getpwd())
|
2012-09-06 10:21:38 +00:00
|
|
|
vpath << Option::output_dir;
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
2012-09-06 10:21:38 +00:00
|
|
|
for (ProStringList::Iterator vpath_it = vpath.begin();
|
2011-04-27 10:05:43 +00:00
|
|
|
vpath_it != vpath.end(); ++vpath_it) {
|
2012-09-06 10:21:38 +00:00
|
|
|
QString real_dir = Option::fixPathToLocalOS((*vpath_it).toQString());
|
2011-04-27 10:05:43 +00:00
|
|
|
if(exists(real_dir + QDir::separator() + val)) {
|
2012-09-06 10:21:38 +00:00
|
|
|
ProString dir = (*vpath_it);
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!dir.endsWith(Option::dir_sep))
|
|
|
|
dir += Option::dir_sep;
|
|
|
|
val = dir + val;
|
|
|
|
if(!(flags & VPATH_NoFixify))
|
2012-09-06 10:21:38 +00:00
|
|
|
val = fileFixify(val.toQString());
|
2011-04-27 10:05:43 +00:00
|
|
|
found = true;
|
|
|
|
debug_msg(1, "Found file through vpath %s -> %s",
|
|
|
|
file.toLatin1().constData(), val.toLatin1().constData());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!found) {
|
2012-09-06 10:21:38 +00:00
|
|
|
QString dir, regex = val.toQString(), real_dir;
|
2011-04-27 10:05:43 +00:00
|
|
|
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.remove(0, 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 = real_dir + files[i];
|
|
|
|
if(!(flags & VPATH_NoFixify))
|
|
|
|
a = fileFixify(a);
|
|
|
|
l.insert(val_it, a);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
debug_msg(1, "%s:%d Cannot match %s%s, as %s does not exist.",
|
|
|
|
__FILE__, __LINE__, real_dir.toLatin1().constData(),
|
|
|
|
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)
|
|
|
|
{
|
2012-09-06 10:21:38 +00:00
|
|
|
ProValueMap &v = project->variables();
|
|
|
|
ProStringList &l = v[ProKey(comp.variable_in)];
|
2011-04-27 10:05:43 +00:00
|
|
|
// 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;
|
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
ProValueMap &v = project->variables();
|
2012-11-09 18:04:28 +00:00
|
|
|
|
|
|
|
if (v["TARGET"].isEmpty())
|
|
|
|
warn_msg(WarnLogic, "TARGET is empty");
|
2012-05-29 08:53:00 +00:00
|
|
|
|
2013-02-28 11:40:16 +00:00
|
|
|
makedir = v["QMAKE_MKDIR_CMD"].join(' ');
|
|
|
|
chkexists = v["QMAKE_CHK_EXISTS"].join(' ');
|
|
|
|
if (makedir.isEmpty()) { // Backwards compat with Qt < 5.0.2 specs
|
|
|
|
if (isWindowsShell()) {
|
|
|
|
makedir = "if not exist %1 mkdir %1 & if not exist %1 exit 1";
|
|
|
|
chkexists = "if not exist %1";
|
|
|
|
} else {
|
|
|
|
makedir = "test -d %1 || mkdir -p %1";
|
|
|
|
chkexists = "test -e %1 ||";
|
|
|
|
}
|
|
|
|
}
|
2012-05-29 08:53:00 +00:00
|
|
|
|
2013-03-18 11:21:38 +00:00
|
|
|
if (v["QMAKE_CC_O_FLAG"].isEmpty())
|
|
|
|
v["QMAKE_CC_O_FLAG"].append("-o ");
|
|
|
|
|
2013-01-30 14:58:00 +00:00
|
|
|
if (v["QMAKE_LINK_O_FLAG"].isEmpty())
|
|
|
|
v["QMAKE_LINK_O_FLAG"].append("-o ");
|
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList &quc = v["QMAKE_EXTRA_COMPILERS"];
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
//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;
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProKey vokey(quc.at(comp_out) + ".variable_out");
|
|
|
|
if (v.contains(vokey)) {
|
|
|
|
const ProStringList &outputs = v.value(vokey);
|
2011-04-27 10:05:43 +00:00
|
|
|
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;
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProKey ikey(quc.at(comp_in) + ".input");
|
|
|
|
if (v.contains(ikey)) {
|
|
|
|
const ProStringList &inputs = v.value(ikey);
|
2011-04-27 10:05:43 +00:00
|
|
|
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
|
2012-09-06 10:21:38 +00:00
|
|
|
// quc.move(comp_out, comp_in);
|
|
|
|
quc.insert(comp_in, quc.value(comp_out));
|
|
|
|
// comp_out > comp_in, so the insertion did move everything up
|
|
|
|
quc.remove(comp_out + 1);
|
2011-04-27 10:05:43 +00:00
|
|
|
comp_out = comp_in;
|
|
|
|
goto continue_compiler_chain;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!project->isEmpty("QMAKE_SUBSTITUTES")) {
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &subs = v["QMAKE_SUBSTITUTES"];
|
2011-04-27 10:05:43 +00:00
|
|
|
for(int i = 0; i < subs.size(); ++i) {
|
2012-09-06 10:21:38 +00:00
|
|
|
QString sub = subs.at(i).toQString();
|
|
|
|
QString inn = sub + ".input", outn = sub + ".output";
|
|
|
|
const ProKey innkey(inn), outnkey(outn);
|
|
|
|
if (v.contains(innkey) || v.contains(outnkey)) {
|
|
|
|
if (!v.contains(innkey) || !v.contains(outnkey)) {
|
2011-04-27 10:05:43 +00:00
|
|
|
warn_msg(WarnLogic, "Substitute '%s' has only one of .input and .output",
|
2012-09-06 10:21:38 +00:00
|
|
|
sub.toLatin1().constData());
|
2011-04-27 10:05:43 +00:00
|
|
|
continue;
|
|
|
|
}
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &tinn = v[innkey], &toutn = v[outnkey];
|
2011-04-27 10:05:43 +00:00
|
|
|
if (tinn.length() != 1) {
|
|
|
|
warn_msg(WarnLogic, "Substitute '%s.input' does not have exactly one value",
|
2012-09-06 10:21:38 +00:00
|
|
|
sub.toLatin1().constData());
|
2011-04-27 10:05:43 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (toutn.length() != 1) {
|
|
|
|
warn_msg(WarnLogic, "Substitute '%s.output' does not have exactly one value",
|
2012-09-06 10:21:38 +00:00
|
|
|
sub.toLatin1().constData());
|
2011-04-27 10:05:43 +00:00
|
|
|
continue;
|
|
|
|
}
|
2012-09-06 10:21:38 +00:00
|
|
|
inn = fileFixify(tinn.first().toQString(), qmake_getpwd());
|
|
|
|
outn = fileFixify(toutn.first().toQString(), qmake_getpwd(), Option::output_dir);
|
2011-04-27 10:05:43 +00:00
|
|
|
} else {
|
2012-09-06 10:21:38 +00:00
|
|
|
inn = fileFixify(sub, qmake_getpwd());
|
2011-04-27 10:05:43 +00:00
|
|
|
if (!QFile::exists(inn)) {
|
|
|
|
// random insanity for backwards compat: .in file specified with absolute out dir
|
2012-09-06 10:21:38 +00:00
|
|
|
inn = fileFixify(sub);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
if(!inn.endsWith(".in")) {
|
|
|
|
warn_msg(WarnLogic, "Substitute '%s' does not end with '.in'",
|
|
|
|
inn.toLatin1().constData());
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
outn = fileFixify(inn.left(inn.length()-3), qmake_getpwd(), Option::output_dir);
|
|
|
|
}
|
2012-02-11 09:42:03 +00:00
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProKey confign(sub + ".CONFIG");
|
2012-02-11 09:42:03 +00:00
|
|
|
bool verbatim = false;
|
|
|
|
if (v.contains(confign))
|
|
|
|
verbatim = v[confign].contains(QLatin1String("verbatim"));
|
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
QFile in(inn);
|
2012-02-11 09:42:03 +00:00
|
|
|
if (in.open(QFile::ReadOnly)) {
|
|
|
|
QByteArray contentBytes;
|
|
|
|
if (verbatim) {
|
|
|
|
contentBytes = in.readAll();
|
|
|
|
} else {
|
|
|
|
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));
|
2012-08-28 18:53:25 +00:00
|
|
|
if (project->test(test, inn, count))
|
2012-02-11 09:42:03 +00:00
|
|
|
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));
|
2012-08-28 18:53:25 +00:00
|
|
|
if (project->test(test, inn, count)) {
|
2012-02-11 09:42:03 +00:00
|
|
|
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) {
|
2011-04-27 10:05:43 +00:00
|
|
|
state.pop();
|
|
|
|
state.push(IN_CONDITION);
|
2012-02-11 09:42:03 +00:00
|
|
|
} else if (state.top() == IN_CONDITION) {
|
|
|
|
state.pop();
|
|
|
|
state.push(MET_CONDITION);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
2012-02-11 09:42:03 +00:00
|
|
|
} 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, in.fileName(), count);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
2012-02-11 09:42:03 +00:00
|
|
|
contentBytes = contents.toUtf8();
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
QFile out(outn);
|
2012-02-11 09:42:03 +00:00
|
|
|
if (out.exists() && out.open(QFile::ReadOnly)) {
|
|
|
|
QByteArray old = out.readAll();
|
|
|
|
if (contentBytes == old) {
|
2011-04-27 10:05:43 +00:00
|
|
|
v["QMAKE_INTERNAL_INCLUDED_FILES"].append(in.fileName());
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
out.close();
|
|
|
|
if(!out.remove()) {
|
|
|
|
warn_msg(WarnLogic, "Cannot clear substitute '%s'",
|
|
|
|
out.fileName().toLatin1().constData());
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mkdir(QFileInfo(out).absolutePath());
|
|
|
|
if(out.open(QFile::WriteOnly)) {
|
|
|
|
v["QMAKE_INTERNAL_INCLUDED_FILES"].append(in.fileName());
|
2012-02-11 09:42:03 +00:00
|
|
|
out.write(contentBytes);
|
2011-04-27 10:05:43 +00:00
|
|
|
} 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", "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);
|
|
|
|
}
|
2012-09-06 10:21:38 +00:00
|
|
|
for (ProStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) {
|
|
|
|
const ProStringList &inputs = v[ProKey(*it + ".input")];
|
2011-04-27 10:05:43 +00:00
|
|
|
for(x = 0; x < inputs.size(); ++x) {
|
|
|
|
Compiler compiler;
|
2012-09-06 10:21:38 +00:00
|
|
|
compiler.variable_in = inputs.at(x).toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
compiler.flags = Compiler::CompilerNoFlags;
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &config = v[ProKey(*it + ".CONFIG")];
|
|
|
|
if (config.indexOf("ignore_no_exist") != -1)
|
2011-04-27 10:05:43 +00:00
|
|
|
compiler.flags |= Compiler::CompilerRemoveNoExist;
|
2012-09-06 10:21:38 +00:00
|
|
|
if (config.indexOf("no_dependencies") != -1)
|
2011-04-27 10:05:43 +00:00
|
|
|
compiler.flags |= Compiler::CompilerNoCheckDeps;
|
2012-09-06 10:21:38 +00:00
|
|
|
if (config.indexOf("add_inputs_as_makefile_deps") != -1)
|
qmake: Allow extra compilers to have the makefile depend on its inputs
And enable this configuration option for the resource compiler. This
results in a re-run of qmake whenever you touch a qrc file, which is
needed to keep the dependencies up to date. Otherwise you might end
up in the situation where you add a file to a qrc, edit the file some
time later, but a rebuild does not regenerate a cpp file and compile
that, so the final binary is stale.
Technically this dependency problem is present for all source files,
and qrc files are no different than any cpp file that you add a new
header #include to, or adding a Q_OBJECT macro to a header. To pick
up these changes we have to re-run qmake, so that qmake can run its
internal dependency checking, and any extra compiler dependency
commands.
The reason we're making this change for rcc files it that conceptually
people treat them as a "project" files, and expect them to behave similarly
to .pro or .pri files, in that editing the file will invalidate the
makefile. In practice this is often what happens when adding new
headers, as you touch the project file when changing the HEADERS
variable.
Task-number: QTBUG-13334
Change-Id: If69149678e7fba6d812d31dcc17877427f9a6122
Reviewed-by: Simon Hausmann <simon.hausmann@nokia.com>
Reviewed-by: Kai Koehne <kai.koehne@nokia.com>
2011-11-24 15:03:19 +00:00
|
|
|
compiler.flags |= Compiler::CompilerAddInputsAsMakefileDeps;
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProKey dkey(*it + ".dependency_type");
|
|
|
|
ProString dep_type;
|
|
|
|
if (!project->isEmpty(dkey))
|
|
|
|
dep_type = project->first(dkey);
|
2011-04-27 10:05:43 +00:00
|
|
|
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
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList paths;
|
2011-04-27 10:05:43 +00:00
|
|
|
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++) {
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList &l = v[paths[y].toKey()];
|
|
|
|
for (ProStringList::Iterator it = l.begin(); it != l.end(); ++it) {
|
2011-04-27 10:05:43 +00:00
|
|
|
if((*it).isEmpty())
|
|
|
|
continue;
|
2012-09-06 10:21:38 +00:00
|
|
|
QString fn = (*it).toQString();
|
|
|
|
if (exists(fn))
|
|
|
|
(*it) = fileFixify(fn);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-23 14:41:08 +00:00
|
|
|
if(noIO() || !doDepends() || project->isActiveConfig("GNUmake"))
|
2011-04-27 10:05:43 +00:00
|
|
|
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
|
|
|
|
//files are already properly fixified.
|
2012-09-06 10:21:38 +00:00
|
|
|
for (ProStringList::Iterator it = quc.begin(); it != quc.end(); ++it) {
|
|
|
|
const ProKey ikey(*it + ".input");
|
|
|
|
const ProKey vokey(*it + ".variable_out");
|
|
|
|
const ProStringList &config = project->values(ProKey(*it + ".CONFIG"));
|
|
|
|
const ProString &tmp_out = project->values(ProKey(*it + ".output")).first();
|
2011-04-27 10:05:43 +00:00
|
|
|
if(tmp_out.isEmpty())
|
|
|
|
continue;
|
2012-09-06 10:21:38 +00:00
|
|
|
if (config.indexOf("combine") != -1) {
|
|
|
|
const ProStringList &compilerInputs = project->values(ikey);
|
2011-04-27 10:05:43 +00:00
|
|
|
// Don't generate compiler output if it doesn't have input.
|
2012-09-06 10:21:38 +00:00
|
|
|
if (compilerInputs.isEmpty() || project->values(compilerInputs.first().toKey()).isEmpty())
|
2011-04-27 10:05:43 +00:00
|
|
|
continue;
|
|
|
|
if(tmp_out.indexOf("$") == -1) {
|
|
|
|
if(!verifyExtraCompiler((*it), QString())) //verify
|
|
|
|
continue;
|
2012-09-06 10:21:38 +00:00
|
|
|
QString out = fileFixify(tmp_out.toQString(), Option::output_dir, Option::output_dir);
|
|
|
|
bool pre_dep = (config.indexOf("target_predeps") != -1);
|
|
|
|
if (v.contains(vokey)) {
|
|
|
|
const ProStringList &var_out = v.value(vokey);
|
2011-04-27 10:05:43 +00:00
|
|
|
for(int i = 0; i < var_out.size(); ++i) {
|
2012-09-06 10:21:38 +00:00
|
|
|
ProKey v = var_out.at(i).toKey();
|
2011-04-27 10:05:43 +00:00
|
|
|
if(v == QLatin1String("SOURCES"))
|
|
|
|
v = "GENERATED_SOURCES";
|
|
|
|
else if(v == QLatin1String("OBJECTS"))
|
|
|
|
pre_dep = false;
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList &list = project->values(v);
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!list.contains(out))
|
|
|
|
list.append(out);
|
|
|
|
}
|
2012-09-06 10:21:38 +00:00
|
|
|
} else if (config.indexOf("no_link") == -1) {
|
|
|
|
ProStringList &list = project->values("OBJECTS");
|
2011-04-27 10:05:43 +00:00
|
|
|
pre_dep = false;
|
|
|
|
if(!list.contains(out))
|
|
|
|
list.append(out);
|
|
|
|
} else {
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList &list = project->values("UNUSED_SOURCES");
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!list.contains(out))
|
|
|
|
list.append(out);
|
|
|
|
}
|
|
|
|
if(pre_dep) {
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList &list = project->values("PRE_TARGETDEPS");
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!list.contains(out))
|
|
|
|
list.append(out);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &tmp = project->values(ikey);
|
|
|
|
for (ProStringList::ConstIterator it2 = tmp.begin(); it2 != tmp.end(); ++it2) {
|
|
|
|
const ProStringList &inputs = project->values((*it2).toKey());
|
|
|
|
for (ProStringList::ConstIterator input = inputs.constBegin(); input != inputs.constEnd(); ++input) {
|
2011-04-27 10:05:43 +00:00
|
|
|
if((*input).isEmpty())
|
|
|
|
continue;
|
2012-09-06 10:21:38 +00:00
|
|
|
QString inpf = (*input).toQString();
|
|
|
|
QString in = Option::fixPathToTargetOS(inpf, false);
|
|
|
|
if (!verifyExtraCompiler((*it).toQString(), in)) //verify
|
2011-04-27 10:05:43 +00:00
|
|
|
continue;
|
2012-09-06 10:21:38 +00:00
|
|
|
QString out = replaceExtraCompilerVariables(tmp_out.toQString(), inpf, QString());
|
2011-04-27 10:05:43 +00:00
|
|
|
out = fileFixify(out, Option::output_dir, Option::output_dir);
|
2012-09-06 10:21:38 +00:00
|
|
|
bool pre_dep = (config.indexOf("target_predeps") != -1);
|
|
|
|
if (v.contains(vokey)) {
|
|
|
|
const ProStringList &var_out = project->values(vokey);
|
2011-04-27 10:05:43 +00:00
|
|
|
for(int i = 0; i < var_out.size(); ++i) {
|
2012-09-06 10:21:38 +00:00
|
|
|
ProKey v = var_out.at(i).toKey();
|
2011-04-27 10:05:43 +00:00
|
|
|
if(v == QLatin1String("SOURCES"))
|
|
|
|
v = "GENERATED_SOURCES";
|
|
|
|
else if(v == QLatin1String("OBJECTS"))
|
|
|
|
pre_dep = false;
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList &list = project->values(v);
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!list.contains(out))
|
|
|
|
list.append(out);
|
|
|
|
}
|
2012-09-06 10:21:38 +00:00
|
|
|
} else if (config.indexOf("no_link") == -1) {
|
2011-04-27 10:05:43 +00:00
|
|
|
pre_dep = false;
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList &list = project->values("OBJECTS");
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!list.contains(out))
|
|
|
|
list.append(out);
|
|
|
|
} else {
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList &list = project->values("UNUSED_SOURCES");
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!list.contains(out))
|
|
|
|
list.append(out);
|
|
|
|
}
|
|
|
|
if(pre_dep) {
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList &list = project->values("PRE_TARGETDEPS");
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!list.contains(out))
|
|
|
|
list.append(out);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//handle dependencies
|
|
|
|
depHeuristicsCache.clear();
|
|
|
|
if(!noIO()) {
|
|
|
|
// dependency paths
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList incDirs = v["DEPENDPATH"] + v["QMAKE_ABSOLUTE_SOURCE_PATH"];
|
2011-04-27 10:05:43 +00:00
|
|
|
if(project->isActiveConfig("depend_includepath"))
|
|
|
|
incDirs += v["INCLUDEPATH"];
|
|
|
|
if(!project->isActiveConfig("no_include_pwd")) {
|
|
|
|
QString pwd = qmake_getpwd();
|
|
|
|
if(pwd.isEmpty())
|
|
|
|
pwd = ".";
|
|
|
|
incDirs += pwd;
|
|
|
|
}
|
|
|
|
QList<QMakeLocalFileName> deplist;
|
2012-09-06 10:21:38 +00:00
|
|
|
for (ProStringList::Iterator it = incDirs.begin(); it != incDirs.end(); ++it)
|
|
|
|
deplist.append(QMakeLocalFileName(unescapeFilePath((*it).toQString())));
|
2011-04-27 10:05:43 +00:00
|
|
|
QMakeSourceFileInfo::setDependencyPaths(deplist);
|
|
|
|
debug_msg(1, "Dependency Directories: %s", incDirs.join(" :: ").toLatin1().constData());
|
|
|
|
//cache info
|
|
|
|
if(project->isActiveConfig("qmake_cache")) {
|
|
|
|
QString cache_file;
|
|
|
|
if(!project->isEmpty("QMAKE_INTERNAL_CACHE_FILE")) {
|
2012-09-06 10:21:38 +00:00
|
|
|
cache_file = QDir::fromNativeSeparators(project->first("QMAKE_INTERNAL_CACHE_FILE").toQString());
|
2011-04-27 10:05:43 +00:00
|
|
|
} else {
|
|
|
|
cache_file = ".qmake.internal.cache";
|
|
|
|
if(project->isActiveConfig("build_pass"))
|
|
|
|
cache_file += ".BUILD." + project->first("BUILD_PASS");
|
|
|
|
}
|
|
|
|
if(cache_file.indexOf('/') == -1)
|
|
|
|
cache_file.prepend(Option::output_dir + '/');
|
|
|
|
QMakeSourceFileInfo::setCacheFile(cache_file);
|
|
|
|
}
|
|
|
|
|
|
|
|
//add to dependency engine
|
|
|
|
for(x = 0; x < compilers.count(); ++x) {
|
|
|
|
const MakefileGenerator::Compiler &comp = compilers.at(x);
|
qmake: Allow extra compilers to have the makefile depend on its inputs
And enable this configuration option for the resource compiler. This
results in a re-run of qmake whenever you touch a qrc file, which is
needed to keep the dependencies up to date. Otherwise you might end
up in the situation where you add a file to a qrc, edit the file some
time later, but a rebuild does not regenerate a cpp file and compile
that, so the final binary is stale.
Technically this dependency problem is present for all source files,
and qrc files are no different than any cpp file that you add a new
header #include to, or adding a Q_OBJECT macro to a header. To pick
up these changes we have to re-run qmake, so that qmake can run its
internal dependency checking, and any extra compiler dependency
commands.
The reason we're making this change for rcc files it that conceptually
people treat them as a "project" files, and expect them to behave similarly
to .pro or .pri files, in that editing the file will invalidate the
makefile. In practice this is often what happens when adding new
headers, as you touch the project file when changing the HEADERS
variable.
Task-number: QTBUG-13334
Change-Id: If69149678e7fba6d812d31dcc17877427f9a6122
Reviewed-by: Simon Hausmann <simon.hausmann@nokia.com>
Reviewed-by: Kai Koehne <kai.koehne@nokia.com>
2011-11-24 15:03:19 +00:00
|
|
|
if(!(comp.flags & Compiler::CompilerNoCheckDeps)) {
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProKey ikey(comp.variable_in);
|
|
|
|
addSourceFiles(v[ikey], QMakeSourceFileInfo::SEEK_DEPS,
|
2011-04-27 10:05:43 +00:00
|
|
|
(QMakeSourceFileInfo::SourceFileType)comp.type);
|
qmake: Allow extra compilers to have the makefile depend on its inputs
And enable this configuration option for the resource compiler. This
results in a re-run of qmake whenever you touch a qrc file, which is
needed to keep the dependencies up to date. Otherwise you might end
up in the situation where you add a file to a qrc, edit the file some
time later, but a rebuild does not regenerate a cpp file and compile
that, so the final binary is stale.
Technically this dependency problem is present for all source files,
and qrc files are no different than any cpp file that you add a new
header #include to, or adding a Q_OBJECT macro to a header. To pick
up these changes we have to re-run qmake, so that qmake can run its
internal dependency checking, and any extra compiler dependency
commands.
The reason we're making this change for rcc files it that conceptually
people treat them as a "project" files, and expect them to behave similarly
to .pro or .pri files, in that editing the file will invalidate the
makefile. In practice this is often what happens when adding new
headers, as you touch the project file when changing the HEADERS
variable.
Task-number: QTBUG-13334
Change-Id: If69149678e7fba6d812d31dcc17877427f9a6122
Reviewed-by: Simon Hausmann <simon.hausmann@nokia.com>
Reviewed-by: Kai Koehne <kai.koehne@nokia.com>
2011-11-24 15:03:19 +00:00
|
|
|
|
|
|
|
if (comp.flags & Compiler::CompilerAddInputsAsMakefileDeps) {
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList &l = v[ikey];
|
qmake: Allow extra compilers to have the makefile depend on its inputs
And enable this configuration option for the resource compiler. This
results in a re-run of qmake whenever you touch a qrc file, which is
needed to keep the dependencies up to date. Otherwise you might end
up in the situation where you add a file to a qrc, edit the file some
time later, but a rebuild does not regenerate a cpp file and compile
that, so the final binary is stale.
Technically this dependency problem is present for all source files,
and qrc files are no different than any cpp file that you add a new
header #include to, or adding a Q_OBJECT macro to a header. To pick
up these changes we have to re-run qmake, so that qmake can run its
internal dependency checking, and any extra compiler dependency
commands.
The reason we're making this change for rcc files it that conceptually
people treat them as a "project" files, and expect them to behave similarly
to .pro or .pri files, in that editing the file will invalidate the
makefile. In practice this is often what happens when adding new
headers, as you touch the project file when changing the HEADERS
variable.
Task-number: QTBUG-13334
Change-Id: If69149678e7fba6d812d31dcc17877427f9a6122
Reviewed-by: Simon Hausmann <simon.hausmann@nokia.com>
Reviewed-by: Kai Koehne <kai.koehne@nokia.com>
2011-11-24 15:03:19 +00:00
|
|
|
for (int i=0; i < l.size(); ++i) {
|
|
|
|
if(v["QMAKE_INTERNAL_INCLUDED_FILES"].indexOf(l.at(i)) == -1)
|
|
|
|
v["QMAKE_INTERNAL_INCLUDED_FILES"].append(l.at(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
processSources(); //remove anything in SOURCES which is included (thus it need not be linked in)
|
|
|
|
|
|
|
|
//all sources and generated sources must be turned into objects at some point (the one builtin compiler)
|
|
|
|
v["OBJECTS"] += createObjectList(v["SOURCES"]) + createObjectList(v["GENERATED_SOURCES"]);
|
|
|
|
|
|
|
|
//Translation files
|
|
|
|
if(!project->isEmpty("TRANSLATIONS")) {
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList &trf = project->values("TRANSLATIONS");
|
|
|
|
for (ProStringList::Iterator it = trf.begin(); it != trf.end(); ++it)
|
|
|
|
(*it) = Option::fixPathToLocalOS((*it).toQString());
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2011-08-12 19:19:26 +00:00
|
|
|
if(!project->isActiveConfig("no_include_pwd")) { //get the output_dir into the pwd
|
2011-04-27 10:05:43 +00:00
|
|
|
if(Option::output_dir != qmake_getpwd())
|
|
|
|
project->values("INCLUDEPATH").append(".");
|
|
|
|
}
|
|
|
|
|
|
|
|
//fix up the target deps
|
2012-08-20 11:04:39 +00:00
|
|
|
static const char * const fixpaths[] = { "PRE_TARGETDEPS", "POST_TARGETDEPS", 0 };
|
|
|
|
for (int path = 0; fixpaths[path]; path++) {
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList &l = v[fixpaths[path]];
|
|
|
|
for (ProStringList::Iterator val_it = l.begin(); val_it != l.end(); ++val_it) {
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!(*val_it).isEmpty())
|
2012-09-06 10:21:38 +00:00
|
|
|
(*val_it) = escapeDependencyPath(Option::fixPathToTargetOS((*val_it).toQString(), false, false));
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//extra depends
|
|
|
|
if(!project->isEmpty("DEPENDS")) {
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList &l = v["DEPENDS"];
|
|
|
|
for (ProStringList::Iterator it = l.begin(); it != l.end(); ++it) {
|
|
|
|
const ProStringList &files = v[ProKey(*it + ".file")] + v[ProKey(*it + ".files")]; //why do I support such evil things?
|
|
|
|
for (ProStringList::ConstIterator file_it = files.begin(); file_it != files.end(); ++file_it) {
|
|
|
|
QStringList &out_deps = findDependencies((*file_it).toQString());
|
|
|
|
const ProStringList &in_deps = v[ProKey(*it + ".depends")]; //even more evilness..
|
|
|
|
for (ProStringList::ConstIterator dep_it = in_deps.begin(); dep_it != in_deps.end(); ++dep_it) {
|
|
|
|
QString dep = (*dep_it).toQString();
|
|
|
|
if (exists(dep)) {
|
|
|
|
out_deps.append(dep);
|
2011-04-27 10:05:43 +00:00
|
|
|
} else {
|
2012-09-06 10:21:38 +00:00
|
|
|
QString dir, regex = Option::fixPathToLocalOS(dep);
|
2011-04-27 10:05:43 +00:00
|
|
|
if(regex.lastIndexOf(Option::dir_sep) != -1) {
|
|
|
|
dir = regex.left(regex.lastIndexOf(Option::dir_sep) + 1);
|
|
|
|
regex.remove(0, dir.length());
|
|
|
|
}
|
|
|
|
QStringList files = QDir(dir).entryList(QStringList(regex));
|
|
|
|
if(files.isEmpty()) {
|
|
|
|
warn_msg(WarnLogic, "Dependency for [%s]: Not found %s", (*file_it).toLatin1().constData(),
|
2012-09-06 10:21:38 +00:00
|
|
|
dep.toLatin1().constData());
|
2011-04-27 10:05:43 +00:00
|
|
|
} else {
|
|
|
|
for(int i = 0; i < files.count(); i++)
|
|
|
|
out_deps.append(dir + files[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// escape qmake command
|
2012-04-23 10:44:40 +00:00
|
|
|
project->values("QMAKE_QMAKE") =
|
2012-09-05 16:29:19 +00:00
|
|
|
ProStringList(escapeFilePath(Option::fixPathToTargetOS(Option::globals->qmake_abslocation, false)));
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
MakefileGenerator::processPrlFile(QString &file)
|
|
|
|
{
|
|
|
|
bool ret = false, try_replace_file=false;
|
|
|
|
QString meta_file, orig_file = file;
|
|
|
|
if(QMakeMetaInfo::libExists(file)) {
|
|
|
|
try_replace_file = true;
|
|
|
|
meta_file = file;
|
|
|
|
file = "";
|
|
|
|
} else {
|
|
|
|
QString tmp = file;
|
|
|
|
int ext = tmp.lastIndexOf('.');
|
|
|
|
if(ext != -1)
|
|
|
|
tmp = tmp.left(ext);
|
|
|
|
meta_file = tmp;
|
|
|
|
}
|
|
|
|
// meta_file = fileFixify(meta_file);
|
|
|
|
QString real_meta_file = Option::fixPathToLocalOS(meta_file);
|
|
|
|
if(!meta_file.isEmpty()) {
|
|
|
|
QString f = fileFixify(real_meta_file, qmake_getpwd(), Option::output_dir);
|
|
|
|
if(QMakeMetaInfo::libExists(f)) {
|
2012-08-22 12:10:35 +00:00
|
|
|
QMakeMetaInfo libinfo(project);
|
2011-04-27 10:05:43 +00:00
|
|
|
debug_msg(1, "Processing PRL file: %s", real_meta_file.toLatin1().constData());
|
|
|
|
if(!libinfo.readLib(f)) {
|
|
|
|
fprintf(stderr, "Error processing meta file: %s\n", real_meta_file.toLatin1().constData());
|
|
|
|
} else if(project->isActiveConfig("no_read_prl_" + libinfo.type().toLower())) {
|
|
|
|
debug_msg(2, "Ignored meta file %s [%s]", real_meta_file.toLatin1().constData(), libinfo.type().toLatin1().constData());
|
|
|
|
} else {
|
|
|
|
ret = true;
|
2012-07-20 13:31:14 +00:00
|
|
|
project->values("QMAKE_CURRENT_PRL_LIBS") = libinfo.values("QMAKE_PRL_LIBS");
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList &defs = project->values("DEFINES");
|
|
|
|
const ProStringList &prl_defs = project->values("PRL_EXPORT_DEFINES");
|
|
|
|
foreach (const ProString &def, libinfo.values("QMAKE_PRL_DEFINES"))
|
2012-07-20 13:31:14 +00:00
|
|
|
if (!defs.contains(def) && prl_defs.contains(def))
|
|
|
|
defs.append(def);
|
2011-04-27 10:05:43 +00:00
|
|
|
if(try_replace_file && !libinfo.isEmpty("QMAKE_PRL_TARGET")) {
|
|
|
|
QString dir;
|
|
|
|
int slsh = real_meta_file.lastIndexOf(Option::dir_sep);
|
|
|
|
if(slsh != -1)
|
|
|
|
dir = real_meta_file.left(slsh+1);
|
2012-09-06 10:21:38 +00:00
|
|
|
file = libinfo.first("QMAKE_PRL_TARGET").toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
if(QDir::isRelativePath(file))
|
|
|
|
file.prepend(dir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(ret) {
|
|
|
|
QString mf = QMakeMetaInfo::findLib(meta_file);
|
|
|
|
if(project->values("QMAKE_PRL_INTERNAL_FILES").indexOf(mf) == -1)
|
|
|
|
project->values("QMAKE_PRL_INTERNAL_FILES").append(mf);
|
|
|
|
if(project->values("QMAKE_INTERNAL_INCLUDED_FILES").indexOf(mf) == -1)
|
|
|
|
project->values("QMAKE_INTERNAL_INCLUDED_FILES").append(mf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(try_replace_file && file.isEmpty()) {
|
|
|
|
#if 0
|
|
|
|
warn_msg(WarnLogic, "Found prl [%s] file with no target [%s]!", meta_file.toLatin1().constData(),
|
|
|
|
orig_file.toLatin1().constData());
|
|
|
|
#endif
|
|
|
|
file = orig_file;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-08-20 11:04:39 +00:00
|
|
|
MakefileGenerator::filterIncludedFiles(const char *var)
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList &inputs = project->values(var);
|
|
|
|
for (ProStringList::Iterator input = inputs.begin(); input != inputs.end(); ) {
|
|
|
|
if (QMakeSourceFileInfo::included((*input).toQString()) > 0)
|
2011-04-27 10:05:43 +00:00
|
|
|
input = inputs.erase(input);
|
|
|
|
else
|
|
|
|
++input;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
MakefileGenerator::processPrlFiles()
|
|
|
|
{
|
2012-07-20 10:29:21 +00:00
|
|
|
qFatal("MakefileGenerator::processPrlFiles() called!");
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
MakefileGenerator::writePrlFile(QTextStream &t)
|
|
|
|
{
|
2012-09-06 10:21:38 +00:00
|
|
|
ProString target = project->first("TARGET");
|
2011-04-27 10:05:43 +00:00
|
|
|
int slsh = target.lastIndexOf(Option::dir_sep);
|
|
|
|
if(slsh != -1)
|
2012-09-06 10:21:38 +00:00
|
|
|
target.chopFront(slsh + 1);
|
2011-04-27 10:05:43 +00:00
|
|
|
QString bdir = Option::output_dir;
|
|
|
|
if(bdir.isEmpty())
|
|
|
|
bdir = qmake_getpwd();
|
|
|
|
t << "QMAKE_PRL_BUILD_DIR = " << bdir << endl;
|
|
|
|
|
2012-08-28 08:12:36 +00:00
|
|
|
t << "QMAKE_PRO_INPUT = " << project->projectFile().section('/', -1) << endl;
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
if(!project->isEmpty("QMAKE_ABSOLUTE_SOURCE_PATH"))
|
|
|
|
t << "QMAKE_PRL_SOURCE_DIR = " << project->first("QMAKE_ABSOLUTE_SOURCE_PATH") << endl;
|
|
|
|
t << "QMAKE_PRL_TARGET = " << target << endl;
|
|
|
|
if(!project->isEmpty("PRL_EXPORT_DEFINES"))
|
2012-05-18 18:00:23 +00:00
|
|
|
t << "QMAKE_PRL_DEFINES = " << project->values("PRL_EXPORT_DEFINES").join(' ') << endl;
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!project->isEmpty("PRL_EXPORT_CFLAGS"))
|
2012-05-18 18:00:23 +00:00
|
|
|
t << "QMAKE_PRL_CFLAGS = " << project->values("PRL_EXPORT_CFLAGS").join(' ') << endl;
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!project->isEmpty("PRL_EXPORT_CXXFLAGS"))
|
2012-05-18 18:00:23 +00:00
|
|
|
t << "QMAKE_PRL_CXXFLAGS = " << project->values("PRL_EXPORT_CXXFLAGS").join(' ') << endl;
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!project->isEmpty("CONFIG"))
|
2012-05-18 18:00:23 +00:00
|
|
|
t << "QMAKE_PRL_CONFIG = " << project->values("CONFIG").join(' ') << endl;
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!project->isEmpty("TARGET_VERSION_EXT"))
|
|
|
|
t << "QMAKE_PRL_VERSION = " << project->first("TARGET_VERSION_EXT") << endl;
|
|
|
|
else if(!project->isEmpty("VERSION"))
|
|
|
|
t << "QMAKE_PRL_VERSION = " << project->first("VERSION") << endl;
|
|
|
|
if(project->isActiveConfig("staticlib") || project->isActiveConfig("explicitlib")) {
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList libs;
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS"))
|
|
|
|
libs = project->values("QMAKE_INTERNAL_PRL_LIBS");
|
|
|
|
else
|
|
|
|
libs << "QMAKE_LIBS"; //obvious one
|
|
|
|
if(project->isActiveConfig("staticlib"))
|
|
|
|
libs << "QMAKE_LIBS_PRIVATE";
|
|
|
|
t << "QMAKE_PRL_LIBS = ";
|
2012-09-06 10:21:38 +00:00
|
|
|
for (ProStringList::Iterator it = libs.begin(); it != libs.end(); ++it)
|
2012-05-18 18:00:23 +00:00
|
|
|
t << project->values((*it).toKey()).join(' ').replace('\\', "\\\\") << " ";
|
2011-04-27 10:05:43 +00:00
|
|
|
t << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
MakefileGenerator::writeProjectMakefile()
|
|
|
|
{
|
|
|
|
QTextStream t(&Option::output);
|
|
|
|
|
|
|
|
//header
|
|
|
|
writeHeader(t);
|
|
|
|
|
|
|
|
QList<SubTarget*> targets;
|
|
|
|
{
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList builds = project->values("BUILDS");
|
|
|
|
for (ProStringList::Iterator it = builds.begin(); it != builds.end(); ++it) {
|
2011-04-27 10:05:43 +00:00
|
|
|
SubTarget *st = new SubTarget;
|
|
|
|
targets.append(st);
|
|
|
|
st->makefile = "$(MAKEFILE)." + (*it);
|
2012-09-06 10:21:38 +00:00
|
|
|
st->name = (*it).toQString();
|
|
|
|
const ProKey tkey(*it + ".target");
|
|
|
|
st->target = (project->isEmpty(tkey) ? (*it) : project->first(tkey)).toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if(project->isActiveConfig("build_all")) {
|
2013-07-04 09:25:16 +00:00
|
|
|
t << "first: all\n";
|
2011-04-27 10:05:43 +00:00
|
|
|
QList<SubTarget*>::Iterator it;
|
|
|
|
|
|
|
|
//install
|
|
|
|
t << "install: ";
|
|
|
|
for(it = targets.begin(); it != targets.end(); ++it)
|
|
|
|
t << (*it)->target << "-install ";
|
|
|
|
t << endl;
|
|
|
|
|
|
|
|
//uninstall
|
|
|
|
t << "uninstall: ";
|
|
|
|
for(it = targets.begin(); it != targets.end(); ++it)
|
|
|
|
t << (*it)->target << "-uninstall ";
|
|
|
|
t << endl;
|
|
|
|
} else {
|
|
|
|
t << "first: " << targets.first()->target << endl
|
2013-07-04 09:25:16 +00:00
|
|
|
<< "install: " << targets.first()->target << "-install\n"
|
|
|
|
<< "uninstall: " << targets.first()->target << "-uninstall\n";
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
writeSubTargets(t, targets, SubTargetsNoFlags);
|
|
|
|
if(!project->isActiveConfig("no_autoqmake")) {
|
|
|
|
for(QList<SubTarget*>::Iterator it = targets.begin(); it != targets.end(); ++it)
|
|
|
|
t << (*it)->makefile << ": " <<
|
|
|
|
Option::fixPathToTargetOS(fileFixify(Option::output.fileName())) << endl;
|
|
|
|
}
|
|
|
|
qDeleteAll(targets);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
MakefileGenerator::write()
|
|
|
|
{
|
|
|
|
if(!project)
|
|
|
|
return false;
|
|
|
|
writePrlFile();
|
|
|
|
if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE || //write makefile
|
|
|
|
Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) {
|
|
|
|
QTextStream t(&Option::output);
|
|
|
|
if(!writeMakefile(t)) {
|
|
|
|
#if 1
|
|
|
|
warn_msg(WarnLogic, "Unable to generate output for: %s [TEMPLATE %s]",
|
|
|
|
Option::output.fileName().toLatin1().constData(),
|
|
|
|
project->first("TEMPLATE").toLatin1().constData());
|
|
|
|
if(Option::output.exists())
|
|
|
|
Option::output.remove();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString
|
|
|
|
MakefileGenerator::prlFileName(bool fixify)
|
|
|
|
{
|
2012-09-06 10:21:38 +00:00
|
|
|
QString ret = project->first("TARGET_PRL").toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
if(ret.isEmpty())
|
2012-09-06 10:21:38 +00:00
|
|
|
ret = project->first("TARGET").toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
int slsh = ret.lastIndexOf(Option::dir_sep);
|
|
|
|
if(slsh != -1)
|
|
|
|
ret.remove(0, slsh);
|
|
|
|
if(!ret.endsWith(Option::prl_ext)) {
|
|
|
|
int dot = ret.indexOf('.');
|
|
|
|
if(dot != -1)
|
|
|
|
ret.truncate(dot);
|
|
|
|
ret += Option::prl_ext;
|
|
|
|
}
|
|
|
|
if(!project->isEmpty("QMAKE_BUNDLE"))
|
|
|
|
ret.prepend(project->first("QMAKE_BUNDLE") + Option::dir_sep);
|
|
|
|
if(fixify) {
|
|
|
|
if(!project->isEmpty("DESTDIR"))
|
2012-09-06 10:21:38 +00:00
|
|
|
ret.prepend(project->first("DESTDIR").toQString());
|
2011-04-27 10:05:43 +00:00
|
|
|
ret = Option::fixPathToLocalOS(fileFixify(ret, qmake_getpwd(), Option::output_dir));
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
MakefileGenerator::writePrlFile()
|
|
|
|
{
|
|
|
|
if((Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
|
|
|
|
Option::qmake_mode == Option::QMAKE_GENERATE_PRL)
|
|
|
|
&& project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty()
|
|
|
|
&& project->isActiveConfig("create_prl")
|
|
|
|
&& (project->first("TEMPLATE") == "lib"
|
|
|
|
|| project->first("TEMPLATE") == "vclib")
|
2011-04-20 17:47:49 +00:00
|
|
|
&& (!project->isActiveConfig("plugin") || project->isActiveConfig("static"))) { //write prl file
|
2011-04-27 10:05:43 +00:00
|
|
|
QString local_prl = prlFileName();
|
|
|
|
QString prl = fileFixify(local_prl);
|
|
|
|
mkdir(fileInfo(local_prl).path());
|
|
|
|
QFile ft(local_prl);
|
|
|
|
if(ft.open(QIODevice::WriteOnly)) {
|
|
|
|
project->values("ALL_DEPS").append(prl);
|
|
|
|
project->values("QMAKE_INTERNAL_PRL_FILE").append(prl);
|
|
|
|
QTextStream t(&ft);
|
|
|
|
writePrlFile(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-08-20 11:04:39 +00:00
|
|
|
MakefileGenerator::writeObj(QTextStream &t, const char *src)
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &srcl = project->values(src);
|
|
|
|
const ProStringList objl = createObjectList(srcl);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList::ConstIterator oit = objl.begin();
|
|
|
|
ProStringList::ConstIterator sit = srcl.begin();
|
2011-04-27 10:05:43 +00:00
|
|
|
QString stringSrc("$src");
|
|
|
|
QString stringObj("$obj");
|
|
|
|
for(;sit != srcl.end() && oit != objl.end(); ++oit, ++sit) {
|
|
|
|
if((*sit).isEmpty())
|
|
|
|
continue;
|
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
QString srcf = (*sit).toQString();
|
|
|
|
QString dstf = (*oit).toQString();
|
|
|
|
t << escapeDependencyPath(dstf) << ": " << escapeDependencyPath(srcf)
|
|
|
|
<< " " << escapeDependencyPaths(findDependencies(srcf)).join(" \\\n\t\t");
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
ProKey comp, cimp;
|
2011-04-27 10:05:43 +00:00
|
|
|
for(QStringList::Iterator cppit = Option::cpp_ext.begin(); cppit != Option::cpp_ext.end(); ++cppit) {
|
|
|
|
if((*sit).endsWith((*cppit))) {
|
|
|
|
comp = "QMAKE_RUN_CXX";
|
|
|
|
cimp = "QMAKE_RUN_CXX_IMP";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(comp.isEmpty()) {
|
|
|
|
comp = "QMAKE_RUN_CC";
|
|
|
|
cimp = "QMAKE_RUN_CC_IMP";
|
|
|
|
}
|
|
|
|
bool use_implicit_rule = !project->isEmpty(cimp);
|
|
|
|
use_implicit_rule = false;
|
|
|
|
if(use_implicit_rule) {
|
|
|
|
if(!project->isEmpty("OBJECTS_DIR")) {
|
|
|
|
use_implicit_rule = false;
|
|
|
|
} else {
|
|
|
|
int dot = (*sit).lastIndexOf('.');
|
|
|
|
if(dot == -1 || ((*sit).left(dot) + Option::obj_ext != (*oit)))
|
|
|
|
use_implicit_rule = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!use_implicit_rule && !project->isEmpty(comp)) {
|
2012-09-06 10:21:38 +00:00
|
|
|
QString p = var(comp);
|
2011-04-27 10:05:43 +00:00
|
|
|
p.replace(stringSrc, escapeFilePath(srcf));
|
2012-09-06 10:21:38 +00:00
|
|
|
p.replace(stringObj, escapeFilePath(dstf));
|
2011-04-27 10:05:43 +00:00
|
|
|
t << "\n\t" << p;
|
|
|
|
}
|
|
|
|
t << endl << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QString
|
|
|
|
MakefileGenerator::filePrefixRoot(const QString &root, const QString &path)
|
|
|
|
{
|
|
|
|
QString ret(root + path);
|
|
|
|
if(path.length() > 2 && path[1] == ':') //c:\foo
|
|
|
|
ret = QString(path.mid(0, 2) + root + path.mid(2));
|
|
|
|
while(ret.endsWith("\\"))
|
|
|
|
ret = ret.left(ret.length()-1);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-09-06 10:21:38 +00:00
|
|
|
MakefileGenerator::writeInstalls(QTextStream &t, bool noBuild)
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
|
|
|
QString rm_dir_contents("-$(DEL_FILE)");
|
|
|
|
if (!isWindowsShell()) //ick
|
|
|
|
rm_dir_contents = "-$(DEL_FILE) -r";
|
|
|
|
|
|
|
|
QString all_installs, all_uninstalls;
|
2012-08-07 15:25:00 +00:00
|
|
|
QSet<QString> made_dirs, removed_dirs;
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &l = project->values("INSTALLS");
|
|
|
|
for (ProStringList::ConstIterator it = l.begin(); it != l.end(); ++it) {
|
|
|
|
const ProKey pvar(*it + ".path");
|
|
|
|
const ProStringList &installConfigValues = project->values(ProKey(*it + ".CONFIG"));
|
|
|
|
if (installConfigValues.indexOf("no_path") == -1 &&
|
|
|
|
installConfigValues.indexOf("dummy_install") == -1 &&
|
2011-04-27 10:05:43 +00:00
|
|
|
project->values(pvar).isEmpty()) {
|
|
|
|
warn_msg(WarnLogic, "%s is not defined: install target not created\n", pvar.toLatin1().constData());
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool do_default = true;
|
|
|
|
const QString root = "$(INSTALL_ROOT)";
|
2012-08-07 15:14:39 +00:00
|
|
|
QString dst;
|
2012-09-06 10:21:38 +00:00
|
|
|
if (installConfigValues.indexOf("no_path") == -1 &&
|
|
|
|
installConfigValues.indexOf("dummy_install") == -1) {
|
|
|
|
dst = fileFixify(unescapeFilePath(project->first(pvar).toQString()), FileFixifyAbsolute, false);
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!dst.endsWith(Option::dir_sep))
|
|
|
|
dst += Option::dir_sep;
|
|
|
|
}
|
|
|
|
|
2012-08-07 15:14:39 +00:00
|
|
|
QStringList tmp, inst, uninst;
|
2011-04-27 10:05:43 +00:00
|
|
|
//other
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList tmp2 = project->values(ProKey(*it + ".extra"));
|
|
|
|
if (tmp2.isEmpty())
|
|
|
|
tmp2 = project->values(ProKey(*it + ".commands")); //to allow compatible name
|
|
|
|
if (!tmp2.isEmpty()) {
|
2011-04-27 10:05:43 +00:00
|
|
|
do_default = false;
|
2012-05-18 18:00:23 +00:00
|
|
|
inst << tmp2.join(' ');
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
//masks
|
2012-09-06 10:21:38 +00:00
|
|
|
tmp2 = findFilesInVPATH(project->values(ProKey(*it + ".files")), VPATH_NoFixify);
|
|
|
|
tmp = fileFixify(tmp2.toQStringList(), FileFixifyAbsolute);
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!tmp.isEmpty()) {
|
|
|
|
do_default = false;
|
2012-09-06 10:21:38 +00:00
|
|
|
QString base_path = project->first(ProKey(*it + ".base")).toQString();
|
2012-08-07 15:25:00 +00:00
|
|
|
if (!base_path.isEmpty()) {
|
|
|
|
base_path = Option::fixPathToTargetOS(base_path, false, true);
|
|
|
|
if (!base_path.endsWith(Option::dir_sep))
|
|
|
|
base_path += Option::dir_sep;
|
|
|
|
}
|
2011-04-27 10:05:43 +00:00
|
|
|
for(QStringList::Iterator wild_it = tmp.begin(); wild_it != tmp.end(); ++wild_it) {
|
|
|
|
QString wild = Option::fixPathToTargetOS((*wild_it), false, false);
|
|
|
|
QString dirstr = qmake_getpwd(), filestr = wild;
|
|
|
|
int slsh = filestr.lastIndexOf(Option::dir_sep);
|
|
|
|
if(slsh != -1) {
|
|
|
|
dirstr = filestr.left(slsh+1);
|
|
|
|
filestr.remove(0, slsh+1);
|
|
|
|
}
|
|
|
|
if(!dirstr.endsWith(Option::dir_sep))
|
|
|
|
dirstr += Option::dir_sep;
|
2012-08-07 15:25:00 +00:00
|
|
|
QString dst_dir = dst;
|
|
|
|
if (!base_path.isEmpty()) {
|
|
|
|
if (!dirstr.startsWith(base_path)) {
|
|
|
|
warn_msg(WarnLogic, "File %s in install rule %s does not start with base %s",
|
2012-09-06 10:21:38 +00:00
|
|
|
qPrintable(wild), qPrintable((*it).toQString()),
|
|
|
|
qPrintable(base_path));
|
2012-08-07 15:25:00 +00:00
|
|
|
} else {
|
|
|
|
QString dir_sfx = dirstr.mid(base_path.length());
|
|
|
|
dst_dir += dir_sfx;
|
|
|
|
if (!dir_sfx.isEmpty() && !made_dirs.contains(dir_sfx)) {
|
|
|
|
made_dirs.insert(dir_sfx);
|
|
|
|
QString tmp_dst = fileFixify(dst_dir, FileFixifyAbsolute, false);
|
|
|
|
tmp_dst.chop(1);
|
|
|
|
inst << mkdir_p_asstring(filePrefixRoot(root, tmp_dst));
|
|
|
|
for (int i = dst.length(); i < dst_dir.length(); i++) {
|
|
|
|
if (dst_dir.at(i) == Option::dir_sep) {
|
|
|
|
QString subd = dst_dir.left(i);
|
|
|
|
if (!removed_dirs.contains(subd)) {
|
|
|
|
removed_dirs.insert(subd);
|
|
|
|
tmp_dst = fileFixify(subd, FileFixifyAbsolute, false);
|
|
|
|
uninst << "-$(DEL_DIR) "
|
|
|
|
+ escapeFilePath(filePrefixRoot(root, tmp_dst));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-04-27 10:05:43 +00:00
|
|
|
bool is_target = (wild == fileFixify(var("TARGET"), FileFixifyAbsolute));
|
|
|
|
if(is_target || exists(wild)) { //real file or target
|
|
|
|
QFileInfo fi(fileInfo(wild));
|
2012-08-07 15:25:00 +00:00
|
|
|
QString dst_file = filePrefixRoot(root, dst_dir);
|
2011-04-27 10:05:43 +00:00
|
|
|
if(fi.isDir() && project->isActiveConfig("copy_dir_files")) {
|
|
|
|
if(!dst_file.endsWith(Option::dir_sep))
|
|
|
|
dst_file += Option::dir_sep;
|
|
|
|
dst_file += fi.fileName();
|
|
|
|
}
|
|
|
|
QString cmd;
|
|
|
|
if (fi.isDir())
|
|
|
|
cmd = "-$(INSTALL_DIR)";
|
|
|
|
else if (is_target || fi.isExecutable())
|
|
|
|
cmd = "-$(INSTALL_PROGRAM)";
|
|
|
|
else
|
|
|
|
cmd = "-$(INSTALL_FILE)";
|
2012-08-07 15:14:39 +00:00
|
|
|
cmd += " " + escapeFilePath(wild) + " " + escapeFilePath(dst_file);
|
|
|
|
inst << cmd;
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!project->isActiveConfig("debug") && !project->isActiveConfig("nostrip") &&
|
|
|
|
!fi.isDir() && fi.isExecutable() && !project->isEmpty("QMAKE_STRIP"))
|
2012-08-07 15:14:39 +00:00
|
|
|
inst << QString("-") + var("QMAKE_STRIP") + " " +
|
2012-08-07 15:25:00 +00:00
|
|
|
escapeFilePath(filePrefixRoot(root, fileFixify(dst_dir + filestr, FileFixifyAbsolute, false)));
|
|
|
|
uninst.append(rm_dir_contents + " " + escapeFilePath(filePrefixRoot(root, fileFixify(dst_dir + filestr, FileFixifyAbsolute, false))));
|
2011-04-27 10:05:43 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
QString local_dirstr = Option::fixPathToLocalOS(dirstr, true);
|
|
|
|
QStringList files = QDir(local_dirstr).entryList(QStringList(filestr));
|
|
|
|
if (installConfigValues.contains("no_check_exist") && files.isEmpty()) {
|
2012-08-07 15:25:00 +00:00
|
|
|
QString dst_file = filePrefixRoot(root, dst_dir);
|
2011-04-27 10:05:43 +00:00
|
|
|
QString cmd;
|
|
|
|
if (installConfigValues.contains("directory")) {
|
|
|
|
cmd = QLatin1String("-$(INSTALL_DIR)");
|
2012-08-06 19:45:58 +00:00
|
|
|
if (project->isActiveConfig("copy_dir_files")) {
|
|
|
|
if (!dst_file.endsWith(Option::dir_sep))
|
|
|
|
dst_file += Option::dir_sep;
|
|
|
|
dst_file += filestr;
|
|
|
|
}
|
2011-04-27 10:05:43 +00:00
|
|
|
} else if (installConfigValues.contains("executable")) {
|
|
|
|
cmd = QLatin1String("-$(INSTALL_PROGRAM)");
|
|
|
|
} else {
|
2012-08-06 19:42:41 +00:00
|
|
|
cmd = QLatin1String("-$(INSTALL_FILE)");
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
2012-08-07 15:14:39 +00:00
|
|
|
cmd += " " + escapeFilePath(wild) + " " + escapeFilePath(dst_file);
|
|
|
|
inst << cmd;
|
2012-08-07 15:25:00 +00:00
|
|
|
uninst.append(rm_dir_contents + " " + escapeFilePath(filePrefixRoot(root, fileFixify(dst_dir + filestr, FileFixifyAbsolute, false))));
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
for(int x = 0; x < files.count(); x++) {
|
|
|
|
QString file = files[x];
|
|
|
|
if(file == "." || file == "..") //blah
|
|
|
|
continue;
|
2012-08-07 15:25:00 +00:00
|
|
|
uninst.append(rm_dir_contents + " " + escapeFilePath(filePrefixRoot(root, fileFixify(dst_dir + file, FileFixifyAbsolute, false))));
|
2011-04-27 10:05:43 +00:00
|
|
|
QFileInfo fi(fileInfo(dirstr + file));
|
2012-08-07 15:25:00 +00:00
|
|
|
QString dst_file = filePrefixRoot(root, fileFixify(dst_dir, FileFixifyAbsolute, false));
|
2011-04-27 10:05:43 +00:00
|
|
|
if(fi.isDir() && project->isActiveConfig("copy_dir_files")) {
|
|
|
|
if(!dst_file.endsWith(Option::dir_sep))
|
|
|
|
dst_file += Option::dir_sep;
|
|
|
|
dst_file += fi.fileName();
|
|
|
|
}
|
|
|
|
QString cmd = QString(fi.isDir() ? "-$(INSTALL_DIR)" : "-$(INSTALL_FILE)") + " " +
|
2012-08-07 15:14:39 +00:00
|
|
|
escapeFilePath(dirstr + file) + " " + escapeFilePath(dst_file);
|
|
|
|
inst << cmd;
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!project->isActiveConfig("debug") && !project->isActiveConfig("nostrip") &&
|
|
|
|
!fi.isDir() && fi.isExecutable() && !project->isEmpty("QMAKE_STRIP"))
|
2012-08-07 15:14:39 +00:00
|
|
|
inst << QString("-") + var("QMAKE_STRIP") + " " +
|
2012-08-07 15:25:00 +00:00
|
|
|
escapeFilePath(filePrefixRoot(root, fileFixify(dst_dir + file, FileFixifyAbsolute, false)));
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-08-07 15:14:39 +00:00
|
|
|
QString target;
|
2011-04-27 10:05:43 +00:00
|
|
|
//default?
|
2012-08-07 14:35:11 +00:00
|
|
|
if (do_default)
|
2012-09-06 10:21:38 +00:00
|
|
|
target = defaultInstall((*it).toQString());
|
2012-08-07 15:14:39 +00:00
|
|
|
else
|
|
|
|
target = inst.join("\n\t");
|
2012-05-18 18:00:23 +00:00
|
|
|
QString puninst = project->values(ProKey(*it + ".uninstall")).join(' ');
|
2012-08-07 14:35:11 +00:00
|
|
|
if (!puninst.isEmpty())
|
|
|
|
uninst << puninst;
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
if (!target.isEmpty() || installConfigValues.indexOf("dummy_install") != -1) {
|
|
|
|
if (noBuild || installConfigValues.indexOf("no_build") != -1)
|
2011-04-27 10:05:43 +00:00
|
|
|
t << "install_" << (*it) << ":";
|
|
|
|
else if(project->isActiveConfig("build_all"))
|
|
|
|
t << "install_" << (*it) << ": all";
|
|
|
|
else
|
|
|
|
t << "install_" << (*it) << ": first";
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &deps = project->values(ProKey(*it + ".depends"));
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!deps.isEmpty()) {
|
2012-09-06 10:21:38 +00:00
|
|
|
for (ProStringList::ConstIterator dep_it = deps.begin(); dep_it != deps.end(); ++dep_it) {
|
|
|
|
QString targ = var(ProKey(*dep_it + ".target"));
|
2011-04-27 10:05:43 +00:00
|
|
|
if(targ.isEmpty())
|
2012-09-06 10:21:38 +00:00
|
|
|
targ = (*dep_it).toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
t << " " << escapeDependencyPath(targ);
|
|
|
|
}
|
|
|
|
}
|
2012-04-25 15:12:53 +00:00
|
|
|
t << " FORCE\n\t";
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &dirs = project->values(pvar);
|
|
|
|
for (ProStringList::ConstIterator pit = dirs.begin(); pit != dirs.end(); ++pit) {
|
|
|
|
QString tmp_dst = fileFixify((*pit).toQString(), FileFixifyAbsolute, false);
|
2011-04-27 10:05:43 +00:00
|
|
|
t << mkdir_p_asstring(filePrefixRoot(root, tmp_dst)) << "\n\t";
|
|
|
|
}
|
|
|
|
t << target << endl << endl;
|
|
|
|
if(!uninst.isEmpty()) {
|
2012-08-07 14:35:11 +00:00
|
|
|
t << "uninstall_" << (*it) << ": FORCE";
|
|
|
|
for (int i = uninst.size(); --i >= 0; )
|
|
|
|
t << "\n\t" << uninst.at(i);
|
2013-07-04 09:25:16 +00:00
|
|
|
t << "\n\t-$(DEL_DIR) " << filePrefixRoot(root, dst) << " \n\n";
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
t << endl;
|
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
if (installConfigValues.indexOf("no_default_install") == -1) {
|
2011-04-27 10:05:43 +00:00
|
|
|
all_installs += QString("install_") + (*it) + " ";
|
|
|
|
if(!uninst.isEmpty())
|
|
|
|
all_uninstalls += "uninstall_" + (*it) + " ";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
debug_msg(1, "no definition for install %s: install target not created",(*it).toLatin1().constData());
|
|
|
|
}
|
|
|
|
}
|
2012-04-25 15:12:53 +00:00
|
|
|
t << "install: " << var("INSTALLDEPS") << " " << all_installs
|
|
|
|
<< " FORCE\n\nuninstall: " << all_uninstalls << " " << var("UNINSTALLDEPS")
|
|
|
|
<< " FORCE\n\n";
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QString
|
2012-09-06 10:21:38 +00:00
|
|
|
MakefileGenerator::var(const ProKey &var)
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
|
|
|
return val(project->values(var));
|
|
|
|
}
|
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
QString
|
|
|
|
MakefileGenerator::val(const ProStringList &varList)
|
|
|
|
{
|
|
|
|
return valGlue(varList, "", " ", "");
|
|
|
|
}
|
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
QString
|
|
|
|
MakefileGenerator::val(const QStringList &varList)
|
|
|
|
{
|
|
|
|
return valGlue(varList, "", " ", "");
|
|
|
|
}
|
|
|
|
|
|
|
|
QString
|
2012-09-06 10:21:38 +00:00
|
|
|
MakefileGenerator::varGlue(const ProKey &var, const QString &before, const QString &glue, const QString &after)
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
|
|
|
return valGlue(project->values(var), before, glue, after);
|
|
|
|
}
|
|
|
|
|
2012-07-12 10:08:42 +00:00
|
|
|
QString
|
2012-09-06 10:21:38 +00:00
|
|
|
MakefileGenerator::fileVarGlue(const ProKey &var, const QString &before, const QString &glue, const QString &after)
|
2012-07-12 10:08:42 +00:00
|
|
|
{
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList varList;
|
|
|
|
foreach (const ProString &val, project->values(var))
|
|
|
|
varList << escapeFilePath(Option::fixPathToTargetOS(val.toQString()));
|
2012-07-12 10:08:42 +00:00
|
|
|
return valGlue(varList, before, glue, after);
|
|
|
|
}
|
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
QString
|
|
|
|
MakefileGenerator::valGlue(const ProStringList &varList, const QString &before, const QString &glue, const QString &after)
|
|
|
|
{
|
|
|
|
QString ret;
|
|
|
|
for (ProStringList::ConstIterator it = varList.begin(); it != varList.end(); ++it) {
|
|
|
|
if (!(*it).isEmpty()) {
|
|
|
|
if (!ret.isEmpty())
|
|
|
|
ret += glue;
|
|
|
|
ret += (*it).toQString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret.isEmpty() ? QString("") : before + ret + after;
|
|
|
|
}
|
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
QString
|
|
|
|
MakefileGenerator::valGlue(const QStringList &varList, const QString &before, const QString &glue, const QString &after)
|
|
|
|
{
|
|
|
|
QString ret;
|
|
|
|
for(QStringList::ConstIterator it = varList.begin(); it != varList.end(); ++it) {
|
|
|
|
if(!(*it).isEmpty()) {
|
|
|
|
if(!ret.isEmpty())
|
|
|
|
ret += glue;
|
|
|
|
ret += (*it);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret.isEmpty() ? QString("") : before + ret + after;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QString
|
2012-09-06 10:21:38 +00:00
|
|
|
MakefileGenerator::varList(const ProKey &var)
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
|
|
|
return valList(project->values(var));
|
|
|
|
}
|
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
QString
|
|
|
|
MakefileGenerator::valList(const ProStringList &varList)
|
|
|
|
{
|
|
|
|
return valGlue(varList, "", " \\\n\t\t", "");
|
|
|
|
}
|
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
QString
|
|
|
|
MakefileGenerator::valList(const QStringList &varList)
|
|
|
|
{
|
|
|
|
return valGlue(varList, "", " \\\n\t\t", "");
|
|
|
|
}
|
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList
|
|
|
|
MakefileGenerator::createObjectList(const ProStringList &sources)
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList ret;
|
2011-04-27 10:05:43 +00:00
|
|
|
QString objdir;
|
|
|
|
if(!project->values("OBJECTS_DIR").isEmpty())
|
2012-09-06 10:21:38 +00:00
|
|
|
objdir = project->first("OBJECTS_DIR").toQString();
|
|
|
|
for (ProStringList::ConstIterator it = sources.begin(); it != sources.end(); ++it) {
|
|
|
|
QString sfn = (*it).toQString();
|
|
|
|
QFileInfo fi(fileInfo(Option::fixPathToLocalOS(sfn)));
|
2011-04-27 10:05:43 +00:00
|
|
|
QString dir;
|
2012-08-16 11:02:30 +00:00
|
|
|
if (project->isActiveConfig("object_parallel_to_source")) {
|
2011-12-05 14:50:43 +00:00
|
|
|
// The source paths are relative to the output dir, but we need source-relative paths
|
2012-09-06 10:21:38 +00:00
|
|
|
QString sourceRelativePath = fileFixify(sfn, qmake_getpwd(), Option::output_dir);
|
2011-12-05 14:50:43 +00:00
|
|
|
sourceRelativePath = Option::fixPathToTargetOS(sourceRelativePath, false);
|
|
|
|
|
|
|
|
if (sourceRelativePath.startsWith(".." + Option::dir_sep))
|
|
|
|
sourceRelativePath = fileFixify(sourceRelativePath, FileFixifyAbsolute);
|
|
|
|
|
|
|
|
if (QDir::isAbsolutePath(sourceRelativePath))
|
|
|
|
sourceRelativePath.remove(0, sourceRelativePath.indexOf(Option::dir_sep) + 1);
|
|
|
|
|
|
|
|
dir = objdir; // We still respect OBJECTS_DIR
|
|
|
|
|
|
|
|
int lastDirSepPosition = sourceRelativePath.lastIndexOf(Option::dir_sep);
|
|
|
|
if (lastDirSepPosition != -1)
|
|
|
|
dir += sourceRelativePath.leftRef(lastDirSepPosition + 1);
|
|
|
|
|
|
|
|
if (!noIO()) {
|
|
|
|
// Ensure that the final output directory of each object exists
|
|
|
|
QString outRelativePath = fileFixify(dir, qmake_getpwd(), Option::output_dir);
|
|
|
|
if (!mkdir(outRelativePath))
|
|
|
|
warn_msg(WarnLogic, "Cannot create directory '%s'", outRelativePath.toLatin1().constData());
|
|
|
|
}
|
2011-04-27 10:05:43 +00:00
|
|
|
} else {
|
|
|
|
dir = objdir;
|
|
|
|
}
|
|
|
|
ret.append(dir + fi.completeBaseName() + Option::obj_ext);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ReplaceExtraCompilerCacheKey::ReplaceExtraCompilerCacheKey(const QString &v, const QStringList &i, const QStringList &o)
|
|
|
|
{
|
|
|
|
static QString doubleColon = QLatin1String("::");
|
|
|
|
|
|
|
|
hash = 0;
|
|
|
|
pwd = qmake_getpwd();
|
|
|
|
var = v;
|
|
|
|
{
|
|
|
|
QStringList il = i;
|
|
|
|
il.sort();
|
|
|
|
in = il.join(doubleColon);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
QStringList ol = o;
|
|
|
|
ol.sort();
|
|
|
|
out = ol.join(doubleColon);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ReplaceExtraCompilerCacheKey::operator==(const ReplaceExtraCompilerCacheKey &f) const
|
|
|
|
{
|
|
|
|
return (hashCode() == f.hashCode() &&
|
|
|
|
f.in == in &&
|
|
|
|
f.out == out &&
|
|
|
|
f.var == var &&
|
|
|
|
f.pwd == pwd);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QString
|
|
|
|
MakefileGenerator::replaceExtraCompilerVariables(const QString &orig_var, const QStringList &in, const QStringList &out)
|
|
|
|
{
|
|
|
|
//lazy cache
|
|
|
|
ReplaceExtraCompilerCacheKey cacheKey(orig_var, in, out);
|
|
|
|
QString cacheVal = extraCompilerVariablesCache.value(cacheKey);
|
|
|
|
if(!cacheVal.isNull())
|
|
|
|
return cacheVal;
|
|
|
|
|
|
|
|
//do the work
|
|
|
|
QString ret = orig_var;
|
|
|
|
QRegExp reg_var("\\$\\{.*\\}");
|
|
|
|
reg_var.setMinimal(true);
|
|
|
|
for(int rep = 0; (rep = reg_var.indexIn(ret, rep)) != -1; ) {
|
|
|
|
QStringList val;
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProString var(ret.mid(rep + 2, reg_var.matchedLength() - 3));
|
2011-04-27 10:05:43 +00:00
|
|
|
bool filePath = false;
|
|
|
|
if(val.isEmpty() && var.startsWith(QLatin1String("QMAKE_VAR_"))) {
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProKey varname = var.mid(10).toKey();
|
|
|
|
val += project->values(varname).toQStringList();
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
if(val.isEmpty() && var.startsWith(QLatin1String("QMAKE_VAR_FIRST_"))) {
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProKey varname = var.mid(16).toKey();
|
|
|
|
val += project->first(varname).toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(val.isEmpty() && !in.isEmpty()) {
|
|
|
|
if(var.startsWith(QLatin1String("QMAKE_FUNC_FILE_IN_"))) {
|
|
|
|
filePath = true;
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProKey funcname = var.mid(19).toKey();
|
|
|
|
val += project->expand(funcname, QList<ProStringList>() << ProStringList(in));
|
2011-04-27 10:05:43 +00:00
|
|
|
} else if(var == QLatin1String("QMAKE_FILE_BASE") || var == QLatin1String("QMAKE_FILE_IN_BASE")) {
|
|
|
|
//filePath = true;
|
|
|
|
for(int i = 0; i < in.size(); ++i) {
|
|
|
|
QFileInfo fi(fileInfo(Option::fixPathToLocalOS(in.at(i))));
|
|
|
|
QString base = fi.completeBaseName();
|
|
|
|
if(base.isNull())
|
|
|
|
base = fi.fileName();
|
|
|
|
val += base;
|
|
|
|
}
|
|
|
|
} else if(var == QLatin1String("QMAKE_FILE_EXT")) {
|
|
|
|
filePath = true;
|
|
|
|
for(int i = 0; i < in.size(); ++i) {
|
|
|
|
QFileInfo fi(fileInfo(Option::fixPathToLocalOS(in.at(i))));
|
|
|
|
QString ext;
|
|
|
|
// Ensure complementarity with QMAKE_FILE_BASE
|
|
|
|
int baseLen = fi.completeBaseName().length();
|
|
|
|
if(baseLen == 0)
|
|
|
|
ext = fi.fileName();
|
|
|
|
else
|
|
|
|
ext = fi.fileName().remove(0, baseLen);
|
|
|
|
val += ext;
|
|
|
|
}
|
|
|
|
} else if(var == QLatin1String("QMAKE_FILE_PATH") || var == QLatin1String("QMAKE_FILE_IN_PATH")) {
|
|
|
|
filePath = true;
|
|
|
|
for(int i = 0; i < in.size(); ++i)
|
|
|
|
val += fileInfo(Option::fixPathToLocalOS(in.at(i))).path();
|
|
|
|
} else if(var == QLatin1String("QMAKE_FILE_NAME") || var == QLatin1String("QMAKE_FILE_IN")) {
|
|
|
|
filePath = true;
|
|
|
|
for(int i = 0; i < in.size(); ++i)
|
|
|
|
val += fileInfo(Option::fixPathToLocalOS(in.at(i))).filePath();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(val.isEmpty() && !out.isEmpty()) {
|
|
|
|
if(var.startsWith(QLatin1String("QMAKE_FUNC_FILE_OUT_"))) {
|
|
|
|
filePath = true;
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProKey funcname = var.mid(20).toKey();
|
|
|
|
val += project->expand(funcname, QList<ProStringList>() << ProStringList(out));
|
2011-04-27 10:05:43 +00:00
|
|
|
} else if(var == QLatin1String("QMAKE_FILE_OUT")) {
|
|
|
|
filePath = true;
|
|
|
|
for(int i = 0; i < out.size(); ++i)
|
|
|
|
val += fileInfo(Option::fixPathToLocalOS(out.at(i))).filePath();
|
|
|
|
} else if(var == QLatin1String("QMAKE_FILE_OUT_BASE")) {
|
|
|
|
//filePath = true;
|
|
|
|
for(int i = 0; i < out.size(); ++i) {
|
|
|
|
QFileInfo fi(fileInfo(Option::fixPathToLocalOS(out.at(i))));
|
|
|
|
QString base = fi.completeBaseName();
|
|
|
|
if(base.isNull())
|
|
|
|
base = fi.fileName();
|
|
|
|
val += base;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(val.isEmpty() && var.startsWith(QLatin1String("QMAKE_FUNC_"))) {
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProKey funcname = var.mid(11).toKey();
|
|
|
|
val += project->expand(funcname, QList<ProStringList>() << ProStringList(in) << ProStringList(out));
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(!val.isEmpty()) {
|
|
|
|
QString fullVal;
|
|
|
|
if(filePath) {
|
|
|
|
for(int i = 0; i < val.size(); ++i) {
|
|
|
|
const QString file = Option::fixPathToTargetOS(unescapeFilePath(val.at(i)), false);
|
|
|
|
if(!fullVal.isEmpty())
|
|
|
|
fullVal += " ";
|
|
|
|
fullVal += escapeFilePath(file);
|
|
|
|
}
|
|
|
|
} else {
|
2012-05-18 18:00:23 +00:00
|
|
|
fullVal = val.join(' ');
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
ret.replace(rep, reg_var.matchedLength(), fullVal);
|
|
|
|
rep += fullVal.length();
|
|
|
|
} else {
|
|
|
|
rep += reg_var.matchedLength();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//cache the value
|
|
|
|
extraCompilerVariablesCache.insert(cacheKey, ret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2012-09-06 10:21:38 +00:00
|
|
|
MakefileGenerator::verifyExtraCompiler(const ProString &comp, const QString &file_unfixed)
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
|
|
|
if(noIO())
|
|
|
|
return false;
|
|
|
|
const QString file = Option::fixPathToLocalOS(file_unfixed);
|
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &config = project->values(ProKey(comp + ".CONFIG"));
|
|
|
|
if (config.indexOf("moc_verify") != -1) {
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!file.isNull()) {
|
|
|
|
QMakeSourceFileInfo::addSourceFile(file, QMakeSourceFileInfo::SEEK_MOCS);
|
|
|
|
if(!mocable(file)) {
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
project->values("MOCABLES").append(file);
|
|
|
|
}
|
|
|
|
}
|
2012-09-06 10:21:38 +00:00
|
|
|
} else if (config.indexOf("function_verify") != -1) {
|
|
|
|
ProString tmp_out = project->values(ProKey(comp + ".output")).first();
|
2011-04-27 10:05:43 +00:00
|
|
|
if(tmp_out.isEmpty())
|
|
|
|
return false;
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList verify_function = project->values(ProKey(comp + ".verify_function"));
|
2011-04-27 10:05:43 +00:00
|
|
|
if(verify_function.isEmpty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for(int i = 0; i < verify_function.size(); ++i) {
|
|
|
|
bool invert = false;
|
2012-09-06 10:21:38 +00:00
|
|
|
ProString verify = verify_function.at(i);
|
2011-04-27 10:05:43 +00:00
|
|
|
if(verify.at(0) == QLatin1Char('!')) {
|
|
|
|
invert = true;
|
|
|
|
verify = verify.mid(1);
|
|
|
|
}
|
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
if (config.indexOf("combine") != -1) {
|
|
|
|
bool pass = project->test(verify.toKey(), QList<ProStringList>() << ProStringList(tmp_out) << ProStringList(file));
|
2011-04-27 10:05:43 +00:00
|
|
|
if(invert)
|
|
|
|
pass = !pass;
|
|
|
|
if(!pass)
|
|
|
|
return false;
|
|
|
|
} else {
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &tmp = project->values(ProKey(comp + ".input"));
|
|
|
|
for (ProStringList::ConstIterator it = tmp.begin(); it != tmp.end(); ++it) {
|
|
|
|
const ProStringList &inputs = project->values((*it).toKey());
|
|
|
|
for (ProStringList::ConstIterator input = inputs.begin(); input != inputs.end(); ++input) {
|
2011-04-27 10:05:43 +00:00
|
|
|
if((*input).isEmpty())
|
|
|
|
continue;
|
2012-09-06 10:21:38 +00:00
|
|
|
QString inpf = (*input).toQString();
|
|
|
|
QString in = fileFixify(Option::fixPathToTargetOS(inpf, false));
|
2011-04-27 10:05:43 +00:00
|
|
|
if(in == file) {
|
2012-09-06 10:21:38 +00:00
|
|
|
bool pass = project->test(verify.toKey(),
|
|
|
|
QList<ProStringList>() << ProStringList(replaceExtraCompilerVariables(tmp_out.toQString(), inpf, QString())) <<
|
|
|
|
ProStringList(file));
|
2011-04-27 10:05:43 +00:00
|
|
|
if(invert)
|
|
|
|
pass = !pass;
|
|
|
|
if(!pass)
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-09-06 10:21:38 +00:00
|
|
|
} else if (config.indexOf("verify") != -1) {
|
|
|
|
QString tmp_out = project->values(ProKey(comp + ".output")).first().toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
if(tmp_out.isEmpty())
|
|
|
|
return false;
|
|
|
|
QString tmp_cmd;
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProKey ckey(comp + ".commands");
|
|
|
|
if (!project->isEmpty(ckey)) {
|
2011-04-27 10:05:43 +00:00
|
|
|
int argv0 = -1;
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList cmdline = project->values(ckey);
|
2011-04-27 10:05:43 +00:00
|
|
|
for(int i = 0; i < cmdline.count(); ++i) {
|
|
|
|
if(!cmdline.at(i).contains('=')) {
|
|
|
|
argv0 = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(argv0 != -1) {
|
2012-09-06 10:21:38 +00:00
|
|
|
cmdline[argv0] = Option::fixPathToTargetOS(cmdline.at(argv0).toQString(), false);
|
2012-05-18 18:00:23 +00:00
|
|
|
tmp_cmd = cmdline.join(' ');
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
if (config.indexOf("combine") != -1) {
|
2011-04-27 10:05:43 +00:00
|
|
|
QString cmd = replaceExtraCompilerVariables(tmp_cmd, QString(), tmp_out);
|
|
|
|
if(system(cmd.toLatin1().constData()))
|
|
|
|
return false;
|
|
|
|
} else {
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &tmp = project->values(ProKey(comp + ".input"));
|
|
|
|
for (ProStringList::ConstIterator it = tmp.begin(); it != tmp.end(); ++it) {
|
|
|
|
const ProStringList &inputs = project->values((*it).toKey());
|
|
|
|
for (ProStringList::ConstIterator input = inputs.begin(); input != inputs.end(); ++input) {
|
2011-04-27 10:05:43 +00:00
|
|
|
if((*input).isEmpty())
|
|
|
|
continue;
|
2012-09-06 10:21:38 +00:00
|
|
|
QString inpf = (*input).toQString();
|
|
|
|
QString in = fileFixify(Option::fixPathToTargetOS(inpf, false));
|
2011-04-27 10:05:43 +00:00
|
|
|
if(in == file) {
|
2012-09-06 10:21:38 +00:00
|
|
|
QString out = replaceExtraCompilerVariables(tmp_out, inpf, QString());
|
2011-04-27 10:05:43 +00:00
|
|
|
QString cmd = replaceExtraCompilerVariables(tmp_cmd, in, out);
|
|
|
|
if(system(cmd.toLatin1().constData()))
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
MakefileGenerator::writeExtraTargets(QTextStream &t)
|
|
|
|
{
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &qut = project->values("QMAKE_EXTRA_TARGETS");
|
|
|
|
for (ProStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it) {
|
|
|
|
QString targ = var(ProKey(*it + ".target")),
|
|
|
|
cmd = var(ProKey(*it + ".commands")), deps;
|
2011-04-27 10:05:43 +00:00
|
|
|
if(targ.isEmpty())
|
2012-09-06 10:21:38 +00:00
|
|
|
targ = (*it).toQString();
|
|
|
|
const ProStringList &deplist = project->values(ProKey(*it + ".depends"));
|
|
|
|
for (ProStringList::ConstIterator dep_it = deplist.begin(); dep_it != deplist.end(); ++dep_it) {
|
|
|
|
QString dep = var(ProKey(*dep_it + ".target"));
|
2011-04-27 10:05:43 +00:00
|
|
|
if(dep.isEmpty())
|
2012-09-06 10:21:38 +00:00
|
|
|
dep = (*dep_it).toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
deps += " " + escapeDependencyPath(dep);
|
|
|
|
}
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &config = project->values(ProKey(*it + ".CONFIG"));
|
|
|
|
if (config.indexOf("fix_target") != -1)
|
2011-04-27 10:05:43 +00:00
|
|
|
targ = fileFixify(targ, Option::output_dir, Option::output_dir);
|
2012-09-06 10:21:38 +00:00
|
|
|
if (config.indexOf("phony") != -1)
|
2012-04-25 15:12:53 +00:00
|
|
|
deps += QLatin1String(" FORCE");
|
2011-04-27 10:05:43 +00:00
|
|
|
t << escapeDependencyPath(targ) << ":" << deps;
|
|
|
|
if(!cmd.isEmpty())
|
|
|
|
t << "\n\t" << cmd;
|
|
|
|
t << endl << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
|
|
|
|
{
|
|
|
|
QString clean_targets;
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &quc = project->values("QMAKE_EXTRA_COMPILERS");
|
|
|
|
for (ProStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) {
|
|
|
|
QString tmp_out = fileFixify(project->first(ProKey(*it + ".output")).toQString(),
|
2011-04-27 10:05:43 +00:00
|
|
|
Option::output_dir, Option::output_dir);
|
|
|
|
QString tmp_cmd;
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProKey ckey(*it + ".commands");
|
|
|
|
if (!project->isEmpty(ckey)) {
|
|
|
|
QStringList cmdline = project->values(ckey).toQStringList();
|
2011-04-27 10:05:43 +00:00
|
|
|
int argv0 = findExecutable(cmdline);
|
|
|
|
if(argv0 != -1) {
|
|
|
|
cmdline[argv0] = escapeFilePath(Option::fixPathToTargetOS(cmdline.at(argv0), false));
|
2012-05-18 18:00:23 +00:00
|
|
|
tmp_cmd = cmdline.join(' ');
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
QString tmp_dep_cmd;
|
|
|
|
QString dep_cd_cmd;
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProKey dckey(*it + ".depend_command");
|
|
|
|
if (!project->isEmpty(dckey)) {
|
2011-04-27 10:05:43 +00:00
|
|
|
int argv0 = -1;
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList cmdline = project->values(dckey);
|
2011-04-27 10:05:43 +00:00
|
|
|
for(int i = 0; i < cmdline.count(); ++i) {
|
|
|
|
if(!cmdline.at(i).contains('=')) {
|
|
|
|
argv0 = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(argv0 != -1) {
|
2012-09-06 10:21:38 +00:00
|
|
|
QString arg = cmdline.at(argv0).toQString();
|
|
|
|
const QString c = Option::fixPathToLocalOS(arg, true);
|
2011-04-27 10:05:43 +00:00
|
|
|
if(exists(c)) {
|
2012-09-06 10:21:38 +00:00
|
|
|
arg = escapeFilePath(Option::fixPathToLocalOS(arg, false));
|
2011-04-27 10:05:43 +00:00
|
|
|
} else {
|
2012-09-06 10:21:38 +00:00
|
|
|
arg = escapeFilePath(arg);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
2012-09-06 10:21:38 +00:00
|
|
|
QFileInfo cmdFileInfo(arg);
|
|
|
|
if (!cmdFileInfo.isAbsolute() || cmdFileInfo.exists()) {
|
|
|
|
cmdline[argv0] = arg;
|
2012-05-18 18:00:23 +00:00
|
|
|
tmp_dep_cmd = cmdline.join(' ');
|
2012-09-06 10:21:38 +00:00
|
|
|
}
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
dep_cd_cmd = QLatin1String("cd ")
|
|
|
|
+ escapeFilePath(Option::fixPathToLocalOS(Option::output_dir, false))
|
|
|
|
+ QLatin1String(" && ");
|
|
|
|
}
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &vars = project->values(ProKey(*it + ".variables"));
|
2011-04-27 10:05:43 +00:00
|
|
|
if(tmp_out.isEmpty() || tmp_cmd.isEmpty())
|
|
|
|
continue;
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList tmp_inputs;
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &comp_inputs = project->values(ProKey(*it + ".input"));
|
|
|
|
for (ProStringList::ConstIterator it2 = comp_inputs.begin(); it2 != comp_inputs.end(); ++it2) {
|
|
|
|
const ProStringList &tmp = project->values((*it2).toKey());
|
|
|
|
for (ProStringList::ConstIterator input = tmp.begin(); input != tmp.end(); ++input) {
|
|
|
|
QString in = Option::fixPathToTargetOS((*input).toQString(), false);
|
2011-04-27 10:05:43 +00:00
|
|
|
if(verifyExtraCompiler((*it), in))
|
|
|
|
tmp_inputs.append((*input));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
t << "compiler_" << (*it) << "_make_all:";
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &config = project->values(ProKey(*it + ".CONFIG"));
|
|
|
|
if (config.indexOf("combine") != -1) {
|
2011-04-27 10:05:43 +00:00
|
|
|
// compilers with a combined input only have one output
|
2012-09-06 10:21:38 +00:00
|
|
|
QString input = project->first(ProKey(*it + ".output")).toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
t << " " << escapeDependencyPath(replaceExtraCompilerVariables(tmp_out, input, QString()));
|
|
|
|
} else {
|
2012-09-06 10:21:38 +00:00
|
|
|
for (ProStringList::ConstIterator input = tmp_inputs.begin(); input != tmp_inputs.end(); ++input) {
|
|
|
|
t << " " << escapeDependencyPath(replaceExtraCompilerVariables(tmp_out, (*input).toQString(), QString()));
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
t << endl;
|
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
if (config.indexOf("no_clean") == -1) {
|
2012-05-18 18:00:23 +00:00
|
|
|
QString tmp_clean = project->values(ProKey(*it + ".clean")).join(' ');
|
|
|
|
QString tmp_clean_cmds = project->values(ProKey(*it + ".clean_commands")).join(' ');
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!tmp_inputs.isEmpty())
|
|
|
|
clean_targets += QString("compiler_" + (*it) + "_clean ");
|
|
|
|
t << "compiler_" << (*it) << "_clean:";
|
|
|
|
bool wrote_clean_cmds = false, wrote_clean = false;
|
|
|
|
if(tmp_clean_cmds.isEmpty()) {
|
|
|
|
wrote_clean_cmds = true;
|
|
|
|
} else if(tmp_clean_cmds.indexOf("${QMAKE_") == -1) {
|
|
|
|
t << "\n\t" << tmp_clean_cmds;
|
|
|
|
wrote_clean_cmds = true;
|
|
|
|
}
|
|
|
|
if(tmp_clean.isEmpty())
|
|
|
|
tmp_clean = tmp_out;
|
|
|
|
if(tmp_clean.indexOf("${QMAKE_") == -1) {
|
2013-07-04 09:25:16 +00:00
|
|
|
t << "\n\t-$(DEL_FILE) " << tmp_clean;
|
2011-04-27 10:05:43 +00:00
|
|
|
wrote_clean = true;
|
|
|
|
}
|
|
|
|
if(!wrote_clean_cmds || !wrote_clean) {
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList cleans;
|
2011-04-27 10:05:43 +00:00
|
|
|
const QString del_statement("-$(DEL_FILE)");
|
|
|
|
if(!wrote_clean) {
|
|
|
|
if(project->isActiveConfig("no_delete_multiple_files")) {
|
2012-09-06 10:21:38 +00:00
|
|
|
for (ProStringList::ConstIterator input = tmp_inputs.begin(); input != tmp_inputs.end(); ++input) {
|
|
|
|
QString tinp = (*input).toQString();
|
|
|
|
cleans.append(" " + replaceExtraCompilerVariables(tmp_clean, tinp,
|
|
|
|
replaceExtraCompilerVariables(tmp_out, tinp, QString())));
|
|
|
|
}
|
2011-04-27 10:05:43 +00:00
|
|
|
} else {
|
|
|
|
QString files, file;
|
|
|
|
const int commandlineLimit = 2047; // NT limit, expanded
|
|
|
|
for(int input = 0; input < tmp_inputs.size(); ++input) {
|
2012-09-06 10:21:38 +00:00
|
|
|
QString tinp = tmp_inputs.at(input).toQString();
|
|
|
|
file = " " + replaceExtraCompilerVariables(tmp_clean, tinp,
|
|
|
|
replaceExtraCompilerVariables(tmp_out, tinp, QString()));
|
2011-04-27 10:05:43 +00:00
|
|
|
if(del_statement.length() + files.length() +
|
|
|
|
qMax(fixEnvVariables(file).length(), file.length()) > commandlineLimit) {
|
|
|
|
cleans.append(files);
|
|
|
|
files.clear();
|
|
|
|
}
|
|
|
|
files += file;
|
|
|
|
}
|
|
|
|
if(!files.isEmpty())
|
|
|
|
cleans.append(files);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!cleans.isEmpty())
|
|
|
|
t << valGlue(cleans, "\n\t" + del_statement, "\n\t" + del_statement, "");
|
|
|
|
if(!wrote_clean_cmds) {
|
2012-09-06 10:21:38 +00:00
|
|
|
for (ProStringList::ConstIterator input = tmp_inputs.begin(); input != tmp_inputs.end(); ++input) {
|
|
|
|
QString tinp = (*input).toQString();
|
|
|
|
t << "\n\t" << replaceExtraCompilerVariables(tmp_clean_cmds, tinp,
|
|
|
|
replaceExtraCompilerVariables(tmp_out, tinp, QString()));
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
t << endl;
|
|
|
|
}
|
2012-09-06 10:21:38 +00:00
|
|
|
QStringList tmp_dep = project->values(ProKey(*it + ".depends")).toQStringList();
|
|
|
|
if (config.indexOf("combine") != -1) {
|
2011-04-27 10:05:43 +00:00
|
|
|
if(tmp_out.indexOf("${QMAKE_") != -1) {
|
|
|
|
warn_msg(WarnLogic, "QMAKE_EXTRA_COMPILERS(%s) with combine has variable output.",
|
|
|
|
(*it).toLatin1().constData());
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
QStringList deps, inputs;
|
|
|
|
if(!tmp_dep.isEmpty())
|
|
|
|
deps += fileFixify(tmp_dep, Option::output_dir, Option::output_dir);
|
2012-09-06 10:21:38 +00:00
|
|
|
for (ProStringList::ConstIterator input = tmp_inputs.begin(); input != tmp_inputs.end(); ++input) {
|
|
|
|
QString inpf = (*input).toQString();
|
|
|
|
deps += findDependencies(inpf);
|
|
|
|
inputs += Option::fixPathToTargetOS(inpf, false);
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!tmp_dep_cmd.isEmpty() && doDepends()) {
|
|
|
|
char buff[256];
|
2012-09-06 10:21:38 +00:00
|
|
|
QString dep_cmd = replaceExtraCompilerVariables(tmp_dep_cmd, inpf, tmp_out);
|
2011-04-27 10:05:43 +00:00
|
|
|
dep_cmd = dep_cd_cmd + fixEnvVariables(dep_cmd);
|
|
|
|
if(FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), "r")) {
|
|
|
|
QString indeps;
|
|
|
|
while(!feof(proc)) {
|
|
|
|
int read_in = (int)fread(buff, 1, 255, proc);
|
|
|
|
if(!read_in)
|
|
|
|
break;
|
|
|
|
indeps += QByteArray(buff, read_in);
|
|
|
|
}
|
|
|
|
QT_PCLOSE(proc);
|
|
|
|
if(!indeps.isEmpty()) {
|
|
|
|
QStringList dep_cmd_deps = indeps.replace('\n', ' ').simplified().split(' ');
|
|
|
|
for(int i = 0; i < dep_cmd_deps.count(); ++i) {
|
|
|
|
QString &file = dep_cmd_deps[i];
|
2013-07-15 13:10:09 +00:00
|
|
|
QString absFile = QDir(Option::output_dir).absoluteFilePath(file);
|
|
|
|
if (exists(absFile)) {
|
|
|
|
file = absFile;
|
|
|
|
} else {
|
2011-04-27 10:05:43 +00:00
|
|
|
QString localFile;
|
|
|
|
QList<QMakeLocalFileName> depdirs = QMakeSourceFileInfo::dependencyPaths();
|
2013-07-15 13:09:11 +00:00
|
|
|
for (QList<QMakeLocalFileName>::Iterator dit = depdirs.begin();
|
|
|
|
dit != depdirs.end(); ++dit) {
|
|
|
|
if (exists((*dit).real() + Option::dir_sep + file)) {
|
|
|
|
localFile = (*dit).local() + Option::dir_sep + file;
|
2011-04-27 10:05:43 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2013-07-15 13:10:09 +00:00
|
|
|
if (localFile.isEmpty()) {
|
|
|
|
if (exists(file))
|
|
|
|
warn_msg(WarnDeprecated, ".depend_command for extra compiler %s"
|
|
|
|
" prints paths relative to source directory",
|
|
|
|
(*it).toLatin1().constData());
|
|
|
|
else
|
|
|
|
file.clear();
|
|
|
|
} else {
|
|
|
|
file = localFile;
|
|
|
|
}
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
if(!file.isEmpty())
|
|
|
|
file = fileFixify(file);
|
|
|
|
}
|
|
|
|
deps += dep_cmd_deps;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for(int i = 0; i < inputs.size(); ) {
|
|
|
|
if(tmp_out == inputs.at(i))
|
|
|
|
inputs.removeAt(i);
|
|
|
|
else
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
for(int i = 0; i < deps.size(); ) {
|
|
|
|
if(tmp_out == deps.at(i))
|
|
|
|
deps.removeAt(i);
|
|
|
|
else
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
if (inputs.isEmpty())
|
|
|
|
continue;
|
|
|
|
|
2011-11-04 12:51:20 +00:00
|
|
|
QString cmd = replaceExtraCompilerVariables(tmp_cmd, escapeFilePaths(inputs), QStringList(tmp_out));
|
2011-04-27 10:05:43 +00:00
|
|
|
t << escapeDependencyPath(tmp_out) << ":";
|
|
|
|
// compiler.CONFIG+=explicit_dependencies means that ONLY compiler.depends gets to cause Makefile dependencies
|
2012-09-06 10:21:38 +00:00
|
|
|
if (config.indexOf("explicit_dependencies") != -1) {
|
2011-04-27 10:05:43 +00:00
|
|
|
t << " " << valList(escapeDependencyPaths(fileFixify(tmp_dep, Option::output_dir, Option::output_dir)));
|
|
|
|
} else {
|
|
|
|
t << " " << valList(escapeDependencyPaths(inputs)) << " " << valList(escapeDependencyPaths(deps));
|
|
|
|
}
|
|
|
|
t << "\n\t" << cmd << endl << endl;
|
|
|
|
continue;
|
|
|
|
}
|
2012-09-06 10:21:38 +00:00
|
|
|
for (ProStringList::ConstIterator input = tmp_inputs.begin(); input != tmp_inputs.end(); ++input) {
|
|
|
|
QString inpf = (*input).toQString();
|
|
|
|
QString in = Option::fixPathToTargetOS(inpf, false);
|
|
|
|
QStringList deps = findDependencies(inpf);
|
2011-04-27 10:05:43 +00:00
|
|
|
deps += escapeDependencyPath(in);
|
2012-10-18 14:42:15 +00:00
|
|
|
QString out = unescapeFilePath(replaceExtraCompilerVariables(tmp_out, inpf, QString()));
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!tmp_dep.isEmpty()) {
|
|
|
|
QStringList pre_deps = fileFixify(tmp_dep, Option::output_dir, Option::output_dir);
|
|
|
|
for(int i = 0; i < pre_deps.size(); ++i)
|
2012-09-06 10:21:38 +00:00
|
|
|
deps += replaceExtraCompilerVariables(pre_deps.at(i), inpf, out);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
2012-09-06 10:21:38 +00:00
|
|
|
QString cmd = replaceExtraCompilerVariables(tmp_cmd, inpf, out);
|
2011-04-27 10:05:43 +00:00
|
|
|
// NOTE: The var -> QMAKE_COMP_var replace feature is unsupported, do not use!
|
2012-09-06 10:21:38 +00:00
|
|
|
for (ProStringList::ConstIterator it3 = vars.constBegin(); it3 != vars.constEnd(); ++it3)
|
2011-04-27 10:05:43 +00:00
|
|
|
cmd.replace("$(" + (*it3) + ")", "$(QMAKE_COMP_" + (*it3)+")");
|
|
|
|
if(!tmp_dep_cmd.isEmpty() && doDepends()) {
|
|
|
|
char buff[256];
|
2012-09-06 10:21:38 +00:00
|
|
|
QString dep_cmd = replaceExtraCompilerVariables(tmp_dep_cmd, inpf, out);
|
2011-04-27 10:05:43 +00:00
|
|
|
dep_cmd = dep_cd_cmd + fixEnvVariables(dep_cmd);
|
|
|
|
if(FILE *proc = QT_POPEN(dep_cmd.toLatin1().constData(), "r")) {
|
|
|
|
QString indeps;
|
|
|
|
while(!feof(proc)) {
|
|
|
|
int read_in = (int)fread(buff, 1, 255, proc);
|
|
|
|
if(!read_in)
|
|
|
|
break;
|
|
|
|
indeps += QByteArray(buff, read_in);
|
|
|
|
}
|
|
|
|
QT_PCLOSE(proc);
|
|
|
|
if(!indeps.isEmpty()) {
|
|
|
|
QStringList dep_cmd_deps = indeps.replace('\n', ' ').simplified().split(' ');
|
|
|
|
for(int i = 0; i < dep_cmd_deps.count(); ++i) {
|
|
|
|
QString &file = dep_cmd_deps[i];
|
2013-07-15 13:10:09 +00:00
|
|
|
QString absFile = QDir(Option::output_dir).absoluteFilePath(file);
|
|
|
|
if (exists(absFile)) {
|
|
|
|
file = absFile;
|
|
|
|
} else {
|
2011-04-27 10:05:43 +00:00
|
|
|
QString localFile;
|
|
|
|
QList<QMakeLocalFileName> depdirs = QMakeSourceFileInfo::dependencyPaths();
|
2013-07-15 13:09:11 +00:00
|
|
|
for (QList<QMakeLocalFileName>::Iterator dit = depdirs.begin();
|
|
|
|
dit != depdirs.end(); ++dit) {
|
|
|
|
if (exists((*dit).real() + Option::dir_sep + file)) {
|
|
|
|
localFile = (*dit).local() + Option::dir_sep + file;
|
2011-04-27 10:05:43 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2013-07-15 13:10:09 +00:00
|
|
|
if (localFile.isEmpty()) {
|
|
|
|
if (exists(file))
|
|
|
|
warn_msg(WarnDeprecated, ".depend_command for extra compiler %s"
|
|
|
|
" prints paths relative to source directory",
|
|
|
|
(*it).toLatin1().constData());
|
|
|
|
else
|
|
|
|
file.clear();
|
|
|
|
} else {
|
|
|
|
file = localFile;
|
|
|
|
}
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
if(!file.isEmpty())
|
|
|
|
file = fileFixify(file);
|
|
|
|
}
|
|
|
|
deps += dep_cmd_deps;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//use the depend system to find includes of these included files
|
|
|
|
QStringList inc_deps;
|
|
|
|
for(int i = 0; i < deps.size(); ++i) {
|
|
|
|
const QString dep = deps.at(i);
|
|
|
|
if(QFile::exists(dep)) {
|
|
|
|
SourceFileType type = TYPE_UNKNOWN;
|
|
|
|
if(type == TYPE_UNKNOWN) {
|
|
|
|
for(QStringList::Iterator cit = Option::c_ext.begin();
|
|
|
|
cit != Option::c_ext.end(); ++cit) {
|
|
|
|
if(dep.endsWith((*cit))) {
|
|
|
|
type = TYPE_C;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(type == TYPE_UNKNOWN) {
|
|
|
|
for(QStringList::Iterator cppit = Option::cpp_ext.begin();
|
|
|
|
cppit != Option::cpp_ext.end(); ++cppit) {
|
|
|
|
if(dep.endsWith((*cppit))) {
|
|
|
|
type = TYPE_C;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(type == TYPE_UNKNOWN) {
|
|
|
|
for(QStringList::Iterator hit = Option::h_ext.begin();
|
|
|
|
type == TYPE_UNKNOWN && hit != Option::h_ext.end(); ++hit) {
|
|
|
|
if(dep.endsWith((*hit))) {
|
|
|
|
type = TYPE_C;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(type != TYPE_UNKNOWN) {
|
|
|
|
if(!QMakeSourceFileInfo::containsSourceFile(dep, type))
|
|
|
|
QMakeSourceFileInfo::addSourceFile(dep, type);
|
|
|
|
inc_deps += QMakeSourceFileInfo::dependencies(dep);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
deps += inc_deps;
|
|
|
|
}
|
|
|
|
for(int i = 0; i < deps.size(); ) {
|
|
|
|
QString &dep = deps[i];
|
|
|
|
dep = Option::fixPathToTargetOS(unescapeFilePath(dep), false);
|
|
|
|
if(out == dep)
|
|
|
|
deps.removeAt(i);
|
|
|
|
else
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
t << escapeDependencyPath(out) << ": " << valList(escapeDependencyPaths(deps)) << "\n\t"
|
|
|
|
<< cmd << endl << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
t << "compiler_clean: " << clean_targets << endl << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
MakefileGenerator::writeExtraCompilerVariables(QTextStream &t)
|
|
|
|
{
|
|
|
|
bool first = true;
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &quc = project->values("QMAKE_EXTRA_COMPILERS");
|
|
|
|
for (ProStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) {
|
|
|
|
const ProStringList &vars = project->values(ProKey(*it + ".variables"));
|
|
|
|
for (ProStringList::ConstIterator varit = vars.begin(); varit != vars.end(); ++varit) {
|
2011-04-27 10:05:43 +00:00
|
|
|
if(first) {
|
2013-07-04 09:25:16 +00:00
|
|
|
t << "\n####### Custom Compiler Variables\n";
|
2011-04-27 10:05:43 +00:00
|
|
|
first = false;
|
|
|
|
}
|
|
|
|
t << "QMAKE_COMP_" << (*varit) << " = "
|
2012-09-06 10:21:38 +00:00
|
|
|
<< valList(project->values((*varit).toKey())) << endl;
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!first)
|
|
|
|
t << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
MakefileGenerator::writeExtraVariables(QTextStream &t)
|
|
|
|
{
|
2012-01-09 18:25:44 +00:00
|
|
|
t << endl;
|
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList outlist;
|
|
|
|
const ProValueMap &vars = project->variables();
|
|
|
|
const ProStringList &exports = project->values("QMAKE_EXTRA_VARIABLES");
|
|
|
|
for (ProValueMap::ConstIterator it = vars.begin(); it != vars.end(); ++it) {
|
|
|
|
for (ProStringList::ConstIterator exp_it = exports.begin(); exp_it != exports.end(); ++exp_it) {
|
|
|
|
QRegExp rx((*exp_it).toQString(), Qt::CaseInsensitive, QRegExp::Wildcard);
|
|
|
|
if (rx.exactMatch(it.key().toQString()))
|
2012-05-18 18:00:23 +00:00
|
|
|
outlist << ("EXPORT_" + it.key() + " = " + it.value().join(' '));
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
2012-01-09 18:25:44 +00:00
|
|
|
if (!outlist.isEmpty()) {
|
2013-07-04 09:25:16 +00:00
|
|
|
t << "####### Custom Variables\n";
|
2012-01-09 18:25:44 +00:00
|
|
|
t << outlist.join("\n") << endl << endl;
|
|
|
|
}
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
2013-08-26 17:51:57 +00:00
|
|
|
bool
|
|
|
|
MakefileGenerator::writeDummyMakefile(QTextStream &t)
|
|
|
|
{
|
|
|
|
if (project->values("QMAKE_FAILED_REQUIREMENTS").isEmpty())
|
|
|
|
return false;
|
|
|
|
t << "QMAKE = " << var("QMAKE_QMAKE") << endl;
|
|
|
|
const ProStringList &qut = project->values("QMAKE_EXTRA_TARGETS");
|
|
|
|
for (ProStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it)
|
|
|
|
t << *it << " ";
|
|
|
|
t << "first all clean install distclean uninstall qmake_all:\n\t"
|
|
|
|
<< "@echo \"Some of the required modules ("
|
|
|
|
<< var("QMAKE_FAILED_REQUIREMENTS") << ") are not available.\"\n\t"
|
|
|
|
<< "@echo \"Skipped.\"\n\n";
|
|
|
|
writeMakeQmake(t);
|
|
|
|
t << "FORCE:\n\n";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
bool
|
|
|
|
MakefileGenerator::writeStubMakefile(QTextStream &t)
|
|
|
|
{
|
|
|
|
t << "QMAKE = " << var("QMAKE_QMAKE") << endl;
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &qut = project->values("QMAKE_EXTRA_TARGETS");
|
|
|
|
for (ProStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it)
|
2011-04-27 10:05:43 +00:00
|
|
|
t << *it << " ";
|
|
|
|
//const QString ofile = Option::fixPathToTargetOS(fileFixify(Option::output.fileName()));
|
2013-07-04 09:25:16 +00:00
|
|
|
t << "first all clean install distclean uninstall: qmake\n"
|
|
|
|
<< "qmake_all:\n";
|
2011-04-27 10:05:43 +00:00
|
|
|
writeMakeQmake(t);
|
2013-07-04 09:25:16 +00:00
|
|
|
t << "FORCE:\n\n";
|
2011-04-27 10:05:43 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
MakefileGenerator::writeMakefile(QTextStream &t)
|
|
|
|
{
|
2013-07-04 09:25:16 +00:00
|
|
|
t << "####### Compile\n\n";
|
2011-04-27 10:05:43 +00:00
|
|
|
writeObj(t, "SOURCES");
|
|
|
|
writeObj(t, "GENERATED_SOURCES");
|
|
|
|
|
2013-07-04 09:25:16 +00:00
|
|
|
t << "####### Install\n\n";
|
2012-09-06 10:21:38 +00:00
|
|
|
writeInstalls(t);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2013-07-04 09:25:16 +00:00
|
|
|
t << "FORCE:\n\n";
|
2011-04-27 10:05:43 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-06-26 13:29:35 +00:00
|
|
|
QString MakefileGenerator::fixifySpecdir(const QString &spec, const QString &outdir)
|
|
|
|
{
|
|
|
|
if (QFileInfo(spec).isAbsolute())
|
|
|
|
return fileFixify(spec, outdir);
|
|
|
|
return spec;
|
|
|
|
}
|
|
|
|
|
2012-08-09 16:54:40 +00:00
|
|
|
QString MakefileGenerator::buildArgs()
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
|
|
|
QString ret;
|
2012-08-09 16:54:40 +00:00
|
|
|
|
|
|
|
foreach (const QString &arg, Option::qmake_args)
|
|
|
|
ret += " " + escapeFilePath(arg);
|
2011-04-27 10:05:43 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
//could get stored argv, but then it would have more options than are
|
|
|
|
//probably necesary this will try to guess the bare minimum..
|
|
|
|
QString MakefileGenerator::build_args(const QString &outdir)
|
|
|
|
{
|
|
|
|
QString ret = "$(QMAKE)";
|
|
|
|
|
|
|
|
// general options and arguments
|
2012-08-09 16:54:40 +00:00
|
|
|
ret += buildArgs();
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
//output
|
|
|
|
QString ofile = Option::fixPathToTargetOS(fileFixify(Option::output.fileName()));
|
|
|
|
if(!ofile.isEmpty() && ofile != project->first("QMAKE_MAKEFILE"))
|
|
|
|
ret += " -o " + escapeFilePath(ofile);
|
|
|
|
|
|
|
|
//inputs
|
|
|
|
ret += " " + escapeFilePath(fileFixify(project->projectFile(), outdir));
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
MakefileGenerator::writeHeader(QTextStream &t)
|
|
|
|
{
|
2013-07-04 09:25:16 +00:00
|
|
|
t << "#############################################################################\n";
|
2011-04-27 10:05:43 +00:00
|
|
|
t << "# Makefile for building: " << escapeFilePath(var("TARGET")) << endl;
|
2013-07-11 13:14:13 +00:00
|
|
|
t << "# Generated by qmake (" QMAKE_VERSION_STR ") (Qt " QT_VERSION_STR ")\n";
|
2011-04-27 10:05:43 +00:00
|
|
|
t << "# Project: " << fileFixify(project->projectFile()) << endl;
|
|
|
|
t << "# Template: " << var("TEMPLATE") << endl;
|
|
|
|
if(!project->isActiveConfig("build_pass"))
|
|
|
|
t << "# Command: " << build_args().replace("$(QMAKE)", var("QMAKE_QMAKE")) << endl;
|
2013-07-04 09:25:16 +00:00
|
|
|
t << "#############################################################################\n";
|
2011-04-27 10:05:43 +00:00
|
|
|
t << endl;
|
2012-12-04 20:17:24 +00:00
|
|
|
QString ofile = Option::fixPathToTargetOS(Option::output.fileName());
|
|
|
|
if (ofile.lastIndexOf(Option::dir_sep) != -1)
|
|
|
|
ofile.remove(0, ofile.lastIndexOf(Option::dir_sep) +1);
|
|
|
|
t << "MAKEFILE = " << ofile << endl << endl;
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QList<MakefileGenerator::SubTarget*>
|
|
|
|
MakefileGenerator::findSubDirsSubTargets() const
|
|
|
|
{
|
|
|
|
QList<SubTarget*> targets;
|
|
|
|
{
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &subdirs = project->values("SUBDIRS");
|
2011-04-27 10:05:43 +00:00
|
|
|
for(int subdir = 0; subdir < subdirs.size(); ++subdir) {
|
2012-09-06 10:21:38 +00:00
|
|
|
ProString ofile = subdirs[subdir];
|
|
|
|
QString oname = ofile.toQString();
|
|
|
|
QString fixedSubdir = oname;
|
2011-04-27 10:05:43 +00:00
|
|
|
fixedSubdir = fixedSubdir.replace(QRegExp("[^a-zA-Z0-9_]"),"-");
|
|
|
|
|
|
|
|
SubTarget *st = new SubTarget;
|
2012-09-06 10:21:38 +00:00
|
|
|
st->name = oname;
|
2011-04-27 10:05:43 +00:00
|
|
|
targets.append(st);
|
|
|
|
|
|
|
|
bool fromFile = false;
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProKey fkey(fixedSubdir + ".file");
|
|
|
|
const ProKey skey(fixedSubdir + ".subdir");
|
|
|
|
if (!project->isEmpty(fkey)) {
|
|
|
|
if (!project->isEmpty(skey))
|
2011-04-27 10:05:43 +00:00
|
|
|
warn_msg(WarnLogic, "Cannot assign both file and subdir for subdir %s",
|
|
|
|
subdirs[subdir].toLatin1().constData());
|
2012-09-06 10:21:38 +00:00
|
|
|
ofile = project->first(fkey);
|
2011-04-27 10:05:43 +00:00
|
|
|
fromFile = true;
|
2012-09-06 10:21:38 +00:00
|
|
|
} else if (!project->isEmpty(skey)) {
|
|
|
|
ofile = project->first(skey);
|
2011-04-27 10:05:43 +00:00
|
|
|
fromFile = false;
|
|
|
|
} else {
|
2012-09-06 10:21:38 +00:00
|
|
|
fromFile = ofile.endsWith(Option::pro_ext);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
2012-09-06 10:21:38 +00:00
|
|
|
QString file = Option::fixPathToTargetOS(ofile.toQString());
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
if(fromFile) {
|
|
|
|
int slsh = file.lastIndexOf(Option::dir_sep);
|
|
|
|
if(slsh != -1) {
|
|
|
|
st->in_directory = file.left(slsh+1);
|
|
|
|
st->profile = file.mid(slsh+1);
|
|
|
|
} else {
|
|
|
|
st->profile = file;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if(!file.isEmpty() && !project->isActiveConfig("subdir_first_pro"))
|
|
|
|
st->profile = file.section(Option::dir_sep, -1) + Option::pro_ext;
|
|
|
|
st->in_directory = file;
|
|
|
|
}
|
|
|
|
while(st->in_directory.endsWith(Option::dir_sep))
|
|
|
|
st->in_directory.chop(1);
|
|
|
|
if(fileInfo(st->in_directory).isRelative())
|
|
|
|
st->out_directory = st->in_directory;
|
|
|
|
else
|
|
|
|
st->out_directory = fileFixify(st->in_directory, qmake_getpwd(), Option::output_dir);
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProKey mkey(fixedSubdir + ".makefile");
|
|
|
|
if (!project->isEmpty(mkey)) {
|
|
|
|
st->makefile = project->first(mkey).toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
} else {
|
2012-05-16 12:54:21 +00:00
|
|
|
st->makefile = "Makefile";
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!st->profile.isEmpty()) {
|
|
|
|
QString basename = st->in_directory;
|
|
|
|
int new_slsh = basename.lastIndexOf(Option::dir_sep);
|
|
|
|
if(new_slsh != -1)
|
|
|
|
basename = basename.mid(new_slsh+1);
|
|
|
|
if(st->profile != basename + Option::pro_ext)
|
|
|
|
st->makefile += "." + st->profile.left(st->profile.length() - Option::pro_ext.length());
|
|
|
|
}
|
|
|
|
}
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProKey dkey(fixedSubdir + ".depends");
|
|
|
|
if (!project->isEmpty(dkey)) {
|
|
|
|
const ProStringList &depends = project->values(dkey);
|
2011-04-27 10:05:43 +00:00
|
|
|
for(int depend = 0; depend < depends.size(); ++depend) {
|
|
|
|
bool found = false;
|
|
|
|
for(int subDep = 0; subDep < subdirs.size(); ++subDep) {
|
|
|
|
if(subdirs[subDep] == depends.at(depend)) {
|
2012-09-06 10:21:38 +00:00
|
|
|
QString subName = subdirs[subDep].toQString();
|
|
|
|
QString fixedSubDep = subName;
|
2011-04-27 10:05:43 +00:00
|
|
|
fixedSubDep = fixedSubDep.replace(QRegExp("[^a-zA-Z0-9_]"),"-");
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProKey dtkey(fixedSubDep + ".target");
|
|
|
|
if (!project->isEmpty(dtkey)) {
|
|
|
|
st->depends += project->first(dtkey);
|
2011-04-27 10:05:43 +00:00
|
|
|
} else {
|
2012-09-06 10:21:38 +00:00
|
|
|
QString d = Option::fixPathToLocalOS(subName);
|
|
|
|
const ProKey dfkey(fixedSubDep + ".file");
|
|
|
|
if (!project->isEmpty(dfkey)) {
|
|
|
|
d = project->first(dfkey).toQString();
|
|
|
|
} else {
|
|
|
|
const ProKey dskey(fixedSubDep + ".subdir");
|
|
|
|
if (!project->isEmpty(dskey))
|
|
|
|
d = project->first(dskey).toQString();
|
|
|
|
}
|
2011-04-27 10:05:43 +00:00
|
|
|
st->depends += "sub-" + d.replace(QRegExp("[^a-zA-Z0-9_]"),"-");
|
|
|
|
}
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!found) {
|
2012-09-06 10:21:38 +00:00
|
|
|
QString depend_str = depends.at(depend).toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
st->depends += depend_str.replace(QRegExp("[^a-zA-Z0-9_]"),"-");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProKey tkey(fixedSubdir + ".target");
|
|
|
|
if (!project->isEmpty(tkey)) {
|
|
|
|
st->target = project->first(tkey).toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
} else {
|
|
|
|
st->target = "sub-" + file;
|
|
|
|
st->target = st->target.replace(QRegExp("[^a-zA-Z0-9_]"),"-");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return targets;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
MakefileGenerator::writeSubDirs(QTextStream &t)
|
|
|
|
{
|
|
|
|
QList<SubTarget*> targets = findSubDirsSubTargets();
|
2013-07-04 09:25:16 +00:00
|
|
|
t << "first: make_first\n";
|
2011-04-27 10:05:43 +00:00
|
|
|
int flags = SubTargetInstalls;
|
|
|
|
if(project->isActiveConfig("ordered"))
|
|
|
|
flags |= SubTargetOrdered;
|
|
|
|
writeSubTargets(t, targets, flags);
|
|
|
|
qDeleteAll(targets);
|
|
|
|
}
|
|
|
|
|
2011-05-03 07:52:30 +00:00
|
|
|
void MakefileGenerator::writeSubMakeCall(QTextStream &t, const QString &callPrefix,
|
2012-04-25 15:12:53 +00:00
|
|
|
const QString &makeArguments)
|
2011-05-03 07:52:30 +00:00
|
|
|
{
|
2012-04-25 15:12:53 +00:00
|
|
|
t << callPrefix << "$(MAKE)" << makeArguments << endl;
|
2011-05-03 07:52:30 +00:00
|
|
|
}
|
|
|
|
|
2012-05-18 20:13:51 +00:00
|
|
|
void
|
|
|
|
MakefileGenerator::writeSubTargetCall(QTextStream &t,
|
|
|
|
const QString &in_directory, const QString &in, const QString &out_directory, const QString &out,
|
2012-04-25 15:12:53 +00:00
|
|
|
const QString &out_directory_cdin, const QString &makefilein)
|
2012-05-18 20:13:51 +00:00
|
|
|
{
|
|
|
|
QString pfx;
|
|
|
|
if (!in.isEmpty()) {
|
|
|
|
if (!in_directory.isEmpty())
|
|
|
|
t << "\n\t" << mkdir_p_asstring(out_directory);
|
2013-02-28 11:40:16 +00:00
|
|
|
pfx = "( " + chkexists.arg(out) +
|
|
|
|
+ " $(QMAKE) " + in + buildArgs() + " -o " + out
|
2012-05-18 20:13:51 +00:00
|
|
|
+ " ) && ";
|
|
|
|
}
|
2012-04-25 15:12:53 +00:00
|
|
|
writeSubMakeCall(t, out_directory_cdin + pfx, makefilein);
|
2012-05-18 20:13:51 +00:00
|
|
|
}
|
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
void
|
|
|
|
MakefileGenerator::writeSubTargets(QTextStream &t, QList<MakefileGenerator::SubTarget*> targets, int flags)
|
|
|
|
{
|
|
|
|
// blasted includes
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &qeui = project->values("QMAKE_EXTRA_INCLUDES");
|
|
|
|
for (ProStringList::ConstIterator qeui_it = qeui.begin(); qeui_it != qeui.end(); ++qeui_it)
|
2011-04-27 10:05:43 +00:00
|
|
|
t << "include " << (*qeui_it) << endl;
|
|
|
|
|
|
|
|
if (!(flags & SubTargetSkipDefaultVariables)) {
|
|
|
|
/* Calling Option::fixPathToTargetOS() is necessary for MinGW/MSYS, which requires
|
|
|
|
* back-slashes to be turned into slashes. */
|
|
|
|
t << "QMAKE = " << var("QMAKE_QMAKE") << endl;
|
|
|
|
t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl;
|
|
|
|
t << "CHK_DIR_EXISTS= " << var("QMAKE_CHK_DIR_EXISTS") << endl;
|
|
|
|
t << "MKDIR = " << var("QMAKE_MKDIR") << endl;
|
|
|
|
t << "COPY = " << var("QMAKE_COPY") << endl;
|
|
|
|
t << "COPY_FILE = " << var("QMAKE_COPY_FILE") << endl;
|
|
|
|
t << "COPY_DIR = " << var("QMAKE_COPY_DIR") << endl;
|
|
|
|
t << "INSTALL_FILE = " << var("QMAKE_INSTALL_FILE") << endl;
|
|
|
|
t << "INSTALL_PROGRAM = " << var("QMAKE_INSTALL_PROGRAM") << endl;
|
|
|
|
t << "INSTALL_DIR = " << var("QMAKE_INSTALL_DIR") << endl;
|
|
|
|
t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl;
|
|
|
|
t << "SYMLINK = " << var("QMAKE_SYMBOLIC_LINK") << endl;
|
|
|
|
t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl;
|
|
|
|
t << "MOVE = " << var("QMAKE_MOVE") << endl;
|
|
|
|
t << "SUBTARGETS = "; // subtargets are sub-directory
|
|
|
|
for(int target = 0; target < targets.size(); ++target)
|
|
|
|
t << " \\\n\t\t" << targets.at(target)->target;
|
|
|
|
t << endl << endl;
|
|
|
|
}
|
|
|
|
writeExtraVariables(t);
|
|
|
|
|
|
|
|
QStringList targetSuffixes;
|
2012-09-06 10:21:38 +00:00
|
|
|
const QString abs_source_path = project->first("QMAKE_ABSOLUTE_SOURCE_PATH").toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
if (!(flags & SubTargetSkipDefaultTargets)) {
|
2010-02-01 17:16:39 +00:00
|
|
|
targetSuffixes << "make_first" << "all" << "clean" << "distclean"
|
2011-04-27 10:05:43 +00:00
|
|
|
<< QString((flags & SubTargetInstalls) ? "install_subtargets" : "install")
|
|
|
|
<< QString((flags & SubTargetInstalls) ? "uninstall_subtargets" : "uninstall");
|
|
|
|
}
|
|
|
|
|
2012-05-18 14:59:22 +00:00
|
|
|
bool dont_recurse = project->isActiveConfig("dont_recurse");
|
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
// generate target rules
|
|
|
|
for(int target = 0; target < targets.size(); ++target) {
|
|
|
|
SubTarget *subtarget = targets.at(target);
|
|
|
|
QString in_directory = subtarget->in_directory;
|
|
|
|
if(!in_directory.isEmpty() && !in_directory.endsWith(Option::dir_sep))
|
|
|
|
in_directory += Option::dir_sep;
|
|
|
|
QString out_directory = subtarget->out_directory;
|
|
|
|
if(!out_directory.isEmpty() && !out_directory.endsWith(Option::dir_sep))
|
|
|
|
out_directory += Option::dir_sep;
|
|
|
|
if(!abs_source_path.isEmpty() && out_directory.startsWith(abs_source_path))
|
|
|
|
out_directory = Option::output_dir + out_directory.mid(abs_source_path.length());
|
|
|
|
|
2012-04-25 15:12:53 +00:00
|
|
|
QString out_directory_cdin = out_directory.isEmpty() ? "\n\t"
|
|
|
|
: "\n\tcd " + out_directory + " && ";
|
2012-05-18 14:59:22 +00:00
|
|
|
QString makefilein = " -f " + subtarget->makefile;
|
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
//qmake it
|
2012-05-18 20:13:51 +00:00
|
|
|
QString out;
|
|
|
|
QString in;
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!subtarget->profile.isEmpty()) {
|
2012-05-18 20:13:51 +00:00
|
|
|
out = subtarget->makefile;
|
|
|
|
in = escapeFilePath(fileFixify(in_directory + subtarget->profile, FileFixifyAbsolute));
|
2011-04-27 10:05:43 +00:00
|
|
|
if(out.startsWith(in_directory))
|
|
|
|
out = out.mid(in_directory.length());
|
|
|
|
t << subtarget->target << "-qmake_all: ";
|
2012-05-30 10:33:34 +00:00
|
|
|
if (flags & SubTargetOrdered) {
|
|
|
|
if (target)
|
|
|
|
t << targets.at(target - 1)->target << "-qmake_all";
|
|
|
|
} else {
|
|
|
|
if (!subtarget->depends.isEmpty())
|
|
|
|
t << valGlue(subtarget->depends, QString(), "-qmake_all ", "-qmake_all");
|
|
|
|
}
|
2012-04-25 15:12:53 +00:00
|
|
|
t << " FORCE\n\t";
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!in_directory.isEmpty()) {
|
|
|
|
t << mkdir_p_asstring(out_directory)
|
2012-04-25 15:12:53 +00:00
|
|
|
<< out_directory_cdin;
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
2012-08-09 16:54:40 +00:00
|
|
|
t << "$(QMAKE) " << in << buildArgs() << " -o " << out;
|
2012-05-18 14:59:22 +00:00
|
|
|
if (!dont_recurse)
|
2012-04-25 15:12:53 +00:00
|
|
|
writeSubMakeCall(t, out_directory_cdin, makefilein + " qmake_all");
|
2012-05-18 14:59:22 +00:00
|
|
|
else
|
|
|
|
t << endl;
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
{ //actually compile
|
2012-05-18 20:13:51 +00:00
|
|
|
t << subtarget->target << ":";
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!subtarget->depends.isEmpty())
|
|
|
|
t << " " << valList(subtarget->depends);
|
2012-04-25 15:12:53 +00:00
|
|
|
t << " FORCE";
|
2012-05-18 20:13:51 +00:00
|
|
|
writeSubTargetCall(t, in_directory, in, out_directory, out,
|
2012-04-25 15:12:53 +00:00
|
|
|
out_directory_cdin, makefilein);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for(int suffix = 0; suffix < targetSuffixes.size(); ++suffix) {
|
|
|
|
QString s = targetSuffixes.at(suffix);
|
|
|
|
if(s == "install_subtargets")
|
|
|
|
s = "install";
|
|
|
|
else if(s == "uninstall_subtargets")
|
|
|
|
s = "uninstall";
|
|
|
|
else if(s == "make_first")
|
|
|
|
s = QString();
|
|
|
|
|
|
|
|
if(flags & SubTargetOrdered) {
|
2012-05-18 20:13:51 +00:00
|
|
|
t << subtarget->target << "-" << targetSuffixes.at(suffix) << "-ordered:";
|
2011-04-27 10:05:43 +00:00
|
|
|
if(target)
|
|
|
|
t << " " << targets.at(target-1)->target << "-" << targetSuffixes.at(suffix) << "-ordered ";
|
2012-04-25 15:12:53 +00:00
|
|
|
t << " FORCE";
|
2012-05-18 20:13:51 +00:00
|
|
|
writeSubTargetCall(t, in_directory, in, out_directory, out,
|
2012-04-25 15:12:53 +00:00
|
|
|
out_directory_cdin, makefilein + " " + s);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
2012-05-18 20:13:51 +00:00
|
|
|
t << subtarget->target << "-" << targetSuffixes.at(suffix) << ":";
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!subtarget->depends.isEmpty())
|
|
|
|
t << " " << valGlue(subtarget->depends, QString(), "-" + targetSuffixes.at(suffix) + " ",
|
|
|
|
"-"+targetSuffixes.at(suffix));
|
2012-04-25 15:12:53 +00:00
|
|
|
t << " FORCE";
|
2012-05-18 20:13:51 +00:00
|
|
|
writeSubTargetCall(t, in_directory, in, out_directory, out,
|
2012-04-25 15:12:53 +00:00
|
|
|
out_directory_cdin, makefilein + " " + s);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
t << endl;
|
|
|
|
|
|
|
|
if (!(flags & SubTargetSkipDefaultTargets)) {
|
2012-05-18 14:59:22 +00:00
|
|
|
writeMakeQmake(t, true);
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
t << "qmake_all:";
|
|
|
|
if(!targets.isEmpty()) {
|
|
|
|
for(QList<SubTarget*>::Iterator it = targets.begin(); it != targets.end(); ++it) {
|
|
|
|
if(!(*it)->profile.isEmpty())
|
2013-07-04 09:25:16 +00:00
|
|
|
t << " " << (*it)->target << "-qmake_all";
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
2013-07-04 09:25:16 +00:00
|
|
|
t << " FORCE\n\n";
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for(int s = 0; s < targetSuffixes.size(); ++s) {
|
|
|
|
QString suffix = targetSuffixes.at(s);
|
|
|
|
if(!(flags & SubTargetInstalls) && suffix.endsWith("install"))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
t << suffix << ":";
|
|
|
|
for(int target = 0; target < targets.size(); ++target) {
|
|
|
|
SubTarget *subTarget = targets.at(target);
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &config = project->values(ProKey(subTarget->name + ".CONFIG"));
|
2010-02-01 17:16:39 +00:00
|
|
|
if (suffix == "make_first"
|
2012-09-06 10:21:38 +00:00
|
|
|
&& config.indexOf("no_default_target") != -1) {
|
2011-04-27 10:05:43 +00:00
|
|
|
continue;
|
|
|
|
}
|
2011-02-24 19:01:18 +00:00
|
|
|
if((suffix == "install_subtargets" || suffix == "uninstall_subtargets")
|
2012-09-06 10:21:38 +00:00
|
|
|
&& config.indexOf("no_default_install") != -1) {
|
2011-02-24 19:01:18 +00:00
|
|
|
continue;
|
|
|
|
}
|
2011-04-27 10:05:43 +00:00
|
|
|
QString targetRule = subTarget->target + "-" + suffix;
|
|
|
|
if(flags & SubTargetOrdered)
|
|
|
|
targetRule += "-ordered";
|
|
|
|
t << " " << targetRule;
|
|
|
|
}
|
|
|
|
if(suffix == "all" || suffix == "make_first")
|
|
|
|
t << varGlue("ALL_DEPS"," "," ","");
|
|
|
|
if(suffix == "clean")
|
|
|
|
t << varGlue("CLEAN_DEPS"," "," ","");
|
2013-07-04 09:25:16 +00:00
|
|
|
t << " FORCE\n";
|
2011-04-27 10:05:43 +00:00
|
|
|
if(suffix == "clean") {
|
2012-07-12 10:08:42 +00:00
|
|
|
t << fileVarGlue("QMAKE_CLEAN", "\t-$(DEL_FILE) ", "\n\t-$(DEL_FILE) ", "\n");
|
2011-04-27 10:05:43 +00:00
|
|
|
} else if(suffix == "distclean") {
|
|
|
|
QString ofile = Option::fixPathToTargetOS(fileFixify(Option::output.fileName()));
|
|
|
|
if(!ofile.isEmpty())
|
|
|
|
t << "\t-$(DEL_FILE) " << ofile << endl;
|
2012-07-12 10:08:42 +00:00
|
|
|
t << fileVarGlue("QMAKE_DISTCLEAN", "\t-$(DEL_FILE) ", " ", "\n");
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// user defined targets
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &qut = project->values("QMAKE_EXTRA_TARGETS");
|
|
|
|
for (ProStringList::ConstIterator qut_it = qut.begin(); qut_it != qut.end(); ++qut_it) {
|
|
|
|
const ProStringList &config = project->values(ProKey(*qut_it + ".CONFIG"));
|
|
|
|
QString targ = var(ProKey(*qut_it + ".target")),
|
|
|
|
cmd = var(ProKey(*qut_it + ".commands")), deps;
|
2011-04-27 10:05:43 +00:00
|
|
|
if(targ.isEmpty())
|
2012-09-06 10:21:38 +00:00
|
|
|
targ = (*qut_it).toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
t << endl;
|
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &deplist = project->values(ProKey(*qut_it + ".depends"));
|
|
|
|
for (ProStringList::ConstIterator dep_it = deplist.begin(); dep_it != deplist.end(); ++dep_it) {
|
|
|
|
QString dep = var(ProKey(*dep_it + ".target"));
|
2011-04-27 10:05:43 +00:00
|
|
|
if(dep.isEmpty())
|
2012-09-06 10:21:38 +00:00
|
|
|
dep = Option::fixPathToTargetOS((*dep_it).toQString(), false);
|
2011-04-27 10:05:43 +00:00
|
|
|
deps += " " + dep;
|
|
|
|
}
|
2012-09-06 10:21:38 +00:00
|
|
|
if (config.indexOf("recursive") != -1) {
|
2011-04-27 10:05:43 +00:00
|
|
|
QSet<QString> recurse;
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProKey rkey(*qut_it + ".recurse");
|
|
|
|
if (project->isSet(rkey)) {
|
|
|
|
recurse = project->values(rkey).toQStringList().toSet();
|
2011-04-27 10:05:43 +00:00
|
|
|
} else {
|
|
|
|
for(int target = 0; target < targets.size(); ++target)
|
|
|
|
recurse.insert(targets.at(target)->name);
|
|
|
|
}
|
|
|
|
for(int target = 0; target < targets.size(); ++target) {
|
|
|
|
SubTarget *subtarget = targets.at(target);
|
|
|
|
QString in_directory = subtarget->in_directory;
|
|
|
|
if(!in_directory.isEmpty() && !in_directory.endsWith(Option::dir_sep))
|
|
|
|
in_directory += Option::dir_sep;
|
|
|
|
QString out_directory = subtarget->out_directory;
|
|
|
|
if(!out_directory.isEmpty() && !out_directory.endsWith(Option::dir_sep))
|
|
|
|
out_directory += Option::dir_sep;
|
|
|
|
if(!abs_source_path.isEmpty() && out_directory.startsWith(abs_source_path))
|
|
|
|
out_directory = Option::output_dir + out_directory.mid(abs_source_path.length());
|
|
|
|
|
|
|
|
if(!recurse.contains(subtarget->name))
|
|
|
|
continue;
|
2012-05-18 20:13:51 +00:00
|
|
|
|
2012-04-25 15:12:53 +00:00
|
|
|
QString out_directory_cdin = out_directory.isEmpty() ? "\n\t"
|
|
|
|
: "\n\tcd " + out_directory + " && ";
|
2011-05-12 07:45:55 +00:00
|
|
|
QString makefilein = " -f " + subtarget->makefile;
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-05-18 20:13:51 +00:00
|
|
|
QString out;
|
|
|
|
QString in;
|
|
|
|
if (!subtarget->profile.isEmpty()) {
|
|
|
|
out = subtarget->makefile;
|
|
|
|
in = escapeFilePath(fileFixify(in_directory + subtarget->profile, FileFixifyAbsolute));
|
|
|
|
if (out.startsWith(in_directory))
|
|
|
|
out = out.mid(in_directory.length());
|
|
|
|
}
|
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
//write the rule/depends
|
|
|
|
if(flags & SubTargetOrdered) {
|
|
|
|
const QString dep = subtarget->target + "-" + (*qut_it) + "_ordered";
|
2012-05-18 20:13:51 +00:00
|
|
|
t << dep << ":";
|
2011-04-27 10:05:43 +00:00
|
|
|
if(target)
|
|
|
|
t << " " << targets.at(target-1)->target << "-" << (*qut_it) << "_ordered ";
|
|
|
|
deps += " " + dep;
|
|
|
|
} else {
|
|
|
|
const QString dep = subtarget->target + "-" + (*qut_it);
|
2012-05-18 20:13:51 +00:00
|
|
|
t << dep << ":";
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!subtarget->depends.isEmpty())
|
|
|
|
t << " " << valGlue(subtarget->depends, QString(), "-" + (*qut_it) + " ", "-" + (*qut_it));
|
|
|
|
deps += " " + dep;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString sub_targ = targ;
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProKey rtkey(*qut_it + ".recurse_target");
|
|
|
|
if (project->isSet(rtkey))
|
|
|
|
sub_targ = project->first(rtkey).toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
//write the commands
|
2012-05-18 20:13:51 +00:00
|
|
|
writeSubTargetCall(t, in_directory, in, out_directory, out,
|
2012-04-25 15:12:53 +00:00
|
|
|
out_directory_cdin, makefilein + " " + sub_targ);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
2012-09-06 10:21:38 +00:00
|
|
|
if (config.indexOf("phony") != -1)
|
2011-04-27 10:05:43 +00:00
|
|
|
deps += " FORCE";
|
|
|
|
t << targ << ":" << deps << "\n";
|
|
|
|
if(!cmd.isEmpty())
|
|
|
|
t << "\t" << cmd << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(flags & SubTargetInstalls) {
|
|
|
|
project->values("INSTALLDEPS") += "install_subtargets";
|
|
|
|
project->values("UNINSTALLDEPS") += "uninstall_subtargets";
|
2012-09-06 10:21:38 +00:00
|
|
|
writeInstalls(t, true);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
2013-07-04 09:25:16 +00:00
|
|
|
t << "FORCE:\n\n";
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-05-18 14:59:22 +00:00
|
|
|
MakefileGenerator::writeMakeQmake(QTextStream &t, bool noDummyQmakeAll)
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
|
|
|
QString ofile = Option::fixPathToTargetOS(fileFixify(Option::output.fileName()));
|
|
|
|
if(project->isEmpty("QMAKE_FAILED_REQUIREMENTS") && !project->isEmpty("QMAKE_INTERNAL_PRL_FILE")) {
|
|
|
|
QStringList files = fileFixify(Option::mkfile::project_files);
|
2013-07-04 09:25:16 +00:00
|
|
|
t << escapeDependencyPath(project->first("QMAKE_INTERNAL_PRL_FILE").toQString()) << ": \n\t"
|
2012-05-18 18:00:23 +00:00
|
|
|
<< "@$(QMAKE) -prl " << buildArgs() << " " << files.join(' ') << endl;
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QString qmake = build_args();
|
|
|
|
if(!ofile.isEmpty() && !project->isActiveConfig("no_autoqmake")) {
|
2012-08-28 08:12:36 +00:00
|
|
|
t << escapeFilePath(ofile) << ": "
|
|
|
|
<< escapeDependencyPath(fileFixify(project->projectFile())) << " ";
|
2012-09-05 16:29:19 +00:00
|
|
|
if (Option::globals->do_cache) {
|
2012-05-10 09:22:07 +00:00
|
|
|
if (!project->confFile().isEmpty())
|
|
|
|
t << escapeDependencyPath(fileFixify(project->confFile())) << " ";
|
|
|
|
if (!project->cacheFile().isEmpty())
|
|
|
|
t << escapeDependencyPath(fileFixify(project->cacheFile())) << " ";
|
|
|
|
}
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!specdir().isEmpty()) {
|
|
|
|
if(exists(Option::fixPathToLocalOS(specdir()+QDir::separator()+"qmake.conf")))
|
|
|
|
t << escapeDependencyPath(specdir() + Option::dir_sep + "qmake.conf") << " ";
|
|
|
|
}
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &included = project->values("QMAKE_INTERNAL_INCLUDED_FILES");
|
2011-04-27 10:05:43 +00:00
|
|
|
t << escapeDependencyPaths(included).join(" \\\n\t\t") << "\n\t"
|
|
|
|
<< qmake << endl;
|
|
|
|
for(int include = 0; include < included.size(); ++include) {
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProString &i = included.at(include);
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!i.isEmpty())
|
2013-07-04 09:25:16 +00:00
|
|
|
t << i << ":\n";
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if(project->first("QMAKE_ORIG_TARGET") != "qmake") {
|
2012-04-25 15:12:53 +00:00
|
|
|
t << "qmake: FORCE\n\t@" << qmake << endl << endl;
|
|
|
|
if (!noDummyQmakeAll)
|
2013-07-04 09:25:16 +00:00
|
|
|
t << "qmake_all: FORCE\n\n";
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QFileInfo
|
|
|
|
MakefileGenerator::fileInfo(QString file) const
|
|
|
|
{
|
|
|
|
static QHash<FileInfoCacheKey, QFileInfo> *cache = 0;
|
|
|
|
static QFileInfo noInfo = QFileInfo();
|
|
|
|
if(!cache) {
|
|
|
|
cache = new QHash<FileInfoCacheKey, QFileInfo>;
|
|
|
|
qmakeAddCacheClear(qmakeDeleteCacheClear<QHash<FileInfoCacheKey, QFileInfo> >, (void**)&cache);
|
|
|
|
}
|
|
|
|
FileInfoCacheKey cacheKey(file);
|
|
|
|
QFileInfo value = cache->value(cacheKey, noInfo);
|
|
|
|
if (value != noInfo)
|
|
|
|
return value;
|
|
|
|
|
|
|
|
QFileInfo fi(file);
|
|
|
|
if (fi.exists())
|
|
|
|
cache->insert(cacheKey, fi);
|
|
|
|
return fi;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString
|
|
|
|
MakefileGenerator::unescapeFilePath(const QString &path) const
|
|
|
|
{
|
|
|
|
QString ret = path;
|
2013-07-17 14:44:18 +00:00
|
|
|
ret.replace(QLatin1String("\\ "), QLatin1String(" "));
|
|
|
|
ret.remove(QLatin1Char('\"'));
|
2011-04-27 10:05:43 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
ProString
|
|
|
|
MakefileGenerator::unescapeFilePath(const ProString &path) const
|
|
|
|
{
|
|
|
|
return ProString(unescapeFilePath(path.toQString()));
|
|
|
|
}
|
|
|
|
|
|
|
|
ProString
|
|
|
|
MakefileGenerator::escapeFilePath(const ProString &path) const
|
|
|
|
{
|
|
|
|
return ProString(escapeFilePath(path.toQString()));
|
|
|
|
}
|
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
QStringList
|
|
|
|
MakefileGenerator::escapeFilePaths(const QStringList &paths) const
|
|
|
|
{
|
|
|
|
QStringList ret;
|
|
|
|
for(int i = 0; i < paths.size(); ++i)
|
|
|
|
ret.append(escapeFilePath(paths.at(i)));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList
|
|
|
|
MakefileGenerator::escapeFilePaths(const ProStringList &paths) const
|
|
|
|
{
|
|
|
|
ProStringList ret;
|
|
|
|
for (int i = 0; i < paths.size(); ++i)
|
|
|
|
ret.append(escapeFilePath(paths.at(i)));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
QStringList
|
|
|
|
MakefileGenerator::escapeDependencyPaths(const QStringList &paths) const
|
|
|
|
{
|
|
|
|
QStringList ret;
|
|
|
|
for(int i = 0; i < paths.size(); ++i)
|
|
|
|
ret.append(escapeDependencyPath(paths.at(i)));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList
|
|
|
|
MakefileGenerator::escapeDependencyPaths(const ProStringList &paths) const
|
|
|
|
{
|
|
|
|
ProStringList ret;
|
|
|
|
for (int i = 0; i < paths.size(); ++i)
|
|
|
|
ret.append(escapeDependencyPath(paths.at(i).toQString()));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
QStringList
|
|
|
|
MakefileGenerator::unescapeFilePaths(const QStringList &paths) const
|
|
|
|
{
|
|
|
|
QStringList ret;
|
|
|
|
for(int i = 0; i < paths.size(); ++i)
|
|
|
|
ret.append(unescapeFilePath(paths.at(i)));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList
|
|
|
|
MakefileGenerator::unescapeFilePaths(const ProStringList &paths) const
|
|
|
|
{
|
|
|
|
ProStringList ret;
|
|
|
|
for (int i = 0; i < paths.size(); ++i)
|
|
|
|
ret.append(unescapeFilePath(paths.at(i)));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
QStringList
|
|
|
|
MakefileGenerator::fileFixify(const QStringList& files, const QString &out_dir, const QString &in_dir,
|
|
|
|
FileFixifyType fix, bool canon) const
|
|
|
|
{
|
|
|
|
if(files.isEmpty())
|
|
|
|
return files;
|
|
|
|
QStringList ret;
|
|
|
|
for(QStringList::ConstIterator it = files.begin(); it != files.end(); ++it) {
|
|
|
|
if(!(*it).isEmpty())
|
|
|
|
ret << fileFixify((*it), out_dir, in_dir, fix, canon);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString
|
|
|
|
MakefileGenerator::fileFixify(const QString& file, const QString &out_d, const QString &in_d,
|
|
|
|
FileFixifyType fix, bool canon) const
|
|
|
|
{
|
|
|
|
if(file.isEmpty())
|
|
|
|
return file;
|
|
|
|
QString ret = unescapeFilePath(file);
|
|
|
|
|
|
|
|
//do the fixin'
|
|
|
|
QString orig_file = ret;
|
|
|
|
if(ret.startsWith(QLatin1Char('~'))) {
|
|
|
|
if(ret.startsWith(QLatin1String("~/")))
|
|
|
|
ret = QDir::homePath() + ret.mid(1);
|
|
|
|
else
|
|
|
|
warn_msg(WarnLogic, "Unable to expand ~ in %s", ret.toLatin1().constData());
|
|
|
|
}
|
|
|
|
if(fix == FileFixifyAbsolute || (fix == FileFixifyDefault && project->isActiveConfig("no_fixpath"))) {
|
|
|
|
if(fix == FileFixifyAbsolute && QDir::isRelativePath(ret)) { //already absolute
|
|
|
|
QString pwd = qmake_getpwd();
|
|
|
|
if (!pwd.endsWith(QLatin1Char('/')))
|
|
|
|
pwd += QLatin1Char('/');
|
|
|
|
ret.prepend(pwd);
|
|
|
|
}
|
|
|
|
ret = Option::fixPathToTargetOS(ret, false, canon);
|
|
|
|
} else { //fix it..
|
|
|
|
QString out_dir = QDir(Option::output_dir).absoluteFilePath(out_d);
|
|
|
|
QString in_dir = QDir(qmake_getpwd()).absoluteFilePath(in_d);
|
|
|
|
{
|
|
|
|
QFileInfo in_fi(fileInfo(in_dir));
|
|
|
|
if(in_fi.exists())
|
|
|
|
in_dir = in_fi.canonicalFilePath();
|
|
|
|
QFileInfo out_fi(fileInfo(out_dir));
|
|
|
|
if(out_fi.exists())
|
|
|
|
out_dir = out_fi.canonicalFilePath();
|
|
|
|
}
|
|
|
|
|
|
|
|
QString qfile(Option::fixPathToLocalOS(ret, true, canon));
|
|
|
|
QFileInfo qfileinfo(fileInfo(qfile));
|
|
|
|
if(out_dir != in_dir || !qfileinfo.isRelative()) {
|
|
|
|
if(qfileinfo.isRelative()) {
|
|
|
|
ret = in_dir + "/" + qfile;
|
|
|
|
qfileinfo.setFile(ret);
|
|
|
|
}
|
|
|
|
ret = Option::fixPathToTargetOS(ret, false, canon);
|
|
|
|
if(canon && qfileinfo.exists() &&
|
|
|
|
file == Option::fixPathToTargetOS(ret, true, canon))
|
|
|
|
ret = Option::fixPathToTargetOS(qfileinfo.canonicalFilePath());
|
|
|
|
QString match_dir = Option::fixPathToTargetOS(out_dir, false, canon);
|
|
|
|
if(ret == match_dir) {
|
|
|
|
ret = "";
|
|
|
|
} else if(ret.startsWith(match_dir + Option::dir_sep)) {
|
|
|
|
ret = ret.mid(match_dir.length() + Option::dir_sep.length());
|
|
|
|
} else {
|
|
|
|
//figure out the depth
|
|
|
|
int depth = 4;
|
|
|
|
if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
|
|
|
|
Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
|
|
|
|
if(project && !project->isEmpty("QMAKE_PROJECT_DEPTH"))
|
|
|
|
depth = project->first("QMAKE_PROJECT_DEPTH").toInt();
|
|
|
|
else if(Option::mkfile::cachefile_depth != -1)
|
|
|
|
depth = Option::mkfile::cachefile_depth;
|
|
|
|
}
|
|
|
|
//calculate how much can be removed
|
|
|
|
QString dot_prefix;
|
|
|
|
for(int i = 1; i <= depth; i++) {
|
|
|
|
int sl = match_dir.lastIndexOf(Option::dir_sep);
|
|
|
|
if(sl == -1)
|
|
|
|
break;
|
|
|
|
match_dir = match_dir.left(sl);
|
|
|
|
if(match_dir.isEmpty())
|
|
|
|
break;
|
|
|
|
if(ret.startsWith(match_dir + Option::dir_sep)) {
|
|
|
|
//concat
|
|
|
|
int remlen = ret.length() - (match_dir.length() + 1);
|
|
|
|
if(remlen < 0)
|
|
|
|
remlen = 0;
|
|
|
|
ret = ret.right(remlen);
|
|
|
|
//prepend
|
|
|
|
for(int o = 0; o < i; o++)
|
|
|
|
dot_prefix += ".." + Option::dir_sep;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ret.prepend(dot_prefix);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ret = Option::fixPathToTargetOS(ret, false, canon);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(ret.isEmpty())
|
|
|
|
ret = ".";
|
|
|
|
debug_msg(3, "Fixed[%d,%d] %s :: to :: %s [%s::%s] [%s::%s]", fix, canon, orig_file.toLatin1().constData(),
|
|
|
|
ret.toLatin1().constData(), in_d.toLatin1().constData(), out_d.toLatin1().constData(),
|
|
|
|
qmake_getpwd().toLatin1().constData(), Option::output_dir.toLatin1().constData());
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
QMakeLocalFileName
|
|
|
|
MakefileGenerator::fixPathForFile(const QMakeLocalFileName &file, bool forOpen)
|
|
|
|
{
|
|
|
|
if(forOpen)
|
|
|
|
return QMakeLocalFileName(fileFixify(file.real(), qmake_getpwd(), Option::output_dir));
|
|
|
|
return QMakeLocalFileName(fileFixify(file.real()));
|
|
|
|
}
|
|
|
|
|
|
|
|
QFileInfo
|
|
|
|
MakefileGenerator::findFileInfo(const QMakeLocalFileName &file)
|
|
|
|
{
|
|
|
|
return fileInfo(file.local());
|
|
|
|
}
|
|
|
|
|
|
|
|
QMakeLocalFileName
|
|
|
|
MakefileGenerator::findFileForDep(const QMakeLocalFileName &dep, const QMakeLocalFileName &file)
|
|
|
|
{
|
|
|
|
QMakeLocalFileName ret;
|
|
|
|
if(!project->isEmpty("SKIP_DEPENDS")) {
|
|
|
|
bool found = false;
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &nodeplist = project->values("SKIP_DEPENDS");
|
|
|
|
for (ProStringList::ConstIterator it = nodeplist.begin();
|
2011-04-27 10:05:43 +00:00
|
|
|
it != nodeplist.end(); ++it) {
|
2012-09-06 10:21:38 +00:00
|
|
|
QRegExp regx((*it).toQString());
|
2011-04-27 10:05:43 +00:00
|
|
|
if(regx.indexIn(dep.local()) != -1) {
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(found)
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = QMakeSourceFileInfo::findFileForDep(dep, file);
|
|
|
|
if(!ret.isNull())
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
//these are some "hacky" heuristics it will try to do on an include
|
|
|
|
//however these can be turned off at runtime, I'm not sure how
|
|
|
|
//reliable these will be, most likely when problems arise turn it off
|
|
|
|
//and see if they go away..
|
|
|
|
if(Option::mkfile::do_dep_heuristics) {
|
|
|
|
if(depHeuristicsCache.contains(dep.real()))
|
|
|
|
return depHeuristicsCache[dep.real()];
|
|
|
|
|
|
|
|
if(Option::output_dir != qmake_getpwd()
|
|
|
|
&& QDir::isRelativePath(dep.real())) { //is it from the shadow tree
|
|
|
|
QList<QMakeLocalFileName> depdirs = QMakeSourceFileInfo::dependencyPaths();
|
|
|
|
depdirs.prepend(fileInfo(file.real()).absoluteDir().path());
|
|
|
|
QString pwd = qmake_getpwd();
|
|
|
|
if(pwd.at(pwd.length()-1) != '/')
|
|
|
|
pwd += '/';
|
|
|
|
for(int i = 0; i < depdirs.count(); i++) {
|
|
|
|
QString dir = depdirs.at(i).real();
|
|
|
|
if(!QDir::isRelativePath(dir) && dir.startsWith(pwd))
|
|
|
|
dir = dir.mid(pwd.length());
|
|
|
|
if(QDir::isRelativePath(dir)) {
|
|
|
|
if(!dir.endsWith(Option::dir_sep))
|
|
|
|
dir += Option::dir_sep;
|
|
|
|
QString shadow = fileFixify(dir + dep.local(), pwd, Option::output_dir);
|
|
|
|
if(exists(shadow)) {
|
|
|
|
ret = QMakeLocalFileName(shadow);
|
|
|
|
goto found_dep_from_heuristic;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{ //is it from an EXTRA_TARGET
|
|
|
|
const QString dep_basename = dep.local().section(Option::dir_sep, -1);
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &qut = project->values("QMAKE_EXTRA_TARGETS");
|
|
|
|
for (ProStringList::ConstIterator it = qut.begin(); it != qut.end(); ++it) {
|
|
|
|
QString targ = var(ProKey(*it + ".target"));
|
2011-04-27 10:05:43 +00:00
|
|
|
if(targ.isEmpty())
|
2012-09-06 10:21:38 +00:00
|
|
|
targ = (*it).toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
QString out = Option::fixPathToTargetOS(targ);
|
|
|
|
if(out == dep.real() || out.section(Option::dir_sep, -1) == dep_basename) {
|
|
|
|
ret = QMakeLocalFileName(out);
|
|
|
|
goto found_dep_from_heuristic;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{ //is it from an EXTRA_COMPILER
|
|
|
|
const QString dep_basename = dep.local().section(Option::dir_sep, -1);
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &quc = project->values("QMAKE_EXTRA_COMPILERS");
|
|
|
|
for (ProStringList::ConstIterator it = quc.begin(); it != quc.end(); ++it) {
|
|
|
|
const ProString &tmp_out = project->first(ProKey(*it + ".output"));
|
2011-04-27 10:05:43 +00:00
|
|
|
if(tmp_out.isEmpty())
|
|
|
|
continue;
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &tmp = project->values(ProKey(*it + ".input"));
|
|
|
|
for (ProStringList::ConstIterator it2 = tmp.begin(); it2 != tmp.end(); ++it2) {
|
|
|
|
const ProStringList &inputs = project->values((*it2).toKey());
|
|
|
|
for (ProStringList::ConstIterator input = inputs.begin(); input != inputs.end(); ++input) {
|
|
|
|
QString out = Option::fixPathToTargetOS(unescapeFilePath(
|
|
|
|
replaceExtraCompilerVariables(tmp_out.toQString(), (*input).toQString(), QString())));
|
|
|
|
if (out == dep.real() || out.section(Option::dir_sep, -1) == dep_basename) {
|
2011-04-27 10:05:43 +00:00
|
|
|
ret = QMakeLocalFileName(fileFixify(out, qmake_getpwd(), Option::output_dir));
|
|
|
|
goto found_dep_from_heuristic;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
found_dep_from_heuristic:
|
|
|
|
depHeuristicsCache.insert(dep.real(), ret);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
QStringList
|
|
|
|
&MakefileGenerator::findDependencies(const QString &file)
|
|
|
|
{
|
|
|
|
const QString fixedFile = fileFixify(file);
|
|
|
|
if(!dependsCache.contains(fixedFile)) {
|
|
|
|
#if 1
|
|
|
|
QStringList deps = QMakeSourceFileInfo::dependencies(file);
|
|
|
|
if(file != fixedFile)
|
|
|
|
deps += QMakeSourceFileInfo::dependencies(fixedFile);
|
|
|
|
#else
|
|
|
|
QStringList deps = QMakeSourceFileInfo::dependencies(fixedFile);
|
|
|
|
#endif
|
|
|
|
dependsCache.insert(fixedFile, deps);
|
|
|
|
}
|
|
|
|
return dependsCache[fixedFile];
|
|
|
|
}
|
|
|
|
|
|
|
|
QString
|
2012-06-26 13:32:17 +00:00
|
|
|
MakefileGenerator::specdir()
|
2011-04-27 10:05:43 +00:00
|
|
|
{
|
2012-06-26 13:32:17 +00:00
|
|
|
if (spec.isEmpty())
|
2012-06-26 13:36:39 +00:00
|
|
|
spec = fileFixify(project->specDir());
|
2011-04-27 10:05:43 +00:00
|
|
|
return spec;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
MakefileGenerator::openOutput(QFile &file, const QString &build) const
|
|
|
|
{
|
|
|
|
{
|
|
|
|
QString outdir;
|
|
|
|
if(!file.fileName().isEmpty()) {
|
|
|
|
if(QDir::isRelativePath(file.fileName()))
|
|
|
|
file.setFileName(Option::output_dir + "/" + file.fileName()); //pwd when qmake was run
|
|
|
|
QFileInfo fi(fileInfo(file.fileName()));
|
|
|
|
if(fi.isDir())
|
|
|
|
outdir = file.fileName() + '/';
|
|
|
|
}
|
|
|
|
if(!outdir.isEmpty() || file.fileName().isEmpty()) {
|
|
|
|
QString fname = "Makefile";
|
|
|
|
if(!project->isEmpty("MAKEFILE"))
|
2012-09-06 10:21:38 +00:00
|
|
|
fname = project->first("MAKEFILE").toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
file.setFileName(outdir + fname);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(QDir::isRelativePath(file.fileName())) {
|
|
|
|
QString fname = Option::output_dir; //pwd when qmake was run
|
|
|
|
if(!fname.endsWith("/"))
|
|
|
|
fname += "/";
|
|
|
|
fname += file.fileName();
|
|
|
|
file.setFileName(fname);
|
|
|
|
}
|
|
|
|
if(!build.isEmpty())
|
|
|
|
file.setFileName(file.fileName() + "." + build);
|
|
|
|
if(project->isEmpty("QMAKE_MAKEFILE"))
|
|
|
|
project->values("QMAKE_MAKEFILE").append(file.fileName());
|
|
|
|
int slsh = file.fileName().lastIndexOf('/');
|
|
|
|
if(slsh != -1)
|
|
|
|
mkdir(file.fileName().left(slsh));
|
|
|
|
if(file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
|
|
|
|
QFileInfo fi(fileInfo(Option::output.fileName()));
|
|
|
|
QString od;
|
|
|
|
if(fi.isSymLink())
|
|
|
|
od = fileInfo(fi.readLink()).absolutePath();
|
|
|
|
else
|
|
|
|
od = fi.path();
|
|
|
|
od = QDir::fromNativeSeparators(od);
|
|
|
|
if(QDir::isRelativePath(od)) {
|
|
|
|
QString dir = Option::output_dir;
|
|
|
|
if (!dir.endsWith('/') && !od.isEmpty())
|
|
|
|
dir += '/';
|
|
|
|
od.prepend(dir);
|
|
|
|
}
|
|
|
|
Option::output_dir = od;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString
|
|
|
|
MakefileGenerator::pkgConfigFileName(bool fixify)
|
|
|
|
{
|
2013-02-04 11:27:34 +00:00
|
|
|
QString ret = project->first("QMAKE_PKGCONFIG_FILE").toQString();
|
|
|
|
if (ret.isEmpty()) {
|
|
|
|
ret = project->first("TARGET").toQString();
|
|
|
|
int slsh = ret.lastIndexOf(Option::dir_sep);
|
|
|
|
if (slsh != -1)
|
|
|
|
ret = ret.right(ret.length() - slsh - 1);
|
|
|
|
if (ret.startsWith("lib"))
|
|
|
|
ret = ret.mid(3);
|
|
|
|
int dot = ret.indexOf('.');
|
|
|
|
if (dot != -1)
|
|
|
|
ret = ret.left(dot);
|
|
|
|
}
|
2011-04-27 10:05:43 +00:00
|
|
|
ret += Option::pkgcfg_ext;
|
2012-09-06 10:21:38 +00:00
|
|
|
QString subdir = project->first("QMAKE_PKGCONFIG_DESTDIR").toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!subdir.isEmpty()) {
|
|
|
|
// initOutPaths() appends dir_sep, but just to be safe..
|
|
|
|
if (!subdir.endsWith(Option::dir_sep))
|
|
|
|
ret.prepend(Option::dir_sep);
|
|
|
|
ret.prepend(subdir);
|
|
|
|
}
|
|
|
|
if(fixify) {
|
|
|
|
if(QDir::isRelativePath(ret) && !project->isEmpty("DESTDIR"))
|
2012-09-06 10:21:38 +00:00
|
|
|
ret.prepend(project->first("DESTDIR").toQString());
|
2011-04-27 10:05:43 +00:00
|
|
|
ret = Option::fixPathToLocalOS(fileFixify(ret, qmake_getpwd(), Option::output_dir));
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString
|
|
|
|
MakefileGenerator::pkgConfigPrefix() const
|
|
|
|
{
|
|
|
|
if(!project->isEmpty("QMAKE_PKGCONFIG_PREFIX"))
|
2012-09-06 10:21:38 +00:00
|
|
|
return project->first("QMAKE_PKGCONFIG_PREFIX").toQString();
|
2012-05-03 13:36:03 +00:00
|
|
|
return QLibraryInfo::rawLocation(QLibraryInfo::PrefixPath, QLibraryInfo::FinalPaths);
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QString
|
|
|
|
MakefileGenerator::pkgConfigFixPath(QString path) const
|
|
|
|
{
|
|
|
|
QString prefix = pkgConfigPrefix();
|
|
|
|
if(path.startsWith(prefix))
|
|
|
|
path = path.replace(prefix, "${prefix}");
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
MakefileGenerator::writePkgConfigFile()
|
|
|
|
{
|
2013-02-18 17:29:45 +00:00
|
|
|
QString fname = pkgConfigFileName();
|
2011-04-27 10:05:43 +00:00
|
|
|
mkdir(fileInfo(fname).path());
|
|
|
|
QFile ft(fname);
|
|
|
|
if(!ft.open(QIODevice::WriteOnly))
|
|
|
|
return;
|
|
|
|
project->values("ALL_DEPS").append(fileFixify(fname));
|
|
|
|
QTextStream t(&ft);
|
|
|
|
|
|
|
|
QString prefix = pkgConfigPrefix();
|
2012-09-06 10:21:38 +00:00
|
|
|
QString libDir = project->first("QMAKE_PKGCONFIG_LIBDIR").toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
if(libDir.isEmpty())
|
|
|
|
libDir = prefix + Option::dir_sep + "lib" + Option::dir_sep;
|
2012-09-06 10:21:38 +00:00
|
|
|
QString includeDir = project->first("QMAKE_PKGCONFIG_INCDIR").toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
if(includeDir.isEmpty())
|
|
|
|
includeDir = prefix + "/include";
|
|
|
|
|
|
|
|
t << "prefix=" << prefix << endl;
|
|
|
|
t << "exec_prefix=${prefix}\n"
|
|
|
|
<< "libdir=" << pkgConfigFixPath(libDir) << "\n"
|
|
|
|
<< "includedir=" << pkgConfigFixPath(includeDir) << endl;
|
2012-06-30 06:05:13 +00:00
|
|
|
t << endl;
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
//extra PKGCONFIG variables
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &pkgconfig_vars = project->values("QMAKE_PKGCONFIG_VARIABLES");
|
2011-04-27 10:05:43 +00:00
|
|
|
for(int i = 0; i < pkgconfig_vars.size(); ++i) {
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProString &var = project->first(ProKey(pkgconfig_vars.at(i) + ".name"));
|
2012-05-18 18:00:23 +00:00
|
|
|
QString val = project->values(ProKey(pkgconfig_vars.at(i) + ".value")).join(' ');
|
2011-04-27 10:05:43 +00:00
|
|
|
if(var.isEmpty())
|
|
|
|
continue;
|
|
|
|
if(val.isEmpty()) {
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &var_vars = project->values(ProKey(pkgconfig_vars.at(i) + ".variable"));
|
2011-04-27 10:05:43 +00:00
|
|
|
for(int v = 0; v < var_vars.size(); ++v) {
|
2012-09-06 10:21:38 +00:00
|
|
|
const ProStringList &vars = project->values(var_vars.at(v).toKey());
|
2011-04-27 10:05:43 +00:00
|
|
|
for(int var = 0; var < vars.size(); ++var) {
|
|
|
|
if(!val.isEmpty())
|
|
|
|
val += " ";
|
2012-09-06 10:21:38 +00:00
|
|
|
val += pkgConfigFixPath(vars.at(var).toQString());
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
t << var << "=" << val << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
t << endl;
|
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
QString name = project->first("QMAKE_PKGCONFIG_NAME").toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
if(name.isEmpty()) {
|
2012-09-06 10:21:38 +00:00
|
|
|
name = project->first("QMAKE_ORIG_TARGET").toQString().toLower();
|
2011-04-27 10:05:43 +00:00
|
|
|
name.replace(0, 1, name[0].toUpper());
|
|
|
|
}
|
|
|
|
t << "Name: " << name << endl;
|
2012-05-18 18:00:23 +00:00
|
|
|
QString desc = project->values("QMAKE_PKGCONFIG_DESCRIPTION").join(' ');
|
2011-04-27 10:05:43 +00:00
|
|
|
if(desc.isEmpty()) {
|
|
|
|
if(name.isEmpty()) {
|
2012-09-06 10:21:38 +00:00
|
|
|
desc = project->first("QMAKE_ORIG_TARGET").toQString().toLower();
|
2011-04-27 10:05:43 +00:00
|
|
|
desc.replace(0, 1, desc[0].toUpper());
|
|
|
|
} else {
|
|
|
|
desc = name;
|
|
|
|
}
|
|
|
|
if(project->first("TEMPLATE") == "lib") {
|
|
|
|
if(project->isActiveConfig("plugin"))
|
|
|
|
desc += " Plugin";
|
|
|
|
else
|
|
|
|
desc += " Library";
|
|
|
|
} else if(project->first("TEMPLATE") == "app") {
|
|
|
|
desc += " Application";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
t << "Description: " << desc << endl;
|
|
|
|
t << "Version: " << project->first("VERSION") << endl;
|
|
|
|
|
|
|
|
// libs
|
|
|
|
t << "Libs: ";
|
|
|
|
QString pkgConfiglibDir;
|
|
|
|
QString pkgConfiglibName;
|
2013-03-06 13:53:36 +00:00
|
|
|
if (target_mode == TARG_MAC_MODE && project->isActiveConfig("lib_bundle")) {
|
2011-04-27 10:05:43 +00:00
|
|
|
pkgConfiglibDir = "-F${libdir}";
|
2012-09-06 10:21:38 +00:00
|
|
|
ProString bundle;
|
2011-04-27 10:05:43 +00:00
|
|
|
if (!project->isEmpty("QMAKE_FRAMEWORK_BUNDLE_NAME"))
|
|
|
|
bundle = unescapeFilePath(project->first("QMAKE_FRAMEWORK_BUNDLE_NAME"));
|
|
|
|
else
|
|
|
|
bundle = unescapeFilePath(project->first("TARGET"));
|
|
|
|
int suffix = bundle.lastIndexOf(".framework");
|
|
|
|
if (suffix != -1)
|
|
|
|
bundle = bundle.left(suffix);
|
|
|
|
pkgConfiglibName = "-framework " + bundle + " ";
|
|
|
|
} else {
|
|
|
|
pkgConfiglibDir = "-L${libdir}";
|
2013-02-18 17:29:45 +00:00
|
|
|
pkgConfiglibName = "-l" + fileInfo(fname).completeBaseName();
|
2012-04-19 12:48:34 +00:00
|
|
|
if (project->isActiveConfig("shared"))
|
2012-09-06 10:21:38 +00:00
|
|
|
pkgConfiglibName += project->first("TARGET_VERSION_EXT").toQString();
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
2013-07-04 09:25:16 +00:00
|
|
|
t << pkgConfiglibDir << " " << pkgConfiglibName << " \n";
|
2011-04-27 10:05:43 +00:00
|
|
|
|
2012-09-06 10:21:38 +00:00
|
|
|
ProStringList libs;
|
2011-04-27 10:05:43 +00:00
|
|
|
if(!project->isEmpty("QMAKE_INTERNAL_PRL_LIBS")) {
|
|
|
|
libs = project->values("QMAKE_INTERNAL_PRL_LIBS");
|
|
|
|
} else {
|
|
|
|
libs << "QMAKE_LIBS"; //obvious one
|
|
|
|
}
|
|
|
|
libs << "QMAKE_LIBS_PRIVATE";
|
|
|
|
libs << "QMAKE_LFLAGS_THREAD"; //not sure about this one, but what about things like -pthread?
|
|
|
|
t << "Libs.private: ";
|
2012-09-06 10:21:38 +00:00
|
|
|
for (ProStringList::ConstIterator it = libs.begin(); it != libs.end(); ++it) {
|
2012-05-18 18:00:23 +00:00
|
|
|
t << project->values((*it).toKey()).join(' ') << " ";
|
2011-04-27 10:05:43 +00:00
|
|
|
}
|
|
|
|
t << endl;
|
|
|
|
|
|
|
|
// flags
|
|
|
|
// ### too many
|
|
|
|
t << "Cflags: "
|
|
|
|
// << var("QMAKE_CXXFLAGS") << " "
|
|
|
|
<< varGlue("PRL_EXPORT_DEFINES","-D"," -D"," ")
|
2013-03-30 05:39:56 +00:00
|
|
|
<< varGlue("PRL_EXPORT_CXXFLAGS", "", " ", " ")
|
|
|
|
<< varGlue("QMAKE_PKGCONFIG_CFLAGS", "", " ", " ")
|
2011-04-27 10:05:43 +00:00
|
|
|
// << varGlue("DEFINES","-D"," -D"," ")
|
2013-07-04 09:25:16 +00:00
|
|
|
<< "-I${includedir}\n";
|
2011-04-27 10:05:43 +00:00
|
|
|
|
|
|
|
// requires
|
2012-05-18 18:00:23 +00:00
|
|
|
const QString requires = project->values("QMAKE_PKGCONFIG_REQUIRES").join(' ');
|
2011-04-27 10:05:43 +00:00
|
|
|
if (!requires.isEmpty()) {
|
|
|
|
t << "Requires: " << requires << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
t << endl;
|
|
|
|
}
|
|
|
|
|
2013-01-10 23:30:41 +00:00
|
|
|
QString MakefileGenerator::installMetaFile(const ProKey &replace_rule, const QString &src, const QString &dst)
|
|
|
|
{
|
|
|
|
QString ret;
|
|
|
|
if (project->isEmpty(replace_rule)
|
|
|
|
|| project->isActiveConfig("no_sed_meta_install")
|
|
|
|
|| project->isEmpty("QMAKE_STREAM_EDITOR")) {
|
|
|
|
ret += "-$(INSTALL_FILE) \"" + src + "\" \"" + dst + "\"";
|
|
|
|
} else {
|
|
|
|
ret += "-$(SED)";
|
|
|
|
const ProStringList &replace_rules = project->values(replace_rule);
|
|
|
|
for (int r = 0; r < replace_rules.size(); ++r) {
|
|
|
|
const ProString match = project->first(ProKey(replace_rules.at(r) + ".match")),
|
|
|
|
replace = project->first(ProKey(replace_rules.at(r) + ".replace"));
|
|
|
|
if (!match.isEmpty() /*&& match != replace*/)
|
|
|
|
ret += " -e \"s," + match + "," + replace + ",g\"";
|
|
|
|
}
|
|
|
|
ret += " \"" + src + "\" >\"" + dst + "\"";
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-04-27 10:05:43 +00:00
|
|
|
QT_END_NAMESPACE
|