qt5base-lts/qmake/option.cpp
Alexey Edelev 43c28aa904 Use Core library for qmake instead of the Bootstrap library
Move the qmake-specific logic of the QLibraryInfo class to
qmake internals. 'qconfig.cpp.in' now stores information about
the library info entries to keep them consistent between qmake
and the Core library. qmake requires specific features enabled
in the Core library, so building qmake will be skipped if the
features are not enabled.

All flags directly related to the qmake have been removed from
Core lib.

Remove all bootstrap related sections from qmake CMakeLists.txt

Task-number: QTBUG-89369
Change-Id: I26de157d3bfd4a5526699296e9d46e1c180b89ae
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Kai Koehne <kai.koehne@qt.io>
2021-02-25 16:08:43 +01:00

681 lines
26 KiB
C++

/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the qmake application of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** 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 The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "option.h"
#include "cachekeys.h"
#include <ioutils.h>
#include <qdir.h>
#include <qregularexpression.h>
#include <qhash.h>
#include <qdebug.h>
#include <qmakelibraryinfo.h>
#include <stdlib.h>
#include <stdarg.h>
QT_BEGIN_NAMESPACE
using namespace QMakeInternal;
EvalHandler Option::evalHandler;
QMakeGlobals *Option::globals;
ProFileCache *Option::proFileCache;
QMakeVfs *Option::vfs;
QMakeParser *Option::parser;
//convenience
QString Option::prf_ext;
QString Option::prl_ext;
QString Option::libtool_ext;
QString Option::pkgcfg_ext;
QString Option::ui_ext;
QStringList Option::h_ext;
QString Option::cpp_moc_ext;
QStringList Option::cpp_ext;
QStringList Option::c_ext;
QString Option::objc_ext;
QString Option::objcpp_ext;
QString Option::obj_ext;
QString Option::lex_ext;
QString Option::yacc_ext;
QString Option::pro_ext;
QString Option::dir_sep;
QString Option::h_moc_mod;
QString Option::yacc_mod;
QString Option::lex_mod;
QString Option::res_ext;
char Option::field_sep;
//mode
Option::QMAKE_MODE Option::qmake_mode = Option::QMAKE_GENERATE_NOTHING;
//all modes
int Option::warn_level = WarnLogic | WarnDeprecated;
int Option::debug_level = 0;
QFile Option::output;
QString Option::output_dir;
bool Option::recursive = false;
//QMAKE_*_PROPERTY stuff
QStringList Option::prop::properties;
//QMAKE_GENERATE_PROJECT stuff
bool Option::projfile::do_pwd = true;
QStringList Option::projfile::project_dirs;
//QMAKE_GENERATE_MAKEFILE stuff
int Option::mkfile::cachefile_depth = -1;
bool Option::mkfile::do_deps = true;
bool Option::mkfile::do_mocs = true;
bool Option::mkfile::do_dep_heuristics = true;
bool Option::mkfile::do_preprocess = false;
QStringList Option::mkfile::project_files;
static Option::QMAKE_MODE default_mode(QString progname)
{
int s = progname.lastIndexOf(QDir::separator());
if(s != -1)
progname = progname.right(progname.length() - (s + 1));
if(progname == "qmakegen")
return Option::QMAKE_GENERATE_PROJECT;
else if(progname == "qt-config")
return Option::QMAKE_QUERY_PROPERTY;
return Option::QMAKE_GENERATE_MAKEFILE;
}
static QString detectProjectFile(const QString &path)
{
QString ret;
QDir dir(path);
if(dir.exists(dir.dirName() + Option::pro_ext)) {
ret = dir.filePath(dir.dirName()) + Option::pro_ext;
} else { //last try..
QStringList profiles = dir.entryList(QStringList("*" + Option::pro_ext));
if(profiles.count() == 1)
ret = dir.filePath(profiles.at(0));
}
return ret;
}
bool usage(const char *a0)
{
fprintf(stdout, "Usage: %s [mode] [options] [files]\n"
"\n"
"QMake has two modes, one mode for generating project files based on\n"
"some heuristics, and the other for generating makefiles. Normally you\n"
"shouldn't need to specify a mode, as makefile generation is the default\n"
"mode for qmake, but you may use this to test qmake on an existing project\n"
"\n"
"Mode:\n"
" -project Put qmake into project file generation mode%s\n"
" In this mode qmake interprets [files] as files to\n"
" be added to the .pro file. By default, all files with\n"
" known source extensions are added.\n"
" Note: The created .pro file probably will \n"
" need to be edited. For example add the QT variable to \n"
" specify what modules are required.\n"
" -makefile Put qmake into makefile generation mode%s\n"
" In this mode qmake interprets files as project files to\n"
" be processed, if skipped qmake will try to find a project\n"
" file in your current working directory\n"
"\n"
"Warnings Options:\n"
" -Wnone Turn off all warnings; specific ones may be re-enabled by\n"
" later -W options\n"
" -Wall Turn on all warnings\n"
" -Wparser Turn on parser warnings\n"
" -Wlogic Turn on logic warnings (on by default)\n"
" -Wdeprecated Turn on deprecation warnings (on by default)\n"
"\n"
"Options:\n"
" * You can place any variable assignment in options and it will be *\n"
" * processed as if it was in [files]. These assignments will be *\n"
" * processed before [files] by default. *\n"
" -o file Write output to file\n"
" -d Increase debug level\n"
" -t templ Overrides TEMPLATE as templ\n"
" -tp prefix Overrides TEMPLATE so that prefix is prefixed into the value\n"
" -help This help\n"
" -v Version information\n"
" -early All subsequent variable assignments will be\n"
" parsed right before default_pre.prf\n"
" -before All subsequent variable assignments will be\n"
" parsed right before [files] (the default)\n"
" -after All subsequent variable assignments will be\n"
" parsed after [files]\n"
" -late All subsequent variable assignments will be\n"
" parsed right after default_post.prf\n"
" -norecursive Don't do a recursive search\n"
" -recursive Do a recursive search\n"
" -set <prop> <value> Set persistent property\n"
" -unset <prop> Unset persistent property\n"
" -query <prop> Query persistent property. Show all if <prop> is empty.\n"
" -qtconf file Use file instead of looking for qt" QT_STRINGIFY(QT_VERSION_MAJOR) ".conf, then qt.conf\n"
" -cache file Use file as cache [makefile mode only]\n"
" -spec spec Use spec as QMAKESPEC [makefile mode only]\n"
" -nocache Don't use a cache file [makefile mode only]\n"
" -nodepend Don't generate dependencies [makefile mode only]\n"
" -nomoc Don't generate moc targets [makefile mode only]\n"
" -nopwd Don't look for files in pwd [project mode only]\n"
,a0,
default_mode(a0) == Option::QMAKE_GENERATE_PROJECT ? " (default)" : "",
default_mode(a0) == Option::QMAKE_GENERATE_MAKEFILE ? " (default)" : ""
);
return false;
}
int
Option::parseCommandLine(QStringList &args, QMakeCmdLineParserState &state)
{
enum { ArgNone, ArgOutput } argState = ArgNone;
int x = 0;
while (x < args.count()) {
switch (argState) {
case ArgOutput:
Option::output.setFileName(args.at(x--));
args.erase(args.begin() + x, args.begin() + x + 2);
argState = ArgNone;
continue;
default:
QMakeGlobals::ArgumentReturn cmdRet = globals->addCommandLineArguments(state, args, &x);
if (cmdRet == QMakeGlobals::ArgumentsOk)
break;
if (cmdRet == QMakeGlobals::ArgumentMalformed) {
fprintf(stderr, "***Option %s requires a parameter\n", qPrintable(args.at(x - 1)));
return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
}
Q_ASSERT(cmdRet == QMakeGlobals::ArgumentUnknown);
QString arg = args.at(x);
if (arg.startsWith(QLatin1Char('-'))) {
if (arg == "-d") {
Option::debug_level++;
} else if (arg == "-v" || arg == "-version" || arg == "--version") {
fprintf(stdout,
"QMake version %s\n"
"Using Qt version %s in %s\n",
QMAKE_VERSION_STR, QT_VERSION_STR,
QMakeLibraryInfo::path(QLibraryInfo::LibrariesPath)
.toLatin1()
.constData());
#ifdef QMAKE_OPENSOURCE_VERSION
fprintf(stdout, "QMake is Open Source software from The Qt Company Ltd and/or its subsidiary(-ies).\n");
#endif
return Option::QMAKE_CMDLINE_BAIL;
} else if (arg == "-h" || arg == "-help" || arg == "--help") {
return Option::QMAKE_CMDLINE_SHOW_USAGE;
} else if (arg == "-Wall") {
Option::warn_level |= WarnAll;
} else if (arg == "-Wparser") {
Option::warn_level |= WarnParser;
} else if (arg == "-Wlogic") {
Option::warn_level |= WarnLogic;
} else if (arg == "-Wdeprecated") {
Option::warn_level |= WarnDeprecated;
} else if (arg == "-Wnone") {
Option::warn_level = WarnNone;
} else if (arg == "-r" || arg == "-recursive") {
Option::recursive = true;
args.removeAt(x);
continue;
} else if (arg == "-nr" || arg == "-norecursive") {
Option::recursive = false;
args.removeAt(x);
continue;
} else if (arg == "-o" || arg == "-output") {
argState = ArgOutput;
} else {
if (Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
if (arg == "-nodepend" || arg == "-nodepends") {
Option::mkfile::do_deps = false;
} else if (arg == "-nomoc") {
Option::mkfile::do_mocs = false;
} else if (arg == "-nodependheuristics") {
Option::mkfile::do_dep_heuristics = false;
} else if (arg == "-E") {
Option::mkfile::do_preprocess = true;
} else {
fprintf(stderr, "***Unknown option %s\n", arg.toLatin1().constData());
return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
}
} else if (Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) {
if (arg == "-nopwd") {
Option::projfile::do_pwd = false;
} else {
fprintf(stderr, "***Unknown option %s\n", arg.toLatin1().constData());
return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
}
}
}
} else {
bool handled = true;
if(Option::qmake_mode == Option::QMAKE_QUERY_PROPERTY ||
Option::qmake_mode == Option::QMAKE_SET_PROPERTY ||
Option::qmake_mode == Option::QMAKE_UNSET_PROPERTY) {
Option::prop::properties.append(arg);
} else {
QFileInfo fi(arg);
if(!fi.makeAbsolute()) //strange
arg = fi.filePath();
if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
if(fi.isDir()) {
QString proj = detectProjectFile(arg);
if (!proj.isNull())
arg = proj;
}
Option::mkfile::project_files.append(arg);
} else if(Option::qmake_mode == Option::QMAKE_GENERATE_PROJECT) {
Option::projfile::project_dirs.append(arg);
} else {
handled = false;
}
}
if(!handled) {
return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
}
args.removeAt(x);
continue;
}
}
x++;
}
if (argState != ArgNone) {
fprintf(stderr, "***Option %s requires a parameter\n", qPrintable(args.at(x - 1)));
return Option::QMAKE_CMDLINE_SHOW_USAGE | Option::QMAKE_CMDLINE_ERROR;
}
return Option::QMAKE_CMDLINE_SUCCESS;
}
int
Option::init(int argc, char **argv)
{
Option::prf_ext = ".prf";
Option::pro_ext = ".pro";
Option::field_sep = ' ';
if(argc && argv) {
QString argv0 = argv[0];
#ifdef Q_OS_WIN
if (!argv0.endsWith(QLatin1String(".exe"), Qt::CaseInsensitive))
argv0 += QLatin1String(".exe");
#endif
if(Option::qmake_mode == Option::QMAKE_GENERATE_NOTHING)
Option::qmake_mode = default_mode(argv0);
if (!argv0.isEmpty() && IoUtils::isAbsolutePath(argv0)) {
globals->qmake_abslocation = argv0;
} else if (argv0.contains(QLatin1Char('/'))
#ifdef Q_OS_WIN
|| argv0.contains(QLatin1Char('\\'))
#endif
) { //relative PWD
globals->qmake_abslocation = QDir::current().absoluteFilePath(argv0);
} else { //in the PATH
QByteArray pEnv = qgetenv("PATH");
QDir currentDir = QDir::current();
#ifdef Q_OS_WIN
QStringList paths = QString::fromLocal8Bit(pEnv).split(QLatin1String(";"));
paths.prepend(QLatin1String("."));
#else
QStringList paths = QString::fromLocal8Bit(pEnv).split(QLatin1String(":"));
#endif
for (QStringList::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) {
if ((*p).isEmpty())
continue;
QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + argv0);
if (QFile::exists(candidate)) {
globals->qmake_abslocation = candidate;
break;
}
}
}
if (Q_UNLIKELY(globals->qmake_abslocation.isNull())) {
// This is rather unlikely to ever happen on a modern system ...
globals->qmake_abslocation =
QMakeLibraryInfo::rawLocation(QMakeLibraryInfo::HostBinariesPath,
QMakeLibraryInfo::EffectivePaths)
#ifdef Q_OS_WIN
+ "/qmake.exe";
#else
+ "/qmake";
#endif
} else {
globals->qmake_abslocation = QDir::cleanPath(globals->qmake_abslocation);
}
} else {
Option::qmake_mode = Option::QMAKE_GENERATE_MAKEFILE;
}
QMakeCmdLineParserState cmdstate(QDir::currentPath());
const QByteArray envflags = qgetenv("QMAKEFLAGS");
if (!envflags.isNull()) {
QStringList args;
QByteArray buf = "";
char quote = 0;
bool hasWord = false;
for (int i = 0; i < envflags.size(); ++i) {
char c = envflags.at(i);
if (!quote && (c == '\'' || c == '"')) {
quote = c;
} else if (c == quote) {
quote = 0;
} else if (!quote && c == ' ') {
if (hasWord) {
args << QString::fromLocal8Bit(buf);
hasWord = false;
buf = "";
}
} else {
buf += c;
hasWord = true;
}
}
if (hasWord)
args << QString::fromLocal8Bit(buf);
parseCommandLine(args, cmdstate);
cmdstate.flush();
}
if(argc && argv) {
QStringList args;
args.reserve(argc - 1);
for (int i = 1; i < argc; i++)
args << QString::fromLocal8Bit(argv[i]);
while (!args.isEmpty()) {
QString opt = args.at(0);
if (opt == "-project") {
Option::recursive = true;
Option::qmake_mode = Option::QMAKE_GENERATE_PROJECT;
} else if (opt == "-prl") {
Option::mkfile::do_deps = false;
Option::mkfile::do_mocs = false;
Option::qmake_mode = Option::QMAKE_GENERATE_PRL;
} else if (opt == "-set") {
Option::qmake_mode = Option::QMAKE_SET_PROPERTY;
} else if (opt == "-unset") {
Option::qmake_mode = Option::QMAKE_UNSET_PROPERTY;
} else if (opt == "-query") {
Option::qmake_mode = Option::QMAKE_QUERY_PROPERTY;
} else if (opt == "-makefile") {
Option::qmake_mode = Option::QMAKE_GENERATE_MAKEFILE;
} else if (opt == "-qtconf") {
// Move the argument following "-qtconf <file>" in front and check again.
if (args.length() >= 3)
args.prepend(args.takeAt(2));
continue;
} else {
break;
}
args.takeFirst();
break;
}
int ret = parseCommandLine(args, cmdstate);
if(ret != Option::QMAKE_CMDLINE_SUCCESS) {
if ((ret & Option::QMAKE_CMDLINE_SHOW_USAGE) != 0)
usage(argv[0]);
return ret;
//return ret == QMAKE_CMDLINE_SHOW_USAGE ? usage(argv[0]) : false;
}
globals->qmake_args = args;
globals->qmake_extra_args = cmdstate.extraargs;
}
globals->commitCommandLineArguments(cmdstate);
globals->debugLevel = Option::debug_level;
//last chance for defaults
if(Option::qmake_mode == Option::QMAKE_GENERATE_MAKEFILE ||
Option::qmake_mode == Option::QMAKE_GENERATE_PRL) {
globals->useEnvironment();
//try REALLY hard to do it for them, lazy..
if(Option::mkfile::project_files.isEmpty()) {
QString proj = detectProjectFile(qmake_getpwd());
if(!proj.isNull())
Option::mkfile::project_files.append(proj);
if(Option::mkfile::project_files.isEmpty()) {
usage(argv[0]);
return Option::QMAKE_CMDLINE_ERROR;
}
}
}
return QMAKE_CMDLINE_SUCCESS;
}
void Option::prepareProject(const QString &pfile)
{
// Canonicalize only the directory, otherwise things will go haywire
// if the file itself is a symbolic link.
const QString srcpath = QFileInfo(QFileInfo(pfile).absolutePath()).canonicalFilePath();
globals->setDirectories(srcpath, output_dir);
}
bool Option::postProcessProject(QMakeProject *project)
{
Option::cpp_ext = project->values("QMAKE_EXT_CPP").toQStringList();
Option::h_ext = project->values("QMAKE_EXT_H").toQStringList();
Option::c_ext = project->values("QMAKE_EXT_C").toQStringList();
Option::objc_ext = project->first("QMAKE_EXT_OBJC").toQString();
Option::objcpp_ext = project->first("QMAKE_EXT_OBJCXX").toQString();
Option::res_ext = project->first("QMAKE_EXT_RES").toQString();
Option::pkgcfg_ext = project->first("QMAKE_EXT_PKGCONFIG").toQString();
Option::libtool_ext = project->first("QMAKE_EXT_LIBTOOL").toQString();
Option::prl_ext = project->first("QMAKE_EXT_PRL").toQString();
Option::ui_ext = project->first("QMAKE_EXT_UI").toQString();
Option::cpp_moc_ext = project->first("QMAKE_EXT_CPP_MOC").toQString();
Option::lex_ext = project->first("QMAKE_EXT_LEX").toQString();
Option::yacc_ext = project->first("QMAKE_EXT_YACC").toQString();
Option::obj_ext = project->first("QMAKE_EXT_OBJ").toQString();
Option::h_moc_mod = project->first("QMAKE_H_MOD_MOC").toQString();
Option::lex_mod = project->first("QMAKE_MOD_LEX").toQString();
Option::yacc_mod = project->first("QMAKE_MOD_YACC").toQString();
Option::dir_sep = project->dirSep().toQString();
if (!project->buildRoot().isEmpty() && Option::output_dir.startsWith(project->buildRoot()))
Option::mkfile::cachefile_depth =
Option::output_dir.mid(project->buildRoot().length()).count('/');
return true;
}
QString
Option::fixString(QString string, uchar flags)
{
//const QString orig_string = string;
static QHash<FixStringCacheKey, QString> *cache = nullptr;
if(!cache) {
cache = new QHash<FixStringCacheKey, QString>;
qmakeAddCacheClear(qmakeDeleteCacheClear<QHash<FixStringCacheKey, QString> >, (void**)&cache);
}
FixStringCacheKey cacheKey(string, flags);
QHash<FixStringCacheKey, QString>::const_iterator it = cache->constFind(cacheKey);
if (it != cache->constEnd()) {
//qDebug() << "Fix (cached) " << orig_string << "->" << it.value();
return it.value();
}
//fix the environment variables
if(flags & Option::FixEnvVars) {
static QRegularExpression reg_var("\\$\\(.*\\)", QRegularExpression::InvertedGreedinessOption);
QRegularExpressionMatch match;
while ((match = reg_var.match(string)).hasMatch()) {
int start = match.capturedStart();
int len = match.capturedLength();
string.replace(start, len,
QString::fromLocal8Bit(qgetenv(string.mid(start + 2, len - 3).toLatin1().constData()).constData()));
}
}
//canonicalize it (and treat as a path)
if(flags & Option::FixPathCanonicalize) {
#if 0
string = QFileInfo(string).canonicalFilePath();
#endif
string = QDir::cleanPath(string);
}
// either none or only one active flag
Q_ASSERT(((flags & Option::FixPathToLocalSeparators) != 0) +
((flags & Option::FixPathToTargetSeparators) != 0) +
((flags & Option::FixPathToNormalSeparators) != 0) <= 1);
//fix separators
if (flags & Option::FixPathToNormalSeparators) {
string.replace('\\', '/');
} else if (flags & Option::FixPathToLocalSeparators) {
#if defined(Q_OS_WIN32)
string.replace('/', '\\');
#else
string.replace('\\', '/');
#endif
} else if(flags & Option::FixPathToTargetSeparators) {
string.replace('/', Option::dir_sep).replace('\\', Option::dir_sep);
}
if ((string.startsWith("\"") && string.endsWith("\"")) ||
(string.startsWith("\'") && string.endsWith("\'")))
string = string.mid(1, string.length()-2);
//cache
//qDebug() << "Fix" << orig_string << "->" << string;
cache->insert(cacheKey, string);
return string;
}
void debug_msg_internal(int level, const char *fmt, ...)
{
if(Option::debug_level < level)
return;
fprintf(stderr, "DEBUG %d: ", level);
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
fprintf(stderr, "\n");
}
void warn_msg(QMakeWarn type, const char *fmt, ...)
{
if(!(Option::warn_level & type))
return;
fprintf(stderr, "WARNING: ");
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
fprintf(stderr, "\n");
}
void EvalHandler::message(int type, const QString &msg, const QString &fileName, int lineNo)
{
QString pfx;
if ((type & QMakeHandler::CategoryMask) == QMakeHandler::WarningMessage) {
int code = (type & QMakeHandler::CodeMask);
if ((code == QMakeHandler::WarnLanguage && !(Option::warn_level & WarnParser))
|| (code == QMakeHandler::WarnDeprecated && !(Option::warn_level & WarnDeprecated)))
return;
pfx = QString::fromLatin1("WARNING: ");
}
if (lineNo > 0)
fprintf(stderr, "%s%s:%d: %s\n", qPrintable(pfx), qPrintable(fileName), lineNo, qPrintable(msg));
else if (lineNo)
fprintf(stderr, "%s%s: %s\n", qPrintable(pfx), qPrintable(fileName), qPrintable(msg));
else
fprintf(stderr, "%s%s\n", qPrintable(pfx), qPrintable(msg));
}
void EvalHandler::fileMessage(int type, const QString &msg)
{
Q_UNUSED(type);
fprintf(stderr, "%s\n", qPrintable(msg));
}
void EvalHandler::aboutToEval(ProFile *, ProFile *, EvalFileType)
{
}
void EvalHandler::doneWithEval(ProFile *)
{
}
class QMakeCacheClearItem {
private:
qmakeCacheClearFunc func;
void **data;
public:
QMakeCacheClearItem(qmakeCacheClearFunc f, void **d) : func(f), data(d) { }
~QMakeCacheClearItem() {
(*func)(*data);
*data = nullptr;
}
};
static QList<QMakeCacheClearItem*> cache_items;
void
qmakeClearCaches()
{
qDeleteAll(cache_items);
cache_items.clear();
}
void
qmakeAddCacheClear(qmakeCacheClearFunc func, void **data)
{
cache_items.append(new QMakeCacheClearItem(func, data));
}
QString qmake_libraryInfoFile()
{
if (!Option::globals->qtconf.isEmpty())
return Option::globals->qtconf;
if (!Option::globals->qmake_abslocation.isEmpty()) {
QDir dir(QFileInfo(Option::globals->qmake_abslocation).absolutePath());
QString qtconfig = dir.filePath("qt" QT_STRINGIFY(QT_VERSION_MAJOR) ".conf");
if (QFile::exists(qtconfig))
return qtconfig;
qtconfig = dir.filePath("qt.conf");
if (QFile::exists(qtconfig))
return qtconfig;
}
return QString();
}
QString qmake_abslocation()
{
return Option::globals->qmake_abslocation;
}
QT_END_NAMESPACE