forked from qt-creator/qt-creator
AutotoolsPM: Hide MakefileParser in cpp
Provide parseMakefile() global function instead. Change-Id: Id2eebfb491f57f43ea0c98cec63de491fdfb9ea0 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -31,11 +31,11 @@ AutotoolsBuildSystem::AutotoolsBuildSystem(Target *target)
|
||||
|
||||
AutotoolsBuildSystem::~AutotoolsBuildSystem() = default;
|
||||
|
||||
static void parseMakefile(QPromise<MakefileParserOutputData> &promise, const QString &makefile)
|
||||
static void parseMakefileImpl(QPromise<MakefileParserOutputData> &promise, const QString &makefile)
|
||||
{
|
||||
MakefileParser parser(makefile);
|
||||
if (parser.parse(QFuture<void>(promise.future())))
|
||||
promise.addResult(parser.outputData());
|
||||
const auto result = parseMakefile(makefile, QFuture<void>(promise.future()));
|
||||
if (result)
|
||||
promise.addResult(*result);
|
||||
else
|
||||
promise.future().cancel();
|
||||
}
|
||||
@@ -46,7 +46,7 @@ void AutotoolsBuildSystem::triggerParsing()
|
||||
|
||||
const auto onSetup = [this, storage](Async<MakefileParserOutputData> &async) {
|
||||
*storage = guardParsingRun();
|
||||
async.setConcurrentCallData(parseMakefile, projectFilePath().toString());
|
||||
async.setConcurrentCallData(parseMakefileImpl, projectFilePath().toString());
|
||||
};
|
||||
const auto onDone = [this, storage](const Async<MakefileParserOutputData> &async) {
|
||||
(*storage)->markAsSuccess();
|
||||
|
||||
@@ -18,24 +18,172 @@ using namespace Utils;
|
||||
|
||||
namespace AutotoolsProjectManager::Internal {
|
||||
|
||||
MakefileParser::MakefileParser(const QString &makefile)
|
||||
: m_makefile(makefile)
|
||||
{}
|
||||
|
||||
bool MakefileParser::parse()
|
||||
/**
|
||||
* @brief Parses the autotools makefile Makefile.am.
|
||||
*
|
||||
* The parser returns the sources, makefiles and executable.
|
||||
* Variables like $(test) are not evaluated. If such a variable
|
||||
* is part of a SOURCES target, a fallback will be done and all
|
||||
* sub directories get parsed for C- and C++ files.
|
||||
*/
|
||||
class MakefileParser : public QObject
|
||||
{
|
||||
QFutureInterface<void> fi;
|
||||
fi.reportStarted(); // The default constructed future is canceled otherwise.
|
||||
return parse(fi.future());
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* @param makefile Filename including path of the autotools
|
||||
* makefile that should be parsed.
|
||||
*/
|
||||
MakefileParser(const QString &makefile) : m_makefile(makefile) {}
|
||||
|
||||
/**
|
||||
* Parses the makefile. Must be invoked at least once, otherwise
|
||||
* the getter functions of MakefileParser will return empty values.
|
||||
* @return True, if the parsing was successful. If false is returned,
|
||||
* the makefile could not be opened.
|
||||
*/
|
||||
bool parse(const QFuture<void> &future);
|
||||
|
||||
MakefileParserOutputData outputData() const { return m_outputData; }
|
||||
|
||||
private:
|
||||
enum TopTarget {
|
||||
Undefined,
|
||||
AmDefaultSourceExt,
|
||||
BinPrograms,
|
||||
BuiltSources,
|
||||
Sources,
|
||||
SubDirs
|
||||
};
|
||||
|
||||
TopTarget topTarget() const;
|
||||
|
||||
/**
|
||||
* Parses the bin_PROGRAM target and stores it in m_executable.
|
||||
*/
|
||||
void parseBinPrograms(QTextStream *textStream);
|
||||
|
||||
/**
|
||||
* Parses all values from a _SOURCE target and appends them to
|
||||
* the m_sources list.
|
||||
*/
|
||||
void parseSources(QTextStream *textStream);
|
||||
|
||||
/**
|
||||
* Parses all sub directories for files having the extension
|
||||
* specified by 'AM_DEFAULT_SOURCE_EXT ='. The result will be
|
||||
* append to the m_sources list. Corresponding header files
|
||||
* will automatically be attached too.
|
||||
*/
|
||||
void parseDefaultSourceExtensions(QTextStream *textStream);
|
||||
|
||||
/**
|
||||
* Parses all sub directories specified by the SUBDIRS target and
|
||||
* adds the found sources to the m_sources list. The found makefiles
|
||||
* get added to the m_makefiles list.
|
||||
*/
|
||||
void parseSubDirs(QTextStream *textStream);
|
||||
|
||||
/**
|
||||
* Helper function for parseDefaultExtensions(). Returns recursively all sources
|
||||
* inside the directory \p directory that match with the extension \p extension.
|
||||
*/
|
||||
QStringList directorySources(const QString &directory, const QStringList &extensions);
|
||||
|
||||
/**
|
||||
* Helper function for all parse-functions. Returns each value of a target as string in
|
||||
* the stringlist. The current line m_line is used as starting point and increased
|
||||
* if the current line ends with a \.
|
||||
*
|
||||
* Example: For the text
|
||||
* \code
|
||||
* my_SOURCES = a.cpp\
|
||||
* b.cpp c.cpp\
|
||||
* d.cpp
|
||||
* \endcode
|
||||
* the string list contains all 4 *.cpp files. m_line is positioned to d.cpp afterwards.
|
||||
* Variables like $(test) are skipped and not part of the return value.
|
||||
*
|
||||
* @param hasVariables Optional output parameter. Is set to true, if the target values
|
||||
* contained a variable like $(test). Note that all variables are not
|
||||
* part of the return value, as they cannot get interpreted currently.
|
||||
*/
|
||||
QStringList targetValues(QTextStream *textStream, bool *hasVariables = nullptr);
|
||||
|
||||
/**
|
||||
* Adds recursively all sources of the current folder to m_sources and removes
|
||||
* all duplicates. The Makefile.am is not parsed, only the folders and files are
|
||||
* handled. This function should only be called, if the sources parsing in the Makefile.am
|
||||
* failed because variables (e.g. $(test)) have been used.
|
||||
*/
|
||||
void addAllSources();
|
||||
|
||||
/**
|
||||
* Adds all include paths to m_includePaths. TODO: Currently this is done
|
||||
* by parsing the generated Makefile. It might be more efficient and reliable
|
||||
* to parse the Makefile.am instead.
|
||||
*/
|
||||
void parseIncludePaths();
|
||||
|
||||
/**
|
||||
* Helper function for MakefileParser::directorySources(). Appends the name of the headerfile
|
||||
* to \p list, if the header could be found in the directory specified by \p dir.
|
||||
* The headerfile base name is defined by \p fileName.
|
||||
*/
|
||||
static void appendHeader(QStringList &list, const QDir &dir, const QString &fileName);
|
||||
|
||||
/**
|
||||
* If line starts with identifier and = goes next, return identifier.
|
||||
* Identifier is valid target name and it matches regexp [a-zA-Z1-9_]+
|
||||
*/
|
||||
static QString parseIdentifierBeforeAssign(const QString &line);
|
||||
|
||||
/**
|
||||
* Parses list of space-separated terms after "="
|
||||
*/
|
||||
static QStringList parseTermsAfterAssign(const QString &line);
|
||||
|
||||
/**
|
||||
* If term is compiler flag -D<macro>, adds macro to defines and returns true.
|
||||
*/
|
||||
bool maybeParseDefine(const QString &term);
|
||||
|
||||
/**
|
||||
* If term is compiler flag -I<path>, adds path to includes and returns true.
|
||||
* @param term Term itself
|
||||
* @param dirName Directory where Makefile placed
|
||||
*/
|
||||
bool maybeParseInclude(const QString &term, const QString &dirName);
|
||||
|
||||
/**
|
||||
* If term is compiler flag -<flag>, adds it to cflags and returns true.
|
||||
*/
|
||||
bool maybeParseCFlag(const QString &term);
|
||||
|
||||
/**
|
||||
* If term is compiler flag -<flag>, adds it to cxxflags and returns true.
|
||||
*/
|
||||
bool maybeParseCXXFlag(const QString &term);
|
||||
|
||||
/**
|
||||
* If term is compiler flag -<flag>, adds it to cppflags and returns true.
|
||||
*/
|
||||
bool maybeParseCPPFlag(const QString &term);
|
||||
|
||||
bool m_success = true; ///< Return value for MakefileParser::parse().
|
||||
bool m_subDirsEmpty = false;///< States if last subdirs var was empty
|
||||
|
||||
QFuture<void> m_future; ///< For periodic checking of cancelled state.
|
||||
|
||||
QString m_makefile; ///< Filename of the makefile
|
||||
MakefileParserOutputData m_outputData;
|
||||
QStringList m_cppflags; ///< The cpp flags, which will be part of both cflags and cxxflags
|
||||
|
||||
QString m_line; ///< Current line of the makefile
|
||||
};
|
||||
|
||||
bool MakefileParser::parse(const QFuture<void> &future)
|
||||
{
|
||||
m_future = future;
|
||||
m_success = true;
|
||||
m_outputData.m_executable.clear();
|
||||
m_outputData.m_sources.clear();
|
||||
m_outputData.m_makefiles.clear();
|
||||
|
||||
QFile file(m_makefile);
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
@@ -46,8 +194,6 @@ bool MakefileParser::parse(const QFuture<void> &future)
|
||||
QFileInfo info(m_makefile);
|
||||
m_outputData.m_makefiles.append(info.fileName());
|
||||
|
||||
emit status(Tr::tr("Parsing %1 in directory %2").arg(info.fileName()).arg(info.absolutePath()));
|
||||
|
||||
QTextStream textStream(&file);
|
||||
|
||||
do {
|
||||
@@ -212,7 +358,6 @@ void MakefileParser::parseSubDirs(QTextStream *textStream)
|
||||
continue;
|
||||
|
||||
MakefileParser parser(subDirMakefile);
|
||||
connect(&parser, &MakefileParser::status, this, &MakefileParser::status);
|
||||
const bool success = parser.parse(m_future);
|
||||
|
||||
// Don't return, try to parse as many sub directories
|
||||
@@ -258,8 +403,6 @@ QStringList MakefileParser::directorySources(const QString &directory,
|
||||
return {};
|
||||
}
|
||||
|
||||
emit status(Tr::tr("Parsing directory %1").arg(directory));
|
||||
|
||||
QStringList list; // return value
|
||||
|
||||
QDir dir(directory);
|
||||
@@ -512,4 +655,13 @@ void MakefileParser::parseIncludePaths()
|
||||
m_outputData.m_cxxflags.removeDuplicates();
|
||||
}
|
||||
|
||||
std::optional<MakefileParserOutputData> parseMakefile(const QString &makefile,
|
||||
const QFuture<void> &future)
|
||||
{
|
||||
MakefileParser parser(makefile);
|
||||
if (parser.parse(future))
|
||||
return parser.outputData();
|
||||
return {};
|
||||
}
|
||||
|
||||
} // AutotoolsProjectManager::Internal
|
||||
|
||||
@@ -6,13 +6,7 @@
|
||||
#include <projectexplorer/projectmacro.h>
|
||||
|
||||
#include <QFuture>
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
#include <QTextStream>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QDir;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace AutotoolsProjectManager::Internal {
|
||||
|
||||
@@ -39,182 +33,7 @@ public:
|
||||
QStringList m_cxxflags;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Parses the autotools makefile Makefile.am.
|
||||
*
|
||||
* The parser returns the sources, makefiles and executable.
|
||||
* Variables like $(test) are not evaluated. If such a variable
|
||||
* is part of a SOURCES target, a fallback will be done and all
|
||||
* sub directories get parsed for C- and C++ files.
|
||||
*/
|
||||
class MakefileParser : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
using Macros = ProjectExplorer::Macros;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @param makefile Filename including path of the autotools
|
||||
* makefile that should be parsed.
|
||||
*/
|
||||
MakefileParser(const QString &makefile);
|
||||
|
||||
/**
|
||||
* Parses the makefile. Must be invoked at least once, otherwise
|
||||
* the getter functions of MakefileParser will return empty values.
|
||||
* @return True, if the parsing was successful. If false is returned,
|
||||
* the makefile could not be opened.
|
||||
*/
|
||||
bool parse();
|
||||
bool parse(const QFuture<void> &future);
|
||||
|
||||
MakefileParserOutputData outputData() const { return m_outputData; }
|
||||
|
||||
signals:
|
||||
/**
|
||||
* Is emitted periodically during parsing the Makefile.am files
|
||||
* and the sub directories. \p status provides a translated
|
||||
* string, that can be shown to indicate the current state
|
||||
* of the parsing.
|
||||
*/
|
||||
void status(const QString &status);
|
||||
|
||||
private:
|
||||
enum TopTarget {
|
||||
Undefined,
|
||||
AmDefaultSourceExt,
|
||||
BinPrograms,
|
||||
BuiltSources,
|
||||
Sources,
|
||||
SubDirs
|
||||
};
|
||||
|
||||
TopTarget topTarget() const;
|
||||
|
||||
/**
|
||||
* Parses the bin_PROGRAM target and stores it in m_executable.
|
||||
*/
|
||||
void parseBinPrograms(QTextStream *textStream);
|
||||
|
||||
/**
|
||||
* Parses all values from a _SOURCE target and appends them to
|
||||
* the m_sources list.
|
||||
*/
|
||||
void parseSources(QTextStream *textStream);
|
||||
|
||||
/**
|
||||
* Parses all sub directories for files having the extension
|
||||
* specified by 'AM_DEFAULT_SOURCE_EXT ='. The result will be
|
||||
* append to the m_sources list. Corresponding header files
|
||||
* will automatically be attached too.
|
||||
*/
|
||||
void parseDefaultSourceExtensions(QTextStream *textStream);
|
||||
|
||||
/**
|
||||
* Parses all sub directories specified by the SUBDIRS target and
|
||||
* adds the found sources to the m_sources list. The found makefiles
|
||||
* get added to the m_makefiles list.
|
||||
*/
|
||||
void parseSubDirs(QTextStream *textStream);
|
||||
|
||||
/**
|
||||
* Helper function for parseDefaultExtensions(). Returns recursively all sources
|
||||
* inside the directory \p directory that match with the extension \p extension.
|
||||
*/
|
||||
QStringList directorySources(const QString &directory,
|
||||
const QStringList &extensions);
|
||||
|
||||
/**
|
||||
* Helper function for all parse-functions. Returns each value of a target as string in
|
||||
* the stringlist. The current line m_line is used as starting point and increased
|
||||
* if the current line ends with a \.
|
||||
*
|
||||
* Example: For the text
|
||||
* \code
|
||||
* my_SOURCES = a.cpp\
|
||||
* b.cpp c.cpp\
|
||||
* d.cpp
|
||||
* \endcode
|
||||
* the string list contains all 4 *.cpp files. m_line is positioned to d.cpp afterwards.
|
||||
* Variables like $(test) are skipped and not part of the return value.
|
||||
*
|
||||
* @param hasVariables Optional output parameter. Is set to true, if the target values
|
||||
* contained a variable like $(test). Note that all variables are not
|
||||
* part of the return value, as they cannot get interpreted currently.
|
||||
*/
|
||||
QStringList targetValues(QTextStream *textStream, bool *hasVariables = nullptr);
|
||||
|
||||
/**
|
||||
* Adds recursively all sources of the current folder to m_sources and removes
|
||||
* all duplicates. The Makefile.am is not parsed, only the folders and files are
|
||||
* handled. This function should only be called, if the sources parsing in the Makefile.am
|
||||
* failed because variables (e.g. $(test)) have been used.
|
||||
*/
|
||||
void addAllSources();
|
||||
|
||||
/**
|
||||
* Adds all include paths to m_includePaths. TODO: Currently this is done
|
||||
* by parsing the generated Makefile. It might be more efficient and reliable
|
||||
* to parse the Makefile.am instead.
|
||||
*/
|
||||
void parseIncludePaths();
|
||||
|
||||
/**
|
||||
* Helper function for MakefileParser::directorySources(). Appends the name of the headerfile
|
||||
* to \p list, if the header could be found in the directory specified by \p dir.
|
||||
* The headerfile base name is defined by \p fileName.
|
||||
*/
|
||||
static void appendHeader(QStringList &list, const QDir &dir, const QString &fileName);
|
||||
|
||||
/**
|
||||
* If line starts with identifier and = goes next, return identifier.
|
||||
* Identifier is valid target name and it matches regexp [a-zA-Z1-9_]+
|
||||
*/
|
||||
static QString parseIdentifierBeforeAssign(const QString &line);
|
||||
|
||||
/**
|
||||
* Parses list of space-separated terms after "="
|
||||
*/
|
||||
static QStringList parseTermsAfterAssign(const QString &line);
|
||||
|
||||
/**
|
||||
* If term is compiler flag -D<macro>, adds macro to defines and returns true.
|
||||
*/
|
||||
bool maybeParseDefine(const QString &term);
|
||||
|
||||
/**
|
||||
* If term is compiler flag -I<path>, adds path to includes and returns true.
|
||||
* @param term Term itself
|
||||
* @param dirName Directory where Makefile placed
|
||||
*/
|
||||
bool maybeParseInclude(const QString &term, const QString &dirName);
|
||||
|
||||
/**
|
||||
* If term is compiler flag -<flag>, adds it to cflags and returns true.
|
||||
*/
|
||||
bool maybeParseCFlag(const QString &term);
|
||||
|
||||
/**
|
||||
* If term is compiler flag -<flag>, adds it to cxxflags and returns true.
|
||||
*/
|
||||
bool maybeParseCXXFlag(const QString &term);
|
||||
|
||||
/**
|
||||
* If term is compiler flag -<flag>, adds it to cppflags and returns true.
|
||||
*/
|
||||
bool maybeParseCPPFlag(const QString &term);
|
||||
|
||||
bool m_success = false; ///< Return value for MakefileParser::parse().
|
||||
bool m_subDirsEmpty = false;///< States if last subdirs var was empty
|
||||
|
||||
QFuture<void> m_future; ///< For periodic checking of cancelled state.
|
||||
|
||||
QString m_makefile; ///< Filename of the makefile
|
||||
MakefileParserOutputData m_outputData;
|
||||
QStringList m_cppflags; ///< The cpp flags, which will be part of both cflags and cxxflags
|
||||
|
||||
QString m_line; ///< Current line of the makefile
|
||||
};
|
||||
std::optional<MakefileParserOutputData> parseMakefile(const QString &makefile,
|
||||
const QFuture<void> &future);
|
||||
|
||||
} // AutotoolsProjectManager::Internal
|
||||
|
||||
Reference in New Issue
Block a user