From 7688754b379e0f1d558e815d6ea2e65b14396db6 Mon Sep 17 00:00:00 2001 From: Sergey Shambir <sergey.shambir.auto@gmail.com> Date: Mon, 29 Apr 2013 02:31:43 +0400 Subject: [PATCH] Autotools: added parsing defines and C/C++ flags from Makefile Change-Id: I7443ba3ada97e4abac5560bb5399ec96e065acee Reviewed-by: hjk <hjk121@nokiamail.com> --- .../autotoolsproject.cpp | 8 +- .../makefileparser.cpp | 102 ++++++++++++++++-- .../autotoolsprojectmanager/makefileparser.h | 49 +++++++++ .../makefileparserthread.cpp | 21 ++++ .../makefileparserthread.h | 21 ++++ 5 files changed, 188 insertions(+), 13 deletions(-) diff --git a/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp b/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp index 25ea5b47a6b..b9f69f887f6 100644 --- a/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp +++ b/src/plugins/autotoolsprojectmanager/autotoolsproject.cpp @@ -411,7 +411,10 @@ void AutotoolsProject::updateCppCodeModel() if (!modelManager) return; - const QStringList cxxflags; // FIXME: Autotools should be able to do better than this! + const QStringList cflags = m_makefileParserThread->cflags(); + QStringList cxxflags = m_makefileParserThread->cxxflags(); + if (cxxflags.isEmpty()) + cxxflags = cflags; CppTools::CppModelManagerInterface::ProjectInfo pinfo = modelManager->projectInfo(this); pinfo.clearProjectParts(); @@ -420,7 +423,7 @@ void AutotoolsProject::updateCppCodeModel() if (activeTarget()) { ProjectExplorer::Kit *k = activeTarget()->kit(); ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(k); - part->evaluateToolchain(tc, cxxflags, cxxflags, + part->evaluateToolchain(tc, cxxflags, cflags, SysRootKitInformation::sysRoot(k)); } @@ -428,6 +431,7 @@ void AutotoolsProject::updateCppCodeModel() part->files << CppTools::ProjectFile(file, CppTools::ProjectFile::CXXSource); part->includePaths += m_makefileParserThread->includePaths(); + part->defines += m_makefileParserThread->defines(); pinfo.appendProjectPart(part); modelManager->updateProjectInfo(pinfo); diff --git a/src/plugins/autotoolsprojectmanager/makefileparser.cpp b/src/plugins/autotoolsprojectmanager/makefileparser.cpp index 760dcb9d903..f1cbae544e0 100644 --- a/src/plugins/autotoolsprojectmanager/makefileparser.cpp +++ b/src/plugins/autotoolsprojectmanager/makefileparser.cpp @@ -123,6 +123,21 @@ QStringList MakefileParser::includePaths() const return m_includePaths; } +QByteArray MakefileParser::defines() const +{ + return m_defines; +} + +QStringList MakefileParser::cflags() const +{ + return m_cflags; +} + +QStringList MakefileParser::cxxflags() const +{ + return m_cxxflags; +} + void MakefileParser::cancel() { QMutexLocker locker(&m_mutex); @@ -424,6 +439,59 @@ QString MakefileParser::parseIdentifierBeforeAssign(const QString &line) return (end < line.size() && line[end] == QLatin1Char('=')) ? ret : QString(); } +QStringList MakefileParser::parseTermsAfterAssign(const QString &line) +{ + int assignPos = line.indexOf(QLatin1Char('=')) + 1; + if (assignPos >= line.size()) + return QStringList(); + return line.mid(assignPos).split(QLatin1Char(' '), QString::SkipEmptyParts); +} + +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; +} + void MakefileParser::addAllSources() { QStringList extensions; @@ -446,25 +514,37 @@ void MakefileParser::parseIncludePaths() if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return; - // TODO: The parsing is done very poor. Comments are ignored and targets - // are ignored too. Whether it is worth to improve this, depends on whether + // TODO: Targets are ignored at this moment. + // Whether it is worth to improve this, depends on whether // we want to parse the generated Makefile at all or whether we want to // improve the Makefile.am parsing to be aware of variables. QTextStream textStream(&file); QString line; do { line = textStream.readLine(); - QStringList terms = line.split(QLatin1Char(' '), QString::SkipEmptyParts); - foreach (const QString &term, terms) { - if (term.startsWith(QLatin1String("-I"))) { - QString includePath = term.right(term.length() - 2); // remove the "-I" - if (includePath == QLatin1String(".")) - includePath = dirName; - if (!includePath.isEmpty()) - m_includePaths += includePath; - } + 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); + } else if (varName.endsWith(QLatin1String("CPPFLAGS")) + || varName.endsWith(QLatin1String("CXXFLAGS"))) { + foreach (const QString &term, parseTermsAfterAssign(line)) + maybeParseDefine(term) || maybeParseInclude(term, dirName) + || maybeParseCXXFlag(term); } } while (!line.isNull()); m_includePaths.removeDuplicates(); + m_cflags.removeDuplicates(); + m_cxxflags.removeDuplicates(); } diff --git a/src/plugins/autotoolsprojectmanager/makefileparser.h b/src/plugins/autotoolsprojectmanager/makefileparser.h index c62ac2c6c39..9638cebba7c 100644 --- a/src/plugins/autotoolsprojectmanager/makefileparser.h +++ b/src/plugins/autotoolsprojectmanager/makefileparser.h @@ -96,6 +96,25 @@ public: */ QStringList includePaths() const; + /** + * @return Concatenated normalized defines, just like in code: + * @code + * #define X12_DEPRECATED __attribute__((deprecated)) + * #define X12_HAS_DEPRECATED + * @endcode + */ + QByteArray defines() const; + + /** + * @return List of compiler flags for C. + */ + QStringList cflags() const; + + /** + * @return List of compiler flags for C++. + */ + QStringList cxxflags() const; + /** * Cancels the parsing. Calling this method only makes sense, if the * parser runs in a different thread than the caller of this method. @@ -211,6 +230,33 @@ private: */ 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); + private: bool m_success; ///< Return value for MakefileParser::parse(). @@ -222,6 +268,9 @@ private: QStringList m_sources; ///< Return value for MakefileParser::sources() QStringList m_makefiles; ///< Return value for MakefileParser::makefiles() QStringList m_includePaths; ///< Return value for MakefileParser::includePaths() + QByteArray m_defines; ///< Return value for MakefileParser::defines() + QStringList m_cflags; ///< Return value for MakefileParser::cflags() + QStringList m_cxxflags; ///< Return value for MakefileParser::cxxflags() QString m_line; ///< Current line of the makefile QTextStream m_textStream; ///< Textstream that represents the makefile diff --git a/src/plugins/autotoolsprojectmanager/makefileparserthread.cpp b/src/plugins/autotoolsprojectmanager/makefileparserthread.cpp index c19f91f53a7..a6d45870ff8 100644 --- a/src/plugins/autotoolsprojectmanager/makefileparserthread.cpp +++ b/src/plugins/autotoolsprojectmanager/makefileparserthread.cpp @@ -72,6 +72,24 @@ QStringList MakefileParserThread::includePaths() const return m_includePaths; } +QByteArray MakefileParserThread::defines() const +{ + QMutexLocker locker(&m_mutex); + return m_defines; +} + +QStringList MakefileParserThread::cflags() const +{ + QMutexLocker locker(&m_mutex); + return m_cflags; +} + +QStringList MakefileParserThread::cxxflags() const +{ + QMutexLocker locker(&m_mutex); + return m_cxxflags; +} + bool MakefileParserThread::hasError() const { QMutexLocker locker(&m_mutex); @@ -102,4 +120,7 @@ void MakefileParserThread::run() m_sources = m_parser.sources(); m_makefiles = m_parser.makefiles(); m_includePaths = m_parser.includePaths(); + m_defines = m_parser.defines(); + m_cflags = m_parser.cflags(); + m_cxxflags = m_parser.cxxflags(); } diff --git a/src/plugins/autotoolsprojectmanager/makefileparserthread.h b/src/plugins/autotoolsprojectmanager/makefileparserthread.h index 05eff169efb..c119de7c550 100644 --- a/src/plugins/autotoolsprojectmanager/makefileparserthread.h +++ b/src/plugins/autotoolsprojectmanager/makefileparserthread.h @@ -86,6 +86,24 @@ public: */ QStringList includePaths() const; + /** + * @return Concatenated defines. Should be invoked, after the signal + * finished() has been emitted. + */ + QByteArray defines() const; + + /** + * @return List of compiler flags for C. Should be invoked, after the signal + * finished() has been emitted. + */ + QStringList cflags() const; + + /** + * @return List of compiler flags for C++. Should be invoked, after the + * signal finished() has been emitted. + */ + QStringList cxxflags() const; + /** * @return True, if an error occurred during the parsing. Should be invoked, * after the signal finished() has been emitted. @@ -122,6 +140,9 @@ private: QStringList m_sources; ///< Return value for MakefileParserThread::sources() QStringList m_makefiles; ///< Return value for MakefileParserThread::makefiles() QStringList m_includePaths; ///< Return value for MakefileParserThread::includePaths() + QByteArray m_defines; ///< Return value for MakefileParserThread::defines() + QStringList m_cflags; ///< Return value for MakefileParserThread::cflags() + QStringList m_cxxflags; ///< Return value for MakefileParserThread::cxxflags() }; } // namespace Internal -- GitLab