Hi all,
We maintain a fairly large Qt-based software, with around 790 Visual Studio projects.
Moving CMake from 4.3.4 to 4.4.0 took the solution to roughly 2210.
Every target with AUTOMOC enabled now gets two extra ones, <target>_autogen and <target>_autogen_timestamp_deps.
I did some digging before posting.
It comes from 680fbb112a (MR !11844), which enables depfile support for the Visual Studio and Xcode generators.
A PRE_BUILD event cannot carry depfile dependencies, so usePRE_BUILD gets cleared and the autogen step becomes a separate target instead of a pre-build step on the origin target.
To be clear, I am not reporting a bug. The commit message is explicit about the trade-off, and the incremental-correctness win is real. We would rather have moc rerun when a transitively included header changes.
The catch is the IDE cost. At around 2200 projects, loading and navigating the solution in Visual Studio gets noticeably slower. That is the exact concern recorded in the comment that still sits above the affected code:
// Under VS use a PRE_BUILD event instead of a separate target to
// reduce the number of targets loaded into the IDE.
As far as I can tell there is no way to keep the old path. useDepfile is decided from the generator name and the Qt version alone, and nothing is exposed through a variable, a target property or a policy.
Hence my question.
Would a CMAKE_AUTOGEN_USE_DEPFILE variable with a matching AUTOGEN_USE_DEPFILE target property be conceivable, with the current behaviour kept as the default?
A per-target property would suit us best: we could enable depfiles on the few targets where accuracy matters and leave the rest alone.
There seems to be precedent nearby. AUTOGEN_ORIGIN_DEPENDS, AUTOGEN_USE_SYSTEM_INCLUDE, AUTOGEN_PARALLEL and AUTOGEN_BETTER_GRAPH_MULTI_CONFIG are each exposed as a variable plus a target property.
I would rather ask for a durable knob than a policy.
The trade-off between incremental accuracy and IDE target count is permanent, not a legacy behaviour waiting to be phased out.
Two side notes:
- The change is confined to the 4.4 series. 680fbb112a is reachable from
v4.4.0-rc1onward and from nov4.3.*tag. Since the 4.3 branch ends at 4.3.4, staying there is a freeze rather than a workaround. - The 4.4.2 docs still describe the old behaviour. The
<ORIGIN>\_autogen_timestamp_depstarget restricts the target to Ninja and Makefiles, and Visual Studio Generators still presentsPRE_BUILDas the normal case, with three exceptions, none of them the depfile condition.
I tried the issue tracker first, but my account is new and got flagged as spam. ![]()
Happy to move this over there if that is the better place.
What I measured
A single static library with one Q_OBJECT class, Visual Studio 17 2022, x64, Qt from vcpkg.
| CMake | Qt | autogen projects added | PreBuildEvent in thing.vcxproj |
|---|---|---|---|
| 4.3.4 | 5.15.12 | 0 | yes |
| 4.4.0 | 5.15.12 | 2 | no |
| 4.3.4 | 6.6.1 | 0 | yes |
| 4.4.0 | 6.6.1 | 2 | no |
| 4.3.4 | 6.11.1 | 0 | yes |
| 4.4.0 | 6.11.1 | 2 | no |
4.4.2 behaves like 4.4.0 (tested with Qt 6).
Reproducer
CMakeLists.txt:
# Project count generated by the Visual Studio generator:
# CMake 4.3.4 -> 3 (CompilerIdCXX, thing, VCTargetsPath)
# CMake 4.4.0 -> 5 (CompilerIdCXX, thing, thing_autogen, thing_autogen_timestamp_deps, VCTargetsPath)
cmake_minimum_required(VERSION 3.28)
project(autogen_vs_repro LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON)
find_package(Qt5 QUIET COMPONENTS Core)
if (Qt5_FOUND)
set(QT_CORE_TARGET Qt5::Core)
set(QT_VERSION ${Qt5_VERSION})
else()
find_package(Qt6 REQUIRED COMPONENTS Core)
set(QT_CORE_TARGET Qt6::Core)
set(QT_VERSION ${Qt6_VERSION})
endif()
add_library(thing STATIC thing.cpp thing.h)
target_link_libraries(thing PRIVATE ${QT_CORE_TARGET})
message(STATUS "CMake version ..... ${CMAKE_VERSION}")
message(STATUS "Qt version ........ ${QT_VERSION}")
message(STATUS "Generator ......... ${CMAKE_GENERATOR}")
thing.h:
#pragma once
#include <QObject>
class Thing : public QObject
{
Q_OBJECT
public:
explicit Thing(QObject \*parent = nullptr);
};
thing.cpp:
#include "thing.h"
Thing::Thing(QObject \*parent)
: QObject(parent)
{
}
Configure with:
cmake -S . -B build -G "Visual Studio 17 2022" -A x64 -DCMAKE_TOOLCHAIN_FILE=<vcpkg>/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows
Any Qt installation works. The vcpkg toolchain is simply how ours is provided.