瀏覽代碼

Merge topic 'AutomocFindQ_OBJECTAlwaysInHeader'

5e8e9ad automoc: always run moc on the cpp file if there is a foo.moc included
ea8ac9f Add copyright notices
56aa6ff automoc:run moc on the header if the source file contains include "foo.moc"
David Cole 14 年之前
父節點
當前提交
61b49402d7
共有 6 個文件被更改,包括 181 次插入86 次删除
  1. 93 85
      Source/cmQtAutomoc.cxx
  2. 16 0
      Source/cmQtAutomoc.h
  3. 1 1
      Tests/QtAutomoc/CMakeLists.txt
  4. 39 0
      Tests/QtAutomoc/foo.cpp
  5. 28 0
      Tests/QtAutomoc/foo.h
  6. 4 0
      Tests/QtAutomoc/main.cpp

+ 93 - 85
Source/cmQtAutomoc.cxx

@@ -1,3 +1,16 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2004-2011 Kitware, Inc.
+  Copyright 2011 Alexander Neundorf ([email protected])
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+
 #include "cmGlobalGenerator.h"
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
@@ -377,9 +390,8 @@ bool cmQtAutomoc::RunAutomocQt4()
 
   // key = moc source filepath, value = moc output filepath
   std::map<std::string, std::string> includedMocs;
-  // key = moc source filepath, value = moc output filename
-  std::map<std::string, std::string> notIncludedMocs;
-
+  // collect all headers which may need to be mocced
+  std::set<std::string> headerFiles;
 
   std::vector<std::string> sourceFiles;
   cmSystemTools::ExpandListArgument(this->Sources, sourceFiles);
@@ -393,34 +405,22 @@ bool cmQtAutomoc::RunAutomocQt4()
       {
       std::cout << "AUTOMOC: Checking " << absFilename << std::endl;
       }
-    this->ParseCppFile(absFilename, includedMocs, notIncludedMocs);
+    this->ParseCppFile(absFilename, includedMocs, headerFiles);
     }
 
-  std::vector<std::string> headerFiles;
-  cmSystemTools::ExpandListArgument(this->Headers, headerFiles);
-  for (std::vector<std::string>::const_iterator it = headerFiles.begin();
-       it != headerFiles.end();
+  std::vector<std::string> headerFilesVec;
+  cmSystemTools::ExpandListArgument(this->Headers, headerFilesVec);
+  for (std::vector<std::string>::const_iterator it = headerFilesVec.begin();
+       it != headerFilesVec.end();
        ++it)
     {
-    const std::string &absFilename = *it;
-    if (this->Verbose)
-      {
-      std::cout << "AUTOMOC: Checking " << absFilename << std::endl;
-      }
-    if (includedMocs.find(absFilename) == includedMocs.end()
-              && notIncludedMocs.find(absFilename) == notIncludedMocs.end())
-      {
-      // if this header is not getting processed yet and is explicitly
-      // mentioned for the automoc the moc is run unconditionally on the
-      // header and the resulting file is included in the _automoc.cpp file
-      // (unless there's a .cpp file later on that includes the moc from
-      // this header)
-      const std::string currentMoc = "moc_" + cmsys::SystemTools::
-                         GetFilenameWithoutLastExtension(absFilename) + ".cpp";
-      notIncludedMocs[absFilename] = currentMoc;
-      }
+    headerFiles.insert(*it);
     }
 
+  // key = moc source filepath, value = moc output filename
+  std::map<std::string, std::string> notIncludedMocs;
+  this->ParseHeaders(headerFiles, includedMocs, notIncludedMocs);
+
   // run moc on all the moc's that are #included in source files
   for(std::map<std::string, std::string>::const_iterator
                                                      it = includedMocs.begin();
@@ -487,12 +487,11 @@ bool cmQtAutomoc::RunAutomocQt4()
 
 void cmQtAutomoc::ParseCppFile(const std::string& absFilename,
                            std::map<std::string, std::string>& includedMocs,
-                           std::map<std::string, std::string>& notIncludedMocs)
+                           std::set<std::string>& absHeaders)
 {
   cmsys::RegularExpression mocIncludeRegExp(
               "[\n][ \t]*#[ \t]*include[ \t]+"
               "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
-  cmsys::RegularExpression qObjectRegExp("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]");
   std::list<std::string> headerExtensions;
   headerExtensions.push_back(".h");
   headerExtensions.push_back(".hpp");
@@ -520,52 +519,7 @@ void cmQtAutomoc::ParseCppFile(const std::string& absFilename,
                    cmsys::SystemTools::GetRealPath(absFilename.c_str())) + '/';
 
   std::string::size_type matchOffset = 0;
-  if (!mocIncludeRegExp.find(contentsString.c_str()))
-    {
-    // no moc #include, look whether we need to create a moc from
-    // the .h nevertheless
-    const std::string basename =
-              cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename);
-    for(std::list<std::string>::const_iterator ext = headerExtensions.begin();
-        ext != headerExtensions.end();
-        ++ext)
-      {
-      const std::string headername = absPath + basename + (*ext);
-      if (cmsys::SystemTools::FileExists(headername.c_str())
-              && includedMocs.find(headername) == includedMocs.end()
-              && notIncludedMocs.find(headername) == notIncludedMocs.end())
-        {
-        const std::string currentMoc = "moc_" + basename + ".cpp";
-        const std::string contents = this->ReadAll(headername);
-        if (qObjectRegExp.find(contents))
-          {
-          //std::cout << "header contains Q_OBJECT macro";
-          notIncludedMocs[headername] = currentMoc;
-          }
-        break;
-        }
-      }
-    for(std::list<std::string>::const_iterator ext = headerExtensions.begin();
-        ext != headerExtensions.end();
-        ++ext)
-      {
-      const std::string privateHeaderName = absPath+basename+"_p"+(*ext);
-      if (cmsys::SystemTools::FileExists(privateHeaderName.c_str())
-          && includedMocs.find(privateHeaderName) == includedMocs.end()
-          && notIncludedMocs.find(privateHeaderName) == notIncludedMocs.end())
-        {
-        const std::string currentMoc = "moc_" + basename + "_p.cpp";
-        const std::string contents = this->ReadAll(privateHeaderName);
-        if (qObjectRegExp.find(contents))
-          {
-          //std::cout << "header contains Q_OBJECT macro";
-          notIncludedMocs[privateHeaderName] = currentMoc;
-          }
-        break;
-        }
-      }
-    }
-  else
+  if (mocIncludeRegExp.find(contentsString.c_str()))
     {
     // for every moc include in the file
     do
@@ -581,17 +535,13 @@ void cmQtAutomoc::ParseCppFile(const std::string& absFilename,
       // the Q_OBJECT class declaration in a header file.
       // If the moc include is of the foo.moc style we need to look for
       // a Q_OBJECT macro in the current source file, if it contains the
-      // macro we generate the moc file from the source file, else from the
-      // header.
+      // macro we generate the moc file from the source file.
       // Q_OBJECT
-      if (moc_style || !qObjectRegExp.find(contentsString))
+      if (moc_style)
         {
-        if (moc_style)
-          {
-          // basename should be the part of the moc filename used for
-          // finding the correct header, so we need to remove the moc_ part
-          basename = basename.substr(4);
-          }
+        // basename should be the part of the moc filename used for
+        // finding the correct header, so we need to remove the moc_ part
+        basename = basename.substr(4);
 
         bool headerFound = false;
         for(std::list<std::string>::const_iterator ext =
@@ -604,7 +554,6 @@ void cmQtAutomoc::ParseCppFile(const std::string& absFilename,
             {
             headerFound = true;
             includedMocs[sourceFilePath] = currentMoc;
-            notIncludedMocs.erase(sourceFilePath);
             break;
             }
           }
@@ -628,7 +577,6 @@ void cmQtAutomoc::ParseCppFile(const std::string& absFilename,
                 {
                 headerFound = true;
                 includedMocs[sourceFilePath] = currentMoc;
-                notIncludedMocs.erase(sourceFilePath);
                 break;
                 }
               }
@@ -658,11 +606,71 @@ void cmQtAutomoc::ParseCppFile(const std::string& absFilename,
       else
         {
         includedMocs[absFilename] = currentMoc;
-        notIncludedMocs.erase(absFilename);
         }
       matchOffset += mocIncludeRegExp.end();
       } while(mocIncludeRegExp.find(contentsString.c_str() + matchOffset));
     }
+
+  // search for header files and private header files we may need to moc:
+  const std::string basename =
+              cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename);
+  for(std::list<std::string>::const_iterator ext = headerExtensions.begin();
+      ext != headerExtensions.end();
+      ++ext)
+    {
+    const std::string headerName = absPath + basename + (*ext);
+    if (cmsys::SystemTools::FileExists(headerName.c_str()))
+      {
+      absHeaders.insert(headerName);
+      break;
+      }
+    }
+  for(std::list<std::string>::const_iterator ext = headerExtensions.begin();
+      ext != headerExtensions.end();
+      ++ext)
+    {
+    const std::string privateHeaderName = absPath+basename+"_p"+(*ext);
+    if (cmsys::SystemTools::FileExists(privateHeaderName.c_str()))
+      {
+      absHeaders.insert(privateHeaderName);
+      break;
+      }
+    }
+
+}
+
+
+void cmQtAutomoc::ParseHeaders(const std::set<std::string>& absHeaders,
+                        const std::map<std::string, std::string>& includedMocs,
+                        std::map<std::string, std::string>& notIncludedMocs)
+{
+  cmsys::RegularExpression qObjectRegExp("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]");
+  for(std::set<std::string>::const_iterator hIt=absHeaders.begin();
+      hIt!=absHeaders.end();
+      ++hIt)
+    {
+    const std::string& headerName = *hIt;
+
+    if (includedMocs.find(headerName) == includedMocs.end())
+      {
+      if (this->Verbose)
+        {
+        std::cout << "AUTOMOC: Checking " << headerName << std::endl;
+        }
+
+      const std::string basename = cmsys::SystemTools::
+                                   GetFilenameWithoutLastExtension(headerName);
+
+      const std::string currentMoc = "moc_" + basename + ".cpp";
+      const std::string contents = this->ReadAll(headerName);
+      if (qObjectRegExp.find(contents))
+        {
+        //std::cout << "header contains Q_OBJECT macro";
+        notIncludedMocs[headerName] = currentMoc;
+        }
+      }
+    }
+
 }
 
 

+ 16 - 0
Source/cmQtAutomoc.h

@@ -1,3 +1,16 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2004-2011 Kitware, Inc.
+  Copyright 2011 Alexander Neundorf ([email protected])
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+
 #ifndef cmQtAutomoc_h
 #define cmQtAutomoc_h
 
@@ -27,6 +40,9 @@ private:
                    const std::string& mocFileName);
   void ParseCppFile(const std::string& absFilename,
                     std::map<std::string, std::string>& includedMocs,
+                    std::set<std::string>& absHeaders);
+  void ParseHeaders(const std::set<std::string>& absHeaders,
+                    const std::map<std::string, std::string>& includedMocs,
                     std::map<std::string, std::string>& notIncludedMocs);
 
   void Init();

+ 1 - 1
Tests/QtAutomoc/CMakeLists.txt

@@ -13,7 +13,7 @@ add_definitions(-DFOO)
 # create an executable and a library target, both requiring automoc:
 add_library(codeeditorLib STATIC codeeditor.cpp)
 
-add_executable(foo main.cpp calwidget.cpp )
+add_executable(foo main.cpp calwidget.cpp foo.cpp)
 
 set_target_properties(foo codeeditorLib PROPERTIES AUTOMOC TRUE)
 

+ 39 - 0
Tests/QtAutomoc/foo.cpp

@@ -0,0 +1,39 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2004-2011 Kitware, Inc.
+  Copyright 2011 Alexander Neundorf ([email protected])
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+
+#include "foo.h"
+
+#include <stdio.h>
+
+class FooFoo : public QObject
+{
+  Q_OBJECT
+  public:
+    FooFoo():QObject() {}
+  public slots:
+    int getValue() const { return 12; }
+};
+
+Foo::Foo()
+:QObject()
+{
+}
+
+
+void Foo::doFoo()
+{
+  FooFoo ff;
+  printf("Hello automoc: %d\n", ff.getValue());
+}
+
+#include "foo.moc"

+ 28 - 0
Tests/QtAutomoc/foo.h

@@ -0,0 +1,28 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2004-2011 Kitware, Inc.
+  Copyright 2011 Alexander Neundorf ([email protected])
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+
+#ifndef FOO_H
+#define FOO_H
+
+#include <QObject>
+
+class Foo : public QObject
+{
+  Q_OBJECT
+  public:
+    Foo();
+  public slots:
+    void doFoo();
+};
+
+#endif

+ 4 - 0
Tests/QtAutomoc/main.cpp

@@ -42,6 +42,7 @@
 
 #include "codeeditor.h"
 #include "calwidget.h"
+#include "foo.h"
 
 int main(int argv, char **args)
 {
@@ -54,5 +55,8 @@ int main(int argv, char **args)
   Window w;
   w.show();
 
+  Foo foo;
+  foo.doFoo();
+
   return app.exec();
 }