2011-11-29 14:19:28 +01:00
|
|
|
/**************************************************************************
|
|
|
|
|
**
|
2015-01-14 18:07:15 +01:00
|
|
|
** Copyright (C) 2015 Openismus GmbH.
|
2012-10-02 09:12:39 +02:00
|
|
|
** Authors: Peter Penz (ppenz@openismus.com)
|
|
|
|
|
** Patricia Santana Cruz (patriciasantanacruz@gmail.com)
|
2015-01-14 18:07:15 +01:00
|
|
|
** Contact: http://www.qt.io/licensing
|
2011-11-29 14:19:28 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2011-11-29 14:19:28 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02: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
|
2015-01-14 18:07:15 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms and
|
|
|
|
|
** conditions see http://www.qt.io/terms-conditions. For further information
|
2014-10-01 13:21:18 +02:00
|
|
|
** use the contact form at http://www.qt.io/contact-us.
|
2011-11-29 14:19:28 +01:00
|
|
|
**
|
|
|
|
|
** GNU Lesser General Public License Usage
|
2012-10-02 09:12:39 +02:00
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
2014-10-01 13:21:18 +02:00
|
|
|
** General Public License version 2.1 or version 3 as published by the Free
|
|
|
|
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
|
|
|
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
|
|
|
|
** following information to ensure the GNU Lesser General Public License
|
|
|
|
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
|
|
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
2011-11-29 14:19:28 +01:00
|
|
|
**
|
2015-01-14 18:07:15 +01:00
|
|
|
** In addition, as a special exception, The Qt Company gives you certain additional
|
|
|
|
|
** rights. These rights are described in The Qt Company LGPL Exception
|
2011-11-29 14:19:28 +01:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2011-11-29 14:19:28 +01:00
|
|
|
|
|
|
|
|
#include "makefileparser.h"
|
|
|
|
|
|
|
|
|
|
#include <utils/qtcassert.h>
|
2015-07-09 01:32:10 +02:00
|
|
|
#include <utils/qtcprocess.h>
|
2011-11-29 14:19:28 +01:00
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QFile>
|
2012-07-25 09:48:48 +02:00
|
|
|
#include <QDir>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QFileInfoList>
|
|
|
|
|
#include <QMutexLocker>
|
2011-11-29 14:19:28 +01:00
|
|
|
|
|
|
|
|
using namespace AutotoolsProjectManager::Internal;
|
|
|
|
|
|
|
|
|
|
MakefileParser::MakefileParser(const QString &makefile) :
|
|
|
|
|
QObject(),
|
|
|
|
|
m_success(false),
|
|
|
|
|
m_cancel(false),
|
|
|
|
|
m_mutex(),
|
|
|
|
|
m_makefile(makefile),
|
|
|
|
|
m_executable(),
|
|
|
|
|
m_sources(),
|
|
|
|
|
m_makefiles(),
|
|
|
|
|
m_includePaths(),
|
|
|
|
|
m_line(),
|
|
|
|
|
m_textStream()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-11 15:02:09 +02:00
|
|
|
MakefileParser::~MakefileParser()
|
|
|
|
|
{
|
|
|
|
|
delete m_textStream.device();
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-29 14:19:28 +01:00
|
|
|
bool MakefileParser::parse()
|
|
|
|
|
{
|
|
|
|
|
m_mutex.lock();
|
|
|
|
|
m_cancel = false;
|
|
|
|
|
m_mutex.unlock(),
|
|
|
|
|
|
|
|
|
|
m_success = true;
|
|
|
|
|
m_executable.clear();
|
|
|
|
|
m_sources.clear();
|
|
|
|
|
m_makefiles.clear();
|
|
|
|
|
|
|
|
|
|
QFile *file = new QFile(m_makefile);
|
2012-11-07 21:45:02 +02:00
|
|
|
if (!file->open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
|
|
|
qWarning("%s: %s", qPrintable(m_makefile), qPrintable(file->errorString()));
|
|
|
|
|
delete file;
|
2011-11-29 14:19:28 +01:00
|
|
|
return false;
|
2012-11-07 21:45:02 +02:00
|
|
|
}
|
2011-11-29 14:19:28 +01:00
|
|
|
|
|
|
|
|
QFileInfo info(m_makefile);
|
|
|
|
|
m_makefiles.append(info.fileName());
|
|
|
|
|
|
|
|
|
|
emit status(tr("Parsing %1 in directory %2").arg(info.fileName()).arg(info.absolutePath()));
|
|
|
|
|
|
|
|
|
|
m_textStream.setDevice(file);
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
m_line = m_textStream.readLine();
|
|
|
|
|
switch (topTarget()) {
|
|
|
|
|
case AmDefaultSourceExt: parseDefaultSourceExtensions(); break;
|
|
|
|
|
case BinPrograms: parseBinPrograms(); break;
|
|
|
|
|
case BuiltSources: break; // TODO: Add to m_sources?
|
|
|
|
|
case Sources: parseSources(); break;
|
|
|
|
|
case SubDirs: parseSubDirs(); break;
|
|
|
|
|
case Undefined:
|
|
|
|
|
default: break;
|
|
|
|
|
}
|
|
|
|
|
} while (!m_line.isNull());
|
|
|
|
|
|
|
|
|
|
parseIncludePaths();
|
|
|
|
|
|
|
|
|
|
return m_success;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QStringList MakefileParser::sources() const
|
|
|
|
|
{
|
|
|
|
|
return m_sources;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QStringList MakefileParser::makefiles() const
|
|
|
|
|
{
|
|
|
|
|
return m_makefiles;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString MakefileParser::executable() const
|
|
|
|
|
{
|
|
|
|
|
return m_executable;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QStringList MakefileParser::includePaths() const
|
|
|
|
|
{
|
|
|
|
|
return m_includePaths;
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-29 02:31:43 +04:00
|
|
|
QByteArray MakefileParser::defines() const
|
|
|
|
|
{
|
|
|
|
|
return m_defines;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QStringList MakefileParser::cflags() const
|
|
|
|
|
{
|
2015-07-09 13:27:27 +02:00
|
|
|
return m_cppflags + m_cflags;
|
2013-04-29 02:31:43 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QStringList MakefileParser::cxxflags() const
|
|
|
|
|
{
|
2015-07-09 13:27:27 +02:00
|
|
|
return m_cppflags + m_cxxflags;
|
2013-04-29 02:31:43 +04:00
|
|
|
}
|
|
|
|
|
|
2011-11-29 14:19:28 +01:00
|
|
|
void MakefileParser::cancel()
|
|
|
|
|
{
|
|
|
|
|
QMutexLocker locker(&m_mutex);
|
|
|
|
|
m_cancel = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MakefileParser::isCanceled() const
|
|
|
|
|
{
|
|
|
|
|
QMutexLocker locker(&m_mutex);
|
|
|
|
|
return m_cancel;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MakefileParser::TopTarget MakefileParser::topTarget() const
|
|
|
|
|
{
|
|
|
|
|
const QString line = m_line.simplified();
|
|
|
|
|
|
2013-02-03 20:47:45 +04:00
|
|
|
if (line.isEmpty() || line.startsWith(QLatin1Char('#')))
|
|
|
|
|
return Undefined;
|
|
|
|
|
|
|
|
|
|
const QString id = parseIdentifierBeforeAssign(line);
|
|
|
|
|
if (id.isEmpty())
|
|
|
|
|
return Undefined;
|
|
|
|
|
|
|
|
|
|
if (id == QLatin1String("AM_DEFAULT_SOURCE_EXT"))
|
|
|
|
|
return AmDefaultSourceExt;
|
|
|
|
|
if (id == QLatin1String("bin_PROGRAMS"))
|
|
|
|
|
return BinPrograms;
|
|
|
|
|
if (id == QLatin1String("BUILT_SOURCES"))
|
|
|
|
|
return BuiltSources;
|
|
|
|
|
if (id == QLatin1String("SUBDIRS") || id == QLatin1String("DIST_SUBDIRS"))
|
|
|
|
|
return SubDirs;
|
|
|
|
|
if (id.endsWith(QLatin1String("_SOURCES")))
|
|
|
|
|
return Sources;
|
|
|
|
|
|
|
|
|
|
return Undefined;
|
2011-11-29 14:19:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MakefileParser::parseBinPrograms()
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(m_line.contains(QLatin1String("bin_PROGRAMS")), return);
|
|
|
|
|
const QStringList binPrograms = targetValues();
|
|
|
|
|
|
|
|
|
|
// TODO: are multiple values possible?
|
|
|
|
|
if (binPrograms.size() == 1) {
|
|
|
|
|
QFileInfo info(binPrograms.first());
|
|
|
|
|
m_executable = info.fileName();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MakefileParser::parseSources()
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(m_line.contains(QLatin1String("_SOURCES")), return);
|
|
|
|
|
|
|
|
|
|
bool hasVariables = false;
|
|
|
|
|
m_sources.append(targetValues(&hasVariables));
|
|
|
|
|
|
|
|
|
|
// Skip parsing of Makefile.am for getting the sub directories,
|
|
|
|
|
// as variables have been used. As fallback all sources will be added.
|
|
|
|
|
if (hasVariables)
|
|
|
|
|
addAllSources();
|
|
|
|
|
|
|
|
|
|
// Duplicates might be possible in combination with 'AM_DEFAULT_SOURCE_EXT ='
|
|
|
|
|
m_sources.removeDuplicates();
|
|
|
|
|
|
|
|
|
|
// TODO: Definitions like "SOURCES = ../src.cpp" are ignored currently.
|
|
|
|
|
// This case must be handled correctly in MakefileParser::parseSubDirs(),
|
|
|
|
|
// where the current sub directory must be shortened.
|
|
|
|
|
QStringList::iterator it = m_sources.begin();
|
|
|
|
|
while (it != m_sources.end()) {
|
|
|
|
|
if ((*it).startsWith(QLatin1String("..")))
|
|
|
|
|
it = m_sources.erase(it);
|
|
|
|
|
else
|
|
|
|
|
++it;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MakefileParser::parseDefaultSourceExtensions()
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(m_line.contains(QLatin1String("AM_DEFAULT_SOURCE_EXT")), return);
|
|
|
|
|
const QStringList extensions = targetValues();
|
|
|
|
|
if (extensions.isEmpty()) {
|
|
|
|
|
m_success = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QFileInfo info(m_makefile);
|
|
|
|
|
const QString dirName = info.absolutePath();
|
|
|
|
|
m_sources.append(directorySources(dirName, extensions));
|
|
|
|
|
|
|
|
|
|
// Duplicates might be possible in combination with '_SOURCES ='
|
|
|
|
|
m_sources.removeDuplicates();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MakefileParser::parseSubDirs()
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(m_line.contains(QLatin1String("SUBDIRS")), return);
|
|
|
|
|
if (isCanceled()) {
|
|
|
|
|
m_success = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QFileInfo info(m_makefile);
|
|
|
|
|
const QString path = info.absolutePath();
|
|
|
|
|
const QString makefileName = info.fileName();
|
|
|
|
|
|
|
|
|
|
bool hasVariables = false;
|
|
|
|
|
QStringList subDirs = targetValues(&hasVariables);
|
|
|
|
|
if (hasVariables) {
|
|
|
|
|
// Skip parsing of Makefile.am for getting the sub directories,
|
|
|
|
|
// as variables have been used. As fallback all sources will be added.
|
|
|
|
|
addAllSources();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If the SUBDIRS values contain a '.' or a variable like $(test),
|
|
|
|
|
// all the sub directories of the current folder must get parsed.
|
|
|
|
|
bool hasDotSubDir = false;
|
|
|
|
|
QStringList::iterator it = subDirs.begin();
|
|
|
|
|
while (it != subDirs.end()) {
|
|
|
|
|
// Erase all entries that represent a '.'
|
2012-04-03 11:53:55 +02:00
|
|
|
if ((*it) == QLatin1String(".")) {
|
2011-11-29 14:19:28 +01:00
|
|
|
hasDotSubDir = true;
|
|
|
|
|
it = subDirs.erase(it);
|
|
|
|
|
} else {
|
|
|
|
|
++it;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (hasDotSubDir) {
|
|
|
|
|
// Add all sub directories of the current folder
|
|
|
|
|
QDir dir(path);
|
|
|
|
|
dir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
|
|
|
|
|
foreach (const QFileInfo& info, dir.entryInfoList()) {
|
|
|
|
|
subDirs.append(info.fileName());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
subDirs.removeDuplicates();
|
|
|
|
|
|
|
|
|
|
// Delegate the parsing of all sub directories to a local
|
|
|
|
|
// makefile parser and merge the results
|
|
|
|
|
foreach (const QString& subDir, subDirs) {
|
2012-04-03 11:53:55 +02:00
|
|
|
const QChar slash = QLatin1Char('/');
|
2011-11-29 14:19:28 +01:00
|
|
|
const QString subDirMakefile = path + slash + subDir
|
|
|
|
|
+ slash + makefileName;
|
|
|
|
|
|
|
|
|
|
// Parse sub directory
|
2012-04-11 15:02:09 +02:00
|
|
|
QFile file(subDirMakefile);
|
2011-11-29 14:19:28 +01:00
|
|
|
|
|
|
|
|
// Don't try to parse a file, that might not exist (e. g.
|
|
|
|
|
// if SUBDIRS specifies a 'po' directory).
|
2012-04-11 15:02:09 +02:00
|
|
|
if (!file.exists())
|
2011-11-29 14:19:28 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
MakefileParser parser(subDirMakefile);
|
2015-01-30 10:19:13 +01:00
|
|
|
connect(&parser, &MakefileParser::status, this, &MakefileParser::status);
|
2011-11-29 14:19:28 +01:00
|
|
|
const bool success = parser.parse();
|
|
|
|
|
|
|
|
|
|
// Don't return, try to parse as many sub directories
|
|
|
|
|
// as possible
|
|
|
|
|
if (!success)
|
|
|
|
|
m_success = false;
|
|
|
|
|
|
|
|
|
|
m_makefiles.append(subDir + slash + makefileName);
|
|
|
|
|
|
|
|
|
|
// Append the sources of the sub directory to the
|
|
|
|
|
// current sources
|
|
|
|
|
foreach (const QString& source, parser.sources())
|
|
|
|
|
m_sources.append(subDir + slash + source);
|
|
|
|
|
|
|
|
|
|
// Duplicates might be possible in combination with several
|
|
|
|
|
// "..._SUBDIRS" targets
|
|
|
|
|
m_makefiles.removeDuplicates();
|
|
|
|
|
m_sources.removeDuplicates();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (subDirs.isEmpty())
|
|
|
|
|
m_success = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QStringList MakefileParser::directorySources(const QString &directory,
|
|
|
|
|
const QStringList &extensions)
|
|
|
|
|
{
|
|
|
|
|
if (isCanceled()) {
|
|
|
|
|
m_success = false;
|
|
|
|
|
return QStringList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
emit status(tr("Parsing directory %1").arg(directory));
|
|
|
|
|
|
|
|
|
|
QStringList list; // return value
|
|
|
|
|
|
|
|
|
|
QDir dir(directory);
|
|
|
|
|
dir.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
|
|
|
|
|
|
|
|
|
|
const QFileInfoList infos = dir.entryInfoList();
|
|
|
|
|
foreach (const QFileInfo& info, infos) {
|
|
|
|
|
if (info.isDir()) {
|
|
|
|
|
// Append recursively sources from the sub directory
|
|
|
|
|
const QStringList subDirSources = directorySources(info.absoluteFilePath(),
|
|
|
|
|
extensions);
|
|
|
|
|
const QString dirPath = info.fileName();
|
|
|
|
|
foreach (const QString& subDirSource, subDirSources)
|
2012-04-03 11:53:55 +02:00
|
|
|
list.append(dirPath + QLatin1Char('/') + subDirSource);
|
2011-11-29 14:19:28 +01:00
|
|
|
} else {
|
|
|
|
|
// Check whether the file matches to an extension
|
|
|
|
|
foreach (const QString& extension, extensions) {
|
|
|
|
|
if (info.fileName().endsWith(extension)) {
|
|
|
|
|
list.append(info.fileName());
|
|
|
|
|
appendHeader(list, dir, info.baseName());
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QStringList MakefileParser::targetValues(bool *hasVariables)
|
|
|
|
|
{
|
|
|
|
|
QStringList values;
|
|
|
|
|
if (hasVariables != 0)
|
|
|
|
|
*hasVariables = false;
|
|
|
|
|
|
2012-04-03 11:53:55 +02:00
|
|
|
const int index = m_line.indexOf(QLatin1Char('='));
|
2011-11-29 14:19:28 +01:00
|
|
|
if (index < 0) {
|
|
|
|
|
m_success = false;
|
|
|
|
|
return QStringList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_line.remove(0, index + 1); // remove the 'target = ' prefix
|
|
|
|
|
|
|
|
|
|
bool endReached = false;
|
|
|
|
|
do {
|
|
|
|
|
m_line = m_line.simplified();
|
|
|
|
|
|
|
|
|
|
// Get all values of a line separated by spaces.
|
|
|
|
|
// Values representing a variable like $(value) get
|
|
|
|
|
// removed currently.
|
2012-08-16 11:10:30 +02:00
|
|
|
QStringList lineValues = m_line.split(QLatin1Char(' '), QString::SkipEmptyParts);
|
2011-11-29 14:19:28 +01:00
|
|
|
QStringList::iterator it = lineValues.begin();
|
|
|
|
|
while (it != lineValues.end()) {
|
|
|
|
|
if ((*it).startsWith(QLatin1String("$("))) {
|
|
|
|
|
it = lineValues.erase(it);
|
|
|
|
|
if (hasVariables != 0)
|
|
|
|
|
*hasVariables = true;
|
|
|
|
|
} else {
|
|
|
|
|
++it;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
endReached = lineValues.isEmpty();
|
|
|
|
|
if (!endReached) {
|
2012-04-03 11:53:55 +02:00
|
|
|
const QChar backSlash = QLatin1Char('\\');
|
2011-11-29 14:19:28 +01:00
|
|
|
QString last = lineValues.last();
|
|
|
|
|
if (last.endsWith(backSlash)) {
|
|
|
|
|
// The last value contains a backslash. Remove the
|
|
|
|
|
// backslash and replace the last value.
|
|
|
|
|
lineValues.pop_back();
|
|
|
|
|
last.remove(backSlash);
|
|
|
|
|
if (!last.isEmpty())
|
|
|
|
|
lineValues.push_back(last);
|
|
|
|
|
|
|
|
|
|
values.append(lineValues);
|
|
|
|
|
m_line = m_textStream.readLine();
|
|
|
|
|
endReached = m_line.isNull();
|
|
|
|
|
} else {
|
|
|
|
|
values.append(lineValues);
|
|
|
|
|
endReached = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} while (!endReached);
|
|
|
|
|
|
|
|
|
|
return values;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MakefileParser::appendHeader(QStringList &list, const QDir &dir, const QString &fileName)
|
|
|
|
|
{
|
|
|
|
|
const char *const headerExtensions[] = { ".h", ".hh", ".hg", ".hxx", ".hpp", 0 };
|
|
|
|
|
int i = 0;
|
|
|
|
|
while (headerExtensions[i] != 0) {
|
|
|
|
|
const QString headerFile = fileName + QLatin1String(headerExtensions[i]);
|
|
|
|
|
QFileInfo fileInfo(dir, headerFile);
|
|
|
|
|
if (fileInfo.exists())
|
|
|
|
|
list.append(headerFile);
|
|
|
|
|
++i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-03 20:47:45 +04:00
|
|
|
QString MakefileParser::parseIdentifierBeforeAssign(const QString &line)
|
|
|
|
|
{
|
|
|
|
|
int end = 0;
|
|
|
|
|
for (; end < line.size(); ++end)
|
|
|
|
|
if (!line[end].isLetterOrNumber() && line[end] != QLatin1Char('_'))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
QString ret = line.left(end);
|
|
|
|
|
while (end < line.size() && line[end].isSpace())
|
|
|
|
|
++end;
|
2013-03-04 23:36:09 +04:00
|
|
|
return (end < line.size() && line[end] == QLatin1Char('=')) ? ret : QString();
|
2013-02-03 20:47:45 +04:00
|
|
|
}
|
|
|
|
|
|
2013-04-29 02:31:43 +04:00
|
|
|
QStringList MakefileParser::parseTermsAfterAssign(const QString &line)
|
|
|
|
|
{
|
|
|
|
|
int assignPos = line.indexOf(QLatin1Char('=')) + 1;
|
2015-07-09 01:32:10 +02:00
|
|
|
if (assignPos <= 0 || assignPos >= line.size())
|
2013-04-29 02:31:43 +04:00
|
|
|
return QStringList();
|
2015-07-09 01:32:29 +02:00
|
|
|
|
2015-07-09 01:32:10 +02:00
|
|
|
const QStringList parts = Utils::QtcProcess::splitArgs(line.mid(assignPos));
|
2015-07-09 01:32:29 +02:00
|
|
|
QStringList result;
|
|
|
|
|
for (int i = 0; i < parts.count(); ++i) {
|
|
|
|
|
const QString cur = parts.at(i);
|
|
|
|
|
const QString next = (i == parts.count() - 1) ? QString() : parts.at(i + 1);
|
|
|
|
|
if (cur == QLatin1String("-D") || cur == QLatin1String("-U") || cur == QLatin1String("-I")) {
|
|
|
|
|
result << cur + next;
|
|
|
|
|
++i;
|
|
|
|
|
} else {
|
|
|
|
|
result << cur;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
2013-04-29 02:31:43 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MakefileParser::maybeParseDefine(const QString &term)
|
|
|
|
|
{
|
|
|
|
|
if (term.startsWith(QLatin1String("-D"))) {
|
|
|
|
|
QString def = term.mid(2); // remove the "-D"
|
|
|
|
|
QByteArray data = def.toUtf8();
|
|
|
|
|
int pos = data.indexOf('=');
|
|
|
|
|
if (pos >= 0)
|
|
|
|
|
data[pos] = ' ';
|
|
|
|
|
m_defines += (QByteArray("#define ") + data + '\n');
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MakefileParser::maybeParseInclude(const QString &term, const QString &dirName)
|
|
|
|
|
{
|
|
|
|
|
if (term.startsWith(QLatin1String("-I"))) {
|
|
|
|
|
QString includePath = term.mid(2); // remove the "-I"
|
|
|
|
|
if (includePath == QLatin1String("."))
|
|
|
|
|
includePath = dirName;
|
|
|
|
|
if (!includePath.isEmpty())
|
|
|
|
|
m_includePaths += includePath;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MakefileParser::maybeParseCFlag(const QString &term)
|
|
|
|
|
{
|
|
|
|
|
if (term.startsWith(QLatin1Char('-'))) {
|
|
|
|
|
m_cflags += term;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MakefileParser::maybeParseCXXFlag(const QString &term)
|
|
|
|
|
{
|
|
|
|
|
if (term.startsWith(QLatin1Char('-'))) {
|
|
|
|
|
m_cxxflags += term;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-09 13:27:27 +02:00
|
|
|
bool MakefileParser::maybeParseCPPFlag(const QString &term)
|
|
|
|
|
{
|
|
|
|
|
if (term.startsWith(QLatin1Char('-'))) {
|
|
|
|
|
m_cppflags += term;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-29 14:19:28 +01:00
|
|
|
void MakefileParser::addAllSources()
|
|
|
|
|
{
|
|
|
|
|
QStringList extensions;
|
|
|
|
|
extensions << QLatin1String(".c")
|
|
|
|
|
<< QLatin1String(".cpp")
|
|
|
|
|
<< QLatin1String(".cc")
|
|
|
|
|
<< QLatin1String(".cxx")
|
|
|
|
|
<< QLatin1String(".ccg");
|
|
|
|
|
QFileInfo info(m_makefile);
|
|
|
|
|
m_sources.append(directorySources(info.absolutePath(), extensions));
|
|
|
|
|
m_sources.removeDuplicates();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MakefileParser::parseIncludePaths()
|
|
|
|
|
{
|
|
|
|
|
QFileInfo info(m_makefile);
|
|
|
|
|
const QString dirName = info.absolutePath();
|
|
|
|
|
|
2012-04-11 15:02:09 +02:00
|
|
|
QFile file(dirName + QLatin1String("/Makefile"));
|
|
|
|
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
2011-11-29 14:19:28 +01:00
|
|
|
return;
|
|
|
|
|
|
2013-04-29 02:31:43 +04:00
|
|
|
// TODO: Targets are ignored at this moment.
|
|
|
|
|
// Whether it is worth to improve this, depends on whether
|
2011-11-29 14:19:28 +01:00
|
|
|
// we want to parse the generated Makefile at all or whether we want to
|
|
|
|
|
// improve the Makefile.am parsing to be aware of variables.
|
2012-04-11 15:02:09 +02:00
|
|
|
QTextStream textStream(&file);
|
2011-11-29 14:19:28 +01:00
|
|
|
QString line;
|
|
|
|
|
do {
|
|
|
|
|
line = textStream.readLine();
|
2015-07-09 01:32:10 +02:00
|
|
|
while (line.endsWith(QLatin1Char('\\'))) {
|
|
|
|
|
line.chop(1);
|
|
|
|
|
QString next = textStream.readLine();
|
|
|
|
|
line.append(next);
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-29 02:31:43 +04:00
|
|
|
const QString varName = parseIdentifierBeforeAssign(line);
|
|
|
|
|
if (varName.isEmpty())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (varName == QLatin1String("DEFS")) {
|
|
|
|
|
foreach (const QString &term, parseTermsAfterAssign(line))
|
|
|
|
|
maybeParseDefine(term);
|
|
|
|
|
} else if (varName.endsWith(QLatin1String("INCLUDES"))) {
|
|
|
|
|
foreach (const QString &term, parseTermsAfterAssign(line))
|
|
|
|
|
maybeParseInclude(term, dirName);
|
|
|
|
|
} else if (varName.endsWith(QLatin1String("CFLAGS"))) {
|
|
|
|
|
foreach (const QString &term, parseTermsAfterAssign(line))
|
|
|
|
|
maybeParseDefine(term) || maybeParseInclude(term, dirName)
|
|
|
|
|
|| maybeParseCFlag(term);
|
2015-07-09 13:27:27 +02:00
|
|
|
} else if (varName.endsWith(QLatin1String("CXXFLAGS"))) {
|
2013-04-29 02:31:43 +04:00
|
|
|
foreach (const QString &term, parseTermsAfterAssign(line))
|
|
|
|
|
maybeParseDefine(term) || maybeParseInclude(term, dirName)
|
|
|
|
|
|| maybeParseCXXFlag(term);
|
2015-07-09 13:27:27 +02:00
|
|
|
} else if (varName.endsWith(QLatin1String("CPPFLAGS"))) {
|
|
|
|
|
foreach (const QString &term, parseTermsAfterAssign(line))
|
|
|
|
|
maybeParseDefine(term) || maybeParseInclude(term, dirName)
|
|
|
|
|
|| maybeParseCPPFlag(term);
|
2011-11-29 14:19:28 +01:00
|
|
|
}
|
|
|
|
|
} while (!line.isNull());
|
|
|
|
|
|
|
|
|
|
m_includePaths.removeDuplicates();
|
2013-04-29 02:31:43 +04:00
|
|
|
m_cflags.removeDuplicates();
|
|
|
|
|
m_cxxflags.removeDuplicates();
|
2011-11-29 14:19:28 +01:00
|
|
|
}
|