This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, next has been updated
       via  33a603aa5558bd107a5d018daeb78659810a8183 (commit)
       via  6e1c359fe9bee71c421a671108176d47fb415d93 (commit)
      from  aac38f88d4016191dbddc65a4ad5d1bb3fd8c9dd (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=33a603aa5558bd107a5d018daeb78659810a8183
commit 33a603aa5558bd107a5d018daeb78659810a8183
Merge: aac38f8 6e1c359
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Fri Oct 24 13:50:30 2014 -0400
Commit:     CMake Topic Stage <kwro...@kitware.com>
CommitDate: Fri Oct 24 13:50:30 2014 -0400

    Merge topic 'autorcc-depends' into next
    
    6e1c359f QtAutogen: Regenerate qrc files if their input changes (#15074)


http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6e1c359fe9bee71c421a671108176d47fb415d93
commit 6e1c359fe9bee71c421a671108176d47fb415d93
Author:     Stephen Kelly <steve...@gmail.com>
AuthorDate: Wed Sep 17 02:42:30 2014 +0200
Commit:     Stephen Kelly <steve...@gmail.com>
CommitDate: Fri Oct 24 19:45:27 2014 +0200

    QtAutogen: Regenerate qrc files if their input changes (#15074)
    
    Get dependencies from the output of ``rcc --list`` if using
    Qt 5.  Otherwise process the file in the same way as the
    qt4_add_resources macro.
    
    This does not work for RCC files which are generated.
    
    The cmake_autogen build step is implemented as a PRE_BUILD step
    of the target currently if possible, rather than a standalone
    custom target.  This is to keep the number of (synthesized)
    custom targets that appear in the UI low, but in some cases
    it is necessary to fall back to a full custom target.
    
    Fall back to a full custom target for the VS builds if autorcc
    is used.

diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in
index 602b065..7d89420 100644
--- a/Modules/AutogenInfo.cmake.in
+++ b/Modules/AutogenInfo.cmake.in
@@ -1,5 +1,6 @@
 set(AM_SOURCES @_cpp_files@ )
 set(AM_RCC_SOURCES @_rcc_files@ )
+set(AM_RCC_INPUTS @_qt_rcc_inputs@)
 set(AM_SKIP_MOC @_skip_moc@ )
 set(AM_SKIP_UIC @_skip_uic@ )
 set(AM_HEADERS @_moc_headers@ )
diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index 7b81f4f..929cbc0 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -166,6 +166,112 @@ static std::string getAutogenTargetDir(cmTarget const* 
target)
   return targetDir;
 }
 
+std::string cmQtAutoGenerators::ListQt5RccInputs(cmSourceFile* sf,
+                                            cmTarget const* target,
+                                            std::vector<std::string>& depends)
+{
+  std::string rccCommand = this->GetRccExecutable(target);
+  std::vector<std::string> qrcEntries;
+
+  std::vector<std::string> command;
+  command.push_back(rccCommand);
+  command.push_back("--list");
+
+  std::string absFile = cmsys::SystemTools::GetRealPath(
+                                              sf->GetFullPath().c_str());
+
+  command.push_back(absFile);
+
+  std::string output;
+  int retVal = 0;
+  bool result = cmSystemTools::RunSingleCommand(command, &output,
+                                            &retVal, 0,
+                                            cmSystemTools::OUTPUT_NONE);
+  if (!result || retVal)
+    {
+    std::cerr << "AUTOGEN: error: Rcc list process for " << sf->GetFullPath()
+              << " failed:\n" << output << std::endl;
+    return std::string();
+    }
+
+  std::istringstream ostr(output);
+  std::string oline;
+  while(std::getline(ostr, oline))
+    {
+    if (oline.empty())
+      {
+      // The output of rcc --list contains many empty lines.
+      continue;
+      }
+    if (cmHasLiteralPrefix(oline, "RCC: Error in"))
+      {
+      static std::string searchString = "Cannot find file '";
+
+      std::string::size_type pos = oline.find(searchString);
+      if (pos == std::string::npos)
+        {
+        std::cerr << "AUTOGEN: error: Rcc lists unparsable output "
+                  << oline << std::endl;
+        return std::string();
+        }
+      pos += searchString.length();
+      std::string::size_type sz = oline.size() - pos - 1;
+      qrcEntries.push_back(oline.substr(pos, sz));
+      }
+    else
+      {
+      qrcEntries.push_back(oline);
+      }
+    }
+  depends.insert(depends.end(), qrcEntries.begin(), qrcEntries.end());
+  std::string entriesList;
+  const char* sep = "";
+  for(std::vector<std::string>::const_iterator it = qrcEntries.begin();
+      it != qrcEntries.end(); ++it)
+    {
+    entriesList += sep;
+    entriesList += *it;
+    sep = "@list_sep@";
+    }
+  return entriesList;
+}
+
+std::string cmQtAutoGenerators::ListQt4RccInputs(cmSourceFile* sf,
+                                            std::vector<std::string>& depends)
+{
+  const std::string qrcContents = ReadAll(sf->GetFullPath());
+
+  cmsys::RegularExpression fileMatchRegex("(<file[^<]+)");
+
+  std::string entriesList;
+  const char* sep = "";
+
+  size_t offset = 0;
+  while (fileMatchRegex.find(qrcContents.c_str() + offset))
+    {
+    std::string qrcEntry = fileMatchRegex.match(1);
+
+    offset += qrcEntry.size();
+
+    cmsys::RegularExpression fileReplaceRegex("(^<file[^>]*>)");
+    fileReplaceRegex.find(qrcEntry);
+    std::string tag = fileReplaceRegex.match(1);
+
+    qrcEntry = qrcEntry.substr(tag.size());
+
+    if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str()))
+      {
+      qrcEntry = sf->GetLocation().GetDirectory() + "/" + qrcEntry;
+      }
+
+    entriesList += sep;
+    entriesList += qrcEntry;
+    sep = "@list_sep@";
+    depends.push_back(qrcEntry);
+    }
+  return entriesList;
+}
+
 bool cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* target)
 {
   cmMakefile* makefile = target->GetMakefile();
@@ -271,6 +377,61 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* 
target)
         }
       }
     }
+#endif
+
+  std::vector<std::string> rcc_output;
+  if(makefile->GetLocalGenerator()->GetGlobalGenerator()->GetName() == "Ninja"
+#if defined(_WIN32) && !defined(__CYGWIN__)
+        || usePRE_BUILD
+#endif
+        )
+    {
+    std::vector<cmSourceFile*> srcFiles;
+    target->GetConfigCommonSourceFiles(srcFiles);
+    for(std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
+        fileIt != srcFiles.end();
+        ++fileIt)
+      {
+      cmSourceFile* sf = *fileIt;
+      std::string absFile = cmsys::SystemTools::GetRealPath(
+                                                sf->GetFullPath().c_str());
+
+      std::string ext = sf->GetExtension();
+
+      if (target->GetPropertyAsBool("AUTORCC"))
+        {
+        if (ext == "qrc"
+            && !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC")))
+          {
+          std::string basename = cmsys::SystemTools::
+                                  GetFilenameWithoutLastExtension(absFile);
+
+          std::string rcc_output_dir = target->GetSupportDirectory();
+          cmSystemTools::MakeDirectory(rcc_output_dir.c_str());
+          std::string rcc_output_file = rcc_output_dir;
+          rcc_output_file += "/qrc_" + basename + ".cpp";
+          rcc_output.push_back(rcc_output_file);
+
+          if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED")))
+            {
+            if (qtMajorVersion == "5")
+              {
+              this->ListQt5RccInputs(sf, target, depends);
+              }
+            else
+              {
+              this->ListQt4RccInputs(sf, depends);
+              }
+#if defined(_WIN32) && !defined(__CYGWIN__)
+            usePRE_BUILD = false;
+#endif
+            }
+          }
+        }
+      }
+    }
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
   if(usePRE_BUILD)
     {
     // Add the pre-build command directly to bypass the OBJECT_LIBRARY
@@ -287,10 +448,29 @@ bool 
cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* target)
   else
 #endif
     {
-    cmTarget* autogenTarget = makefile->AddUtilityCommand(
+    cmTarget* autogenTarget = 0;
+    if (!rcc_output.empty())
+      {
+      makefile->AddCustomCommandToOutput(rcc_output, depends, "",
+                                         commandLines, 0,
+                                         workingDirectory.c_str(),
+                                         false, false);
+
+      cmCustomCommandLines no_commands;
+      autogenTarget = makefile->AddUtilityCommand(
+                          autogenTargetName, true,
+                          workingDirectory.c_str(), rcc_output,
+                          no_commands, false, autogenComment.c_str());
+
+      }
+    else
+      {
+      autogenTarget = makefile->AddUtilityCommand(
                                 autogenTargetName, true,
                                 workingDirectory.c_str(), depends,
                                 commandLines, false, autogenComment.c_str());
+      }
+
     // Set target folder
     const char* autogenFolder = makefile->GetCMakeInstance()->GetProperty(
                                                      "AUTOMOC_TARGETS_FOLDER");
@@ -418,6 +598,8 @@ void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget 
const* target)
   inputFile += "/Modules/AutogenInfo.cmake.in";
   std::string outputFile = targetDir;
   outputFile += "/AutogenInfo.cmake";
+  makefile->AddDefinition("_qt_rcc_inputs",
+              makefile->GetDefinition("_qt_rcc_inputs_" + target->GetName()));
   makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(),
                           false, true, false);
 
@@ -869,9 +1051,12 @@ void cmQtAutoGenerators::SetupAutoRccTarget(cmTarget 
const* target)
   std::vector<cmSourceFile*> srcFiles;
   target->GetConfigCommonSourceFiles(srcFiles);
 
+  std::string qrcInputs;
+  const char* qrcInputsSep = "";
+
   std::string rccFileFiles;
   std::string rccFileOptions;
-  const char *sep = "";
+  const char *optionSep = "";
 
   const char *qtVersion = makefile->GetDefinition("_target_qt_version");
 
@@ -880,6 +1065,11 @@ void cmQtAutoGenerators::SetupAutoRccTarget(cmTarget 
const* target)
     {
     cmSystemTools::ExpandListArgument(opts, rccOptions);
     }
+  std::string qtMajorVersion = makefile->GetSafeDefinition("QT_VERSION_MAJOR");
+  if (qtMajorVersion == "")
+    {
+    qtMajorVersion = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR");
+    }
 
   for(std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
       fileIt != srcFiles.end();
@@ -909,9 +1099,9 @@ void cmQtAutoGenerators::SetupAutoRccTarget(cmTarget 
const* target)
 
         if (!rccOptions.empty())
           {
-          rccFileFiles += sep;
+          rccFileFiles += optionSep;
           rccFileFiles += absFile;
-          rccFileOptions += sep;
+          rccFileOptions += optionSep;
           }
         const char *listSep = "";
         for(std::vector<std::string>::const_iterator it = rccOptions.begin();
@@ -922,10 +1112,34 @@ void cmQtAutoGenerators::SetupAutoRccTarget(cmTarget 
const* target)
           rccFileOptions += *it;
           listSep = "@list_sep@";
           }
-        sep = ";";
+        optionSep = ";";
+
+        std::vector<std::string> depends;
+
+        std::string entriesList;
+        if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED")))
+          {
+          if (qtMajorVersion == "5")
+            {
+            entriesList = this->ListQt5RccInputs(sf, target, depends);
+            }
+          else
+            {
+            entriesList = this->ListQt4RccInputs(sf, depends);
+            }
+          if (entriesList.empty())
+            {
+            return;
+            }
+          }
+        qrcInputs += qrcInputsSep;
+        qrcInputs += entriesList;
+        qrcInputsSep = ";";
         }
       }
     }
+  makefile->AddDefinition("_qt_rcc_inputs_" + target->GetName(),
+                      cmLocalGenerator::EscapeForCMake(qrcInputs).c_str());
 
   makefile->AddDefinition("_rcc_files",
           cmLocalGenerator::EscapeForCMake(_rcc_files).c_str());
@@ -1153,6 +1367,28 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(cmMakefile* 
makefile,
     cmSystemTools::ReplaceString(*optionIt, "@list_sep@", ";");
     this->RccOptions[*fileIt] = *optionIt;
     }
+
+  const char *rccInputs = makefile->GetSafeDefinition("AM_RCC_INPUTS");
+  std::vector<std::string> rccInputLists;
+  cmSystemTools::ExpandListArgument(rccInputs, rccInputLists);
+
+  if (this->RccSources.size() != rccInputLists.size())
+    {
+    cmSystemTools::Error("Error processing file: ", filename.c_str());
+    return false;
+    }
+
+  for (std::vector<std::string>::iterator fileIt = this->RccSources.begin(),
+                                            inputIt = rccInputLists.begin();
+                                            fileIt != this->RccSources.end();
+                                            ++fileIt, ++inputIt)
+    {
+    cmSystemTools::ReplaceString(*inputIt, "@list_sep@", ";");
+    std::vector<std::string> rccInputFiles;
+    cmSystemTools::ExpandListArgument(*inputIt, rccInputFiles);
+
+    this->RccInputs[*fileIt] = rccInputFiles;
+    }
   }
   this->CurrentCompileSettingsStr = this->MakeCompileSettingsString(makefile);
 
@@ -2075,6 +2311,25 @@ bool cmQtAutoGenerators::GenerateUi(const std::string& 
realName,
   return false;
 }
 
+bool cmQtAutoGenerators::InputFilesNewerThanQrc(const std::string& qrcFile,
+                                                const std::string& rccOutput)
+{
+  std::vector<std::string> const& files = this->RccInputs[qrcFile];
+  for (std::vector<std::string>::const_iterator it = files.begin();
+       it != files.end(); ++it)
+    {
+    int inputNewerThanQrc = 0;
+    bool success = cmsys::SystemTools::FileTimeCompare(it->c_str(),
+                                                      rccOutput.c_str(),
+                                                      &inputNewerThanQrc);
+    if (!success || inputNewerThanQrc >= 0)
+      {
+      return true;
+      }
+    }
+  return false;
+}
+
 bool cmQtAutoGenerators::GenerateQrc()
 {
   for(std::vector<std::string>::const_iterator si = this->RccSources.begin();
@@ -2097,10 +2352,14 @@ bool cmQtAutoGenerators::GenerateQrc()
                                 + ".dir/qrc_" + basename + ".cpp";
 
     int sourceNewerThanQrc = 0;
-    bool success = cmsys::SystemTools::FileTimeCompare(*si,
-                                                      rcc_output_file,
+    bool generateQrc = !cmsys::SystemTools::FileTimeCompare(*si,
+                                                      rcc_output_file.c_str(),
                                                       &sourceNewerThanQrc);
-    if (this->GenerateAll || !success || sourceNewerThanQrc >= 0)
+    generateQrc = generateQrc || (sourceNewerThanQrc >= 0);
+    generateQrc = generateQrc || this->InputFilesNewerThanQrc(*si,
+                                                          rcc_output_file);
+
+    if (this->GenerateAll || generateQrc)
       {
       std::map<std::string, std::string>::const_iterator optionIt
               = this->RccOptions.find(*si);
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h
index ce27852..79fa5df 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGenerators.h
@@ -88,6 +88,15 @@ private:
 
   std::string GetRccExecutable(cmTarget const* target);
 
+  std::string ListQt5RccInputs(cmSourceFile* sf, cmTarget const* target,
+                               std::vector<std::string>& depends);
+
+  std::string ListQt4RccInputs(cmSourceFile* sf,
+                               std::vector<std::string>& depends);
+
+  bool InputFilesNewerThanQrc(const std::string& qrcFile,
+                              const std::string& rccOutput);
+
   std::string QtMajorVersion;
   std::string Sources;
   std::vector<std::string> RccSources;
@@ -118,6 +127,7 @@ private:
   std::vector<std::string> UicTargetOptions;
   std::map<std::string, std::string> UicOptions;
   std::map<std::string, std::string> RccOptions;
+  std::map<std::string, std::vector<std::string> > RccInputs;
 
   bool Verbose;
   bool ColorOutput;
diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt
index 3fd00b8..a60b556 100644
--- a/Tests/QtAutogen/CMakeLists.txt
+++ b/Tests/QtAutogen/CMakeLists.txt
@@ -113,3 +113,35 @@ set_target_properties(no_link_language PROPERTIES AUTOMOC 
TRUE)
 qtx_wrap_cpp(uicOnlyMoc sub/uiconly.h)
 add_executable(uiconly sub/uiconly.cpp ${uicOnlyMoc})
 target_link_libraries(uiconly ${QT_LIBRARIES})
+
+try_compile(RCC_DEPENDS
+  "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends"
+  "${CMAKE_CURRENT_SOURCE_DIR}/autorcc_depends"
+  autorcc_depends
+  CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" 
"-DQT_TEST_VERSION=${QT_TEST_VERSION}"
+  OUTPUT_VARIABLE output
+)
+if (NOT RCC_DEPENDS)
+  message(SEND_ERROR "Initial build of autorcc_depends failed. Output: 
${output}")
+endif()
+
+file(STRINGS "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends/info_file.txt" 
qrc_files)
+
+list(GET qrc_files 0 qrc_file1)
+
+set(timeformat "%Y%j%H%M%S")
+
+file(TIMESTAMP "${qrc_file1}" file1_before "${timeformat}")
+
+execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1) # Ensure that the 
timestamp will change.
+execute_process(COMMAND "${CMAKE_COMMAND}" -E touch 
"${CMAKE_CURRENT_SOURCE_DIR}/autorcc_depends/res1_input.txt")
+
+execute_process(COMMAND "${CMAKE_COMMAND}" --build .
+  WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends"
+)
+
+file(TIMESTAMP "${qrc_file1}" file1_step1 "${timeformat}")
+
+if (NOT file1_step1 GREATER file1_before)
+  message(SEND_ERROR "file1 (${qrc_file1}) should have changed in the first 
step!")
+endif()
diff --git a/Tests/QtAutogen/autorcc_depends/CMakeLists.txt 
b/Tests/QtAutogen/autorcc_depends/CMakeLists.txt
new file mode 100644
index 0000000..afd95bc
--- /dev/null
+++ b/Tests/QtAutogen/autorcc_depends/CMakeLists.txt
@@ -0,0 +1,24 @@
+cmake_minimum_required(VERSION 2.8)
+project(autorcc_depends)
+
+set(CMAKE_AUTORCC ON)
+
+if (QT_TEST_VERSION STREQUAL 4)
+  find_package(Qt4 REQUIRED)
+  set(QT_CORE_TARGET Qt4::QtCore)
+else()
+  if (NOT QT_TEST_VERSION STREQUAL 5)
+    message(SEND_ERROR "Invalid Qt version specified.")
+  endif()
+
+  find_package(Qt5Core REQUIRED)
+  set(QT_CORE_TARGET Qt5::Core)
+endif()
+
+add_executable(test_res1
+  test_res1.cpp
+  res1.qrc
+)
+target_link_libraries(test_res1 ${QT_CORE_TARGET})
+add_custom_command(TARGET test_res1 POST_BUILD COMMAND
+  ${CMAKE_COMMAND} -E echo "$<TARGET_FILE:test_res1>" > info_file.txt)
diff --git a/Tests/QtAutogen/autorcc_depends/res1.qrc 
b/Tests/QtAutogen/autorcc_depends/res1.qrc
new file mode 100644
index 0000000..cfea618
--- /dev/null
+++ b/Tests/QtAutogen/autorcc_depends/res1.qrc
@@ -0,0 +1,5 @@
+<RCC>
+    <qresource prefix="/">
+        <file>res1_input.txt</file>
+    </qresource>
+</RCC>
diff --git a/Tests/QtAutogen/autorcc_depends/res1_input.txt 
b/Tests/QtAutogen/autorcc_depends/res1_input.txt
new file mode 100644
index 0000000..da62762
--- /dev/null
+++ b/Tests/QtAutogen/autorcc_depends/res1_input.txt
@@ -0,0 +1 @@
+Res1 input.
diff --git a/Tests/QtAutogen/autorcc_depends/test_res1.cpp 
b/Tests/QtAutogen/autorcc_depends/test_res1.cpp
new file mode 100644
index 0000000..766b775
--- /dev/null
+++ b/Tests/QtAutogen/autorcc_depends/test_res1.cpp
@@ -0,0 +1,5 @@
+
+int main()
+{
+  return 0;
+}

-----------------------------------------------------------------------

Summary of changes:


hooks/post-receive
-- 
CMake
_______________________________________________
Cmake-commits mailing list
Cmake-commits@cmake.org
http://public.kitware.com/mailman/listinfo/cmake-commits

Reply via email to