summaryrefslogtreecommitdiff
path: root/src/lib/buildgraph/automoc.cpp
diff options
context:
space:
mode:
authorJoerg Bornemann <joerg.bornemann@digia.com>2013-08-02 13:57:26 +0200
committerJoerg Bornemann <joerg.bornemann@digia.com>2013-11-27 11:49:01 +0100
commit006824f89c4f298f19c45f4f4585b4452cd2d2b9 (patch)
tree0007c73137e7d167cefa4e5611a01803e69fa5fd /src/lib/buildgraph/automoc.cpp
parentdbb39fc1fce3686a5161d68e89e96086fc664556 (diff)
downloadqbs-dynablaster.tar.gz
introduce class BuildGraphNodedynablaster
To support different types of nodes in the build graph, we introduce the base class BuildGraphNode. Artifact now derives from BuildGraphNode. A - yet unused - RuleNode class is introduced that represents a rule in the build graph. Change-Id: Ie1ad5e7a9e65bfd5f99d3e824737516053de0f94 ***new artifacts hash in ProductBuildData Change-Id: I50521ec64f734bfb3662759076fa5e7912ac084e ***automoc fixup Change-Id: Ie2bb228ae38d63deccc600d67d283bc3beda9fec slightly nicer rule debug output Change-Id: I60ddef73cd7f0a67055f2d56e6dbe7fa45ddd450 create RuleNode objects and add them to roots Change-Id: I51a0f89b98cda524d34888ab758d7bd397d82f00 ***execute rule nodes on build Change-Id: I291c32868cd982e37393d6bc8d696f2b63fbff50 ***ArtifactSet::fromNodeSet Change-Id: I7586bcfbe43406c22b1ee1a1fd826beaa247164f ***update after rebase Change-Id: I5f73afc80b746b11eeb83aeadf29c2358accbab8 ***phonytarget Change-Id: I587b7e072e54b866e8d5ea37c874e6a8baa550e0 update after rebase Change-Id: I6017c0cbe9244fea04d513f53e3a2a85092bf962 skip nodes early We must skip Building and Built nodes. m_leaves can contain duplicates now. Change-Id: If275106a47c403a455103f4deeb20049548007f5 debug message Change-Id: I90e238eef72a8a02fb0a9f2c77715f5f15c1442d disable phony thingy Change-Id: I7bb60b850b96b65ab738c11e96c3a84cbe58d2f7 connect each output of a rule to the rule itself Change-Id: I159d76c4b63094058cc9a07ccc2d0b67c7ce06e6 TagScanner Change-Id: I4741e48cd674c0ca830ee1b4d05b59a8c542694f TagScanner deps Change-Id: If3e43a7ac25616cd151229684a085ac8ee787645 update after rebase Change-Id: I58d49a5ed1049a17733fc2154588f12c1cda53e6 only root tag scanners in product Change-Id: Ia94732a5632156a5ec3c5518c9596cd4cefac105 run TagScanners Change-Id: I869a183f2da23a43957a6df45dc5a1b30b10af92 TagScannerRunner Change-Id: Id3c5fac73e6fb84e56d6ab1d48a959f3677f7a67 crash fix Change-Id: Ie3c26dbed41ab4615915a08913c495868c3a8910 more TagScanRunner Change-Id: I80b79f101c0f4d802fb4f6515c0848e369fed066 handle removal of filetags Change-Id: Icdd8d05c2e26953f7b12d968aa5dfcc23928b9ba Qt4 build fix Change-Id: Ie5fcb64e36ddc5004003183bea7243536bc8ab15 do not waste space with type information Change-Id: I7b9354e6fceead228ba335723b9addeb701bef56 update nodes that must get new transformers Change-Id: I06cd7ffe606ae643393350c5959ef6475343929f update after rebase Change-Id: If080e664972f2950c12fd800a3e4b521e65dca3a only run tag scanners on changed sources And do not call RulesApplicator in bgloader. Change-Id: I5140c91c79a842dab933ad7b328100bdec13cb10 Conflicts: src/lib/buildgraph/buildgraphloader.cpp sketch of moc tagscanners impl Change-Id: I7736c2da1b1742bc3556ef660c163e6c32cbd4c9 Conflicts: share/qbs/modules/Qt/core/core.qbs MocTagScanner Change-Id: I87199e8f355b8b20cf2387f4d4190a20bddae0db fix lib.qbs Change-Id: Ibcb5bc290d3839b04828f8c9b155577634bcc9e4 moctagscanner split Change-Id: Iace5d48483c02b5d33d9ccd54ac07162bfc09d27
Diffstat (limited to 'src/lib/buildgraph/automoc.cpp')
-rw-r--r--src/lib/buildgraph/automoc.cpp344
1 files changed, 0 insertions, 344 deletions
diff --git a/src/lib/buildgraph/automoc.cpp b/src/lib/buildgraph/automoc.cpp
deleted file mode 100644
index 60a1ae318..000000000
--- a/src/lib/buildgraph/automoc.cpp
+++ /dev/null
@@ -1,344 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the Qt Build Suite.
-**
-** 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.
-**
-** GNU Lesser General Public License Usage
-** 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
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-****************************************************************************/
-
-#include "automoc.h"
-#include "productbuilddata.h"
-#include "projectbuilddata.h"
-#include "buildgraph.h"
-#include "rulesapplicator.h"
-#include "scanresultcache.h"
-#include <buildgraph/artifact.h>
-#include <buildgraph/transformer.h>
-#include <language/language.h>
-#include <logging/translator.h>
-#include <tools/error.h>
-#include <tools/fileinfo.h>
-#include <tools/scannerpluginmanager.h>
-
-namespace qbs {
-namespace Internal {
-
-AutoMoc::AutoMoc(const Logger &logger, QObject *parent)
- : QObject(parent)
- , m_scanResultCache(0)
- , m_logger(logger)
-{
-}
-
-void AutoMoc::setScanResultCache(ScanResultCache *scanResultCache)
-{
- m_scanResultCache = scanResultCache;
-}
-
-void AutoMoc::apply(const ResolvedProductPtr &product)
-{
- if (cppScanners().isEmpty() || hppScanners().isEmpty())
- throw ErrorInfo("C++ scanner cannot be loaded.");
-
- Artifact *pluginMetaDataFile = 0;
- Artifact *pchFile = 0;
- QList<QPair<Artifact *, FileType> > artifactsToMoc;
- QSet<QString> includedMocCppFiles;
- const FileTime currentTime = FileTime::currentTime();
- ArtifactList::const_iterator it = product->buildData->artifacts.begin();
- for (; it != product->buildData->artifacts.end(); ++it) {
- Artifact *artifact = *it;
- if (!pchFile || !pluginMetaDataFile) {
- foreach (const FileTag &fileTag, artifact->fileTags) {
- if (fileTag == "cpp_pch")
- pchFile = artifact;
- else if (fileTag == "qt_plugin_metadata")
- pluginMetaDataFile = artifact;
- }
- }
-
- if (!pluginMetaDataFile && artifact->fileTags.contains("qt_plugin_metadata")) {
- if (m_logger.debugEnabled()) {
- m_logger.qbsDebug() << "[AUTOMOC] found Qt plugin metadata file "
- << artifact->filePath();
- }
- pluginMetaDataFile = artifact;
- }
- if (artifact->artifactType != Artifact::SourceFile)
- continue;
- if (artifact->timestamp() < artifact->autoMocTimestamp)
- continue;
- artifact->autoMocTimestamp = currentTime;
- const FileType fileType = AutoMoc::fileType(artifact);
- if (fileType == UnknownFileType)
- continue;
- FileTag mocFileTag;
- bool alreadyMocced = isVictimOfMoc(artifact, fileType, mocFileTag);
- bool hasQObjectMacro;
- scan(artifact, fileType, hasQObjectMacro, includedMocCppFiles);
- if (hasQObjectMacro && !alreadyMocced) {
- artifactsToMoc += qMakePair(artifact, fileType);
- } else if (!hasQObjectMacro && alreadyMocced) {
- unmoc(artifact, mocFileTag);
- }
- }
-
- Artifact *pluginHeaderFile = 0;
- ArtifactsPerFileTagMap artifactsPerFileTag;
- for (int i = artifactsToMoc.count(); --i >= 0;) {
- const QPair<Artifact *, FileType> &p = artifactsToMoc.at(i);
- Artifact * const artifact = p.first;
- FileType fileType = p.second;
- foreach (const FileTag &fileTag, artifact->fileTags) {
- if (fileTag == "moc_hpp") {
- const QString mocFileName = generateMocFileName(artifact, fileType);
- if (includedMocCppFiles.contains(mocFileName)) {
- FileTag newFileTag = "moc_hpp_inc";
- artifact->fileTags -= fileTag;
- artifact->fileTags += newFileTag;
- artifactsPerFileTag[newFileTag].insert(artifact);
- continue;
- }
- } else if (fileTag == "moc_plugin_hpp") {
- if (m_logger.debugEnabled()) {
- m_logger.qbsDebug() << "[AUTOMOC] found Qt plugin header file "
- << artifact->filePath();
- }
- FileTag newFileTag = "moc_hpp";
- artifact->fileTags -= fileTag;
- artifact->fileTags += newFileTag;
- artifactsPerFileTag[newFileTag].insert(artifact);
- pluginHeaderFile = artifact;
- }
- artifactsPerFileTag[fileTag].insert(artifact);
- }
- }
-
- if (pchFile)
- artifactsPerFileTag["cpp_pch"] += pchFile;
- if (!artifactsPerFileTag.isEmpty()) {
- emit reportCommandDescription(QLatin1String("automoc"),
- Tr::tr("Applying moc rules for '%1'.")
- .arg(product->name));
- RulesApplicator(product, artifactsPerFileTag, m_logger).applyAllRules();
- }
- if (pluginHeaderFile && pluginMetaDataFile) {
- // Make every artifact that is dependent of the header file also
- // dependent of the plugin metadata file.
- foreach (Artifact *outputOfHeader, pluginHeaderFile->parents)
- loggedConnect(outputOfHeader, pluginMetaDataFile, m_logger);
- }
-
- product->topLevelProject()->buildData->updateNodesThatMustGetNewTransformer(m_logger);
-}
-
-QString AutoMoc::generateMocFileName(Artifact *artifact, FileType fileType)
-{
- QString mocFileName;
- switch (fileType) {
- case UnknownFileType:
- break;
- case HppFileType:
- mocFileName = "moc_" + FileInfo::baseName(artifact->filePath()) + ".cpp";
- break;
- case CppFileType:
- mocFileName = FileInfo::baseName(artifact->filePath()) + ".moc";
- break;
- }
- return mocFileName;
-}
-
-AutoMoc::FileType AutoMoc::fileType(Artifact *artifact)
-{
- foreach (const FileTag &fileTag, artifact->fileTags)
- if (fileTag == "hpp")
- return HppFileType;
- else if (fileTag == "cpp")
- return CppFileType;
- return UnknownFileType;
-}
-
-void AutoMoc::scan(Artifact *artifact, FileType fileType, bool &hasQObjectMacro,
- QSet<QString> &includedMocCppFiles)
-{
- if (m_logger.traceEnabled())
- m_logger.qbsTrace() << "[AUTOMOC] checks " << relativeArtifactFileName(artifact);
-
- hasQObjectMacro = false;
-
- foreach (ScannerPlugin *scanner, fileType == HppFileType ? hppScanners() : cppScanners()) {
- ScanResultCache::Result scanResult = m_scanResultCache->value(artifact->filePath());
- if (!scanResult.valid) {
- scanResult.valid = true;
- void *opaq = scanner->open(artifact->filePath().utf16(),
- ScanForDependenciesFlag | ScanForFileTagsFlag);
- if (!opaq || !scanner->additionalFileTags)
- continue;
-
- int length = 0;
- const char **szFileTagsFromScanner = scanner->additionalFileTags(opaq, &length);
- if (szFileTagsFromScanner && length > 0) {
- for (int i = length; --i >= 0;)
- scanResult.additionalFileTags += szFileTagsFromScanner[i];
- }
-
- forever {
- int flags = 0;
- const char *szOutFilePath = scanner->next(opaq, &length, &flags);
- if (szOutFilePath == 0)
- break;
- QString includedFilePath = QString::fromLocal8Bit(szOutFilePath, length);
- if (includedFilePath.isEmpty())
- continue;
- bool isLocalInclude = (flags & SC_LOCAL_INCLUDE_FLAG);
- scanResult.deps += ScanResultCache::Dependency(includedFilePath, isLocalInclude);
- }
-
- scanner->close(opaq);
- m_scanResultCache->insert(artifact->filePath(), scanResult);
- }
-
- foreach (const FileTag &tag, scanResult.additionalFileTags) {
- artifact->fileTags.insert(tag);
- if (tag.name().startsWith("moc")) {
- hasQObjectMacro = true;
- if (m_logger.traceEnabled())
- m_logger.qbsTrace() << "[AUTOMOC] finds Q_OBJECT macro";
- }
- }
-
- foreach (const ScanResultCache::Dependency &dependency, scanResult.deps) {
- const QString &includedFilePath = dependency.filePath();
- if (includedFilePath.startsWith("moc_") && includedFilePath.endsWith(".cpp")) {
- if (m_logger.traceEnabled())
- m_logger.qbsTrace() << "[AUTOMOC] finds included file: " << includedFilePath;
- includedMocCppFiles += includedFilePath;
- }
- }
- }
-}
-
-static FileTags provideMocHeaderFileTags()
-{
- FileTags fileTags;
- fileTags << "moc_hpp" << "moc_hpp_inc" << "moc_plugin_hpp";
- return fileTags;
-}
-
-bool AutoMoc::isVictimOfMoc(Artifact *artifact, FileType fileType, FileTag &foundMocFileTag)
-{
- static const FileTags mocHeaderFileTags = provideMocHeaderFileTags();
- static const FileTag mocCppFileTag = "moc_cpp";
- foundMocFileTag.clear();
- switch (fileType) {
- case UnknownFileType:
- break;
- case HppFileType:
- foreach (const FileTag &fileTag, artifact->fileTags) {
- if (mocHeaderFileTags.contains(fileTag)) {
- foundMocFileTag = fileTag;
- break;
- }
- }
- break;
- case CppFileType:
- if (artifact->fileTags.contains(mocCppFileTag))
- foundMocFileTag = mocCppFileTag;
- break;
- }
- return foundMocFileTag.isValid();
-}
-
-void AutoMoc::unmoc(Artifact *artifact, const FileTag &mocFileTag)
-{
- if (m_logger.traceEnabled())
- m_logger.qbsTrace() << "[AUTOMOC] unmoc'ing " << relativeArtifactFileName(artifact);
-
- artifact->fileTags.remove(mocFileTag);
-
- Artifact *generatedMocArtifact = 0;
- foreach (Artifact *parent, artifact->parents) {
- foreach (const FileTag &fileTag, parent->fileTags) {
- if (fileTag == "hpp" || fileTag == "cpp") {
- generatedMocArtifact = parent;
- break;
- }
- }
- }
-
- if (!generatedMocArtifact) {
- m_logger.qbsTrace() << "[AUTOMOC] generated moc artifact could not be found";
- return;
- }
-
- TopLevelProject * const project = artifact->product->topLevelProject();
- if (mocFileTag == "moc_hpp") {
- Artifact *mocObjArtifact = 0;
- foreach (Artifact *parent, generatedMocArtifact->parents) {
- foreach (const FileTag &fileTag, parent->fileTags) {
- if (fileTag == "obj" || fileTag == "fpicobj") {
- mocObjArtifact = parent;
- break;
- }
- }
- }
-
- if (!mocObjArtifact) {
- m_logger.qbsTrace() << "[AUTOMOC] generated moc obj artifact could not be found";
- } else {
- if (m_logger.traceEnabled()) {
- m_logger.qbsTrace() << "[AUTOMOC] removing moc obj artifact "
- << relativeArtifactFileName(mocObjArtifact);
- }
- project->buildData->removeArtifact(mocObjArtifact, m_logger);
- delete mocObjArtifact;
- }
- }
-
- if (m_logger.traceEnabled()) {
- m_logger.qbsTrace() << "[AUTOMOC] removing generated artifact "
- << relativeArtifactFileName(generatedMocArtifact);
- }
- project->buildData->removeArtifact(generatedMocArtifact, m_logger);
- delete generatedMocArtifact;
-}
-
-const QList<ScannerPlugin *> &AutoMoc::cppScanners() const
-{
- if (m_cppScanners.isEmpty())
- m_cppScanners = ScannerPluginManager::scannersForFileTag("cpp");
-
- return m_cppScanners;
-}
-
-const QList<ScannerPlugin *> &AutoMoc::hppScanners() const
-{
- if (m_hppScanners.isEmpty())
- m_hppScanners = ScannerPluginManager::scannersForFileTag("hpp");
-
- return m_hppScanners;
-}
-
-} // namespace Internal
-} // namespace qbs