Merge topic 'automoc-rerun-missing-dependency'

9ac3503d30 AutoMoc: Re-run moc if a dependency is missing

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !5180
This commit is contained in:
Brad King
2020-09-10 13:45:47 +00:00
committed by Kitware Robot
9 changed files with 132 additions and 7 deletions
+15 -7
View File
@@ -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) {
@@ -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()
@@ -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})
@@ -0,0 +1,2 @@
#include <qobject.h>
@@ -0,0 +1,2 @@
#include <qobject.h>
@@ -0,0 +1,9 @@
#include <iostream>
#include "myobject.h"
int main(int argc, char* argv[])
{
MyObject obj;
return 0;
}
@@ -0,0 +1,6 @@
#include "myobject.h"
MyObject::MyObject(QObject* parent)
: QObject(parent)
{
}
@@ -0,0 +1,10 @@
#pragma once
#include <foo.h>
class MyObject : public QObject
{
Q_OBJECT
public:
MyObject(QObject* parent = 0);
};
+1
View File
@@ -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)