summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2020-09-10 13:45:47 +0000
committerKitware Robot <kwrobot@kitware.com>2020-09-10 09:45:52 -0400
commit9b5f167348d1bb6e4ddaa0a105d6794b9f290122 (patch)
tree2dc0bd2ba77a0f54b963f4e3b3399c9c0e94ae60
parent8de27c599f297654342920b0b8aec65c3245936f (diff)
parent9ac3503d30ed46c63c6a733304072d316f0042cf (diff)
downloadcmake-9b5f167348d1bb6e4ddaa0a105d6794b9f290122.tar.gz
Merge topic 'automoc-rerun-missing-dependency' into release-3.18
9ac3503d30 AutoMoc: Re-run moc if a dependency is missing Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !5180
-rw-r--r--Source/cmQtAutoMocUic.cxx22
-rw-r--r--Tests/QtAutogen/RerunMocOnMissingDependency/CMakeLists.txt80
-rw-r--r--Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/CMakeLists.txt.in7
-rw-r--r--Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/inc1/foo.h2
-rw-r--r--Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/inc2/foo.h2
-rw-r--r--Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/main.cpp9
-rw-r--r--Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/myobject.cpp6
-rw-r--r--Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/myobject.h10
-rw-r--r--Tests/QtAutogen/Tests.cmake1
9 files changed, 132 insertions, 7 deletions
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index 71c288ce29..9cb172bd35 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -192,7 +192,7 @@ public:
{
public:
// -- Parse Cache
- bool ParseCacheChanged = false;
+ std::atomic<bool> ParseCacheChanged = ATOMIC_VAR_INIT(false);
cmFileTime ParseCacheTime;
ParseCacheT ParseCache;
@@ -1777,16 +1777,24 @@ bool cmQtAutoMocUicT::JobProbeDepsMocT::Probe(MappingT const& mapping,
{
// Check dependency timestamps
std::string const sourceDir = SubDirPrefix(sourceFile);
- for (std::string const& dep : mapping.SourceFile->ParseData->Moc.Depends) {
+ auto& dependencies = mapping.SourceFile->ParseData->Moc.Depends;
+ for (auto it = dependencies.begin(); it != dependencies.end(); ++it) {
+ auto& dep = *it;
+
// Find dependency file
auto const depMatch = FindDependency(sourceDir, dep);
if (depMatch.first.empty()) {
- Log().Warning(GenT::MOC,
- cmStrCat(MessagePath(sourceFile), " depends on ",
- MessagePath(dep),
- " but the file does not exist."));
- continue;
+ if (reason != nullptr) {
+ *reason =
+ cmStrCat("Generating ", MessagePath(outputFile), " from ",
+ MessagePath(sourceFile), ", because its dependency ",
+ MessagePath(dep), " vanished.");
+ }
+ dependencies.erase(it);
+ BaseEval().ParseCacheChanged = true;
+ return true;
}
+
// Test if dependency file is older
if (outputFileTime.Older(depMatch.second)) {
if (reason != nullptr) {
diff --git a/Tests/QtAutogen/RerunMocOnMissingDependency/CMakeLists.txt b/Tests/QtAutogen/RerunMocOnMissingDependency/CMakeLists.txt
new file mode 100644
index 0000000000..c5811ebce1
--- /dev/null
+++ b/Tests/QtAutogen/RerunMocOnMissingDependency/CMakeLists.txt
@@ -0,0 +1,80 @@
+# This test checks whether a missing dependency of the moc output triggers an AUTOMOC re-run.
+
+cmake_minimum_required(VERSION 3.10)
+project(RerunMocOnMissingDependency)
+include("../AutogenCoreTest.cmake")
+
+# Create an executable to generate a clean target
+set(main_source "${CMAKE_CURRENT_BINARY_DIR}/generated_main.cpp")
+file(WRITE "${main_source}" "int main() {}")
+add_executable(exe "${main_source}")
+
+# Utility variables
+set(testProjectTemplateDir "${CMAKE_CURRENT_SOURCE_DIR}/MocOnMissingDependency")
+set(testProjectSrc "${CMAKE_CURRENT_BINARY_DIR}/MocOnMissingDependency")
+set(testProjectBinDir "${CMAKE_CURRENT_BINARY_DIR}/MocOnMissingDependency-build")
+if(DEFINED Qt5Core_VERSION AND Qt5Core_VERSION VERSION_GREATER_EQUAL "5.15.0")
+ set(moc_depfiles_supported TRUE)
+else()
+ set(moc_depfiles_supported FALSE)
+endif()
+
+# Utility macros
+macro(sleep)
+ message(STATUS "Sleeping for a few seconds.")
+ execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1)
+endmacro()
+
+macro(rebuild buildName)
+ message(STATUS "Starting build ${buildName}.")
+ execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${testProjectBinDir}"
+ RESULT_VARIABLE result OUTPUT_VARIABLE output)
+ if (result)
+ message(FATAL_ERROR "Build ${buildName} failed.")
+ else()
+ message(STATUS "Build ${buildName} finished.")
+ endif()
+endmacro()
+
+# Create the test project from the template
+file(COPY "${testProjectTemplateDir}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
+configure_file("${testProjectTemplateDir}/CMakeLists.txt.in" "${testProjectSrc}/CMakeLists.txt" @ONLY)
+
+# Initial build
+file(REMOVE_RECURSE "${testProjectBinDir}")
+try_compile(MOC_RERUN
+ "${testProjectBinDir}"
+ "${testProjectSrc}"
+ MocOnMissingDependency
+ CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
+ "-DCMAKE_AUTOGEN_VERBOSE=ON"
+ "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
+ OUTPUT_VARIABLE output
+)
+if (NOT MOC_RERUN)
+ message(FATAL_ERROR "Initial build of mocOnMissingDependency failed. Output: ${output}")
+endif()
+
+# Sleep to ensure new timestamps
+sleep()
+
+if(moc_depfiles_supported)
+ # Remove the dependency inc1/foo.h and build again.
+ # We expect that the moc_XXX.cpp file gets re-generated. But only if we have depfile support.
+ file(REMOVE_RECURSE "${testProjectSrc}/inc1")
+ rebuild(2)
+ if(NOT output MATCHES "AutoMoc: Generating \"[^\"]*moc_myobject.cpp\"")
+ message(FATAL_ERROR "moc_myobject.cpp was not re-generated "
+ "after removing one of its dependencies")
+ endif()
+endif()
+
+# Sleep to ensure new timestamps
+sleep()
+
+# The next build should *not* re-renerate any moc outputs
+rebuild(3)
+if(output MATCHES "AutoMoc: Generating")
+ message(FATAL_ERROR "moc_myobject.cpp was not re-generated "
+ "after removing one of its dependencies")
+endif()
diff --git a/Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/CMakeLists.txt.in b/Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/CMakeLists.txt.in
new file mode 100644
index 0000000000..2155f450a3
--- /dev/null
+++ b/Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/CMakeLists.txt.in
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 3.18)
+project(MocOnMissingDependency)
+include("@CMAKE_CURRENT_LIST_DIR@/../AutogenCoreTest.cmake")
+set(CMAKE_AUTOMOC ON)
+add_executable(MocOnMissingDependency main.cpp myobject.cpp)
+target_include_directories(MocOnMissingDependency PRIVATE inc1 inc2)
+target_link_libraries(MocOnMissingDependency PRIVATE ${QT_QTCORE_TARGET})
diff --git a/Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/inc1/foo.h b/Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/inc1/foo.h
new file mode 100644
index 0000000000..cd8b2f990c
--- /dev/null
+++ b/Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/inc1/foo.h
@@ -0,0 +1,2 @@
+
+#include <qobject.h>
diff --git a/Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/inc2/foo.h b/Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/inc2/foo.h
new file mode 100644
index 0000000000..cd8b2f990c
--- /dev/null
+++ b/Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/inc2/foo.h
@@ -0,0 +1,2 @@
+
+#include <qobject.h>
diff --git a/Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/main.cpp b/Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/main.cpp
new file mode 100644
index 0000000000..36d51fae8d
--- /dev/null
+++ b/Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/main.cpp
@@ -0,0 +1,9 @@
+#include <iostream>
+
+#include "myobject.h"
+
+int main(int argc, char* argv[])
+{
+ MyObject obj;
+ return 0;
+}
diff --git a/Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/myobject.cpp b/Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/myobject.cpp
new file mode 100644
index 0000000000..7a15300586
--- /dev/null
+++ b/Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/myobject.cpp
@@ -0,0 +1,6 @@
+#include "myobject.h"
+
+MyObject::MyObject(QObject* parent)
+ : QObject(parent)
+{
+}
diff --git a/Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/myobject.h b/Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/myobject.h
new file mode 100644
index 0000000000..25176cc31c
--- /dev/null
+++ b/Tests/QtAutogen/RerunMocOnMissingDependency/MocOnMissingDependency/myobject.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include <foo.h>
+
+class MyObject : public QObject
+{
+ Q_OBJECT
+public:
+ MyObject(QObject* parent = 0);
+};
diff --git a/Tests/QtAutogen/Tests.cmake b/Tests/QtAutogen/Tests.cmake
index 0c7bd79148..b1337d6266 100644
--- a/Tests/QtAutogen/Tests.cmake
+++ b/Tests/QtAutogen/Tests.cmake
@@ -21,6 +21,7 @@ ADD_AUTOGEN_TEST(RccOnly rccOnly)
ADD_AUTOGEN_TEST(RccSkipSource)
ADD_AUTOGEN_TEST(RerunMocBasic)
ADD_AUTOGEN_TEST(RerunMocOnAddFile)
+ADD_AUTOGEN_TEST(RerunMocOnMissingDependency)
ADD_AUTOGEN_TEST(RerunRccConfigChange)
ADD_AUTOGEN_TEST(RerunRccDepends)
ADD_AUTOGEN_TEST(SameName sameName)