Autogen: Fix compilation of unchanged source files

Since generated `ui` headers are added as byproducts of the autogen
target, it causes to compilation of unchanged files.

This commits adds generated `ui` headers to byproducts of the
timestamp target instead of the autogen target's.

Fixes: #25436
Fixes: #26135
This commit is contained in:
Orkun Tokdemir
2024-07-16 17:26:25 +02:00
parent 68ea116380
commit 5363bebc1e
14 changed files with 382 additions and 2 deletions

View File

@@ -1340,9 +1340,12 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
}
if (this->Uic.Enabled) {
for (const auto& file : this->Uic.UiHeaders) {
// Make all ui_*.h files byproducts of the ${target}_autogen/timestamp
// custom command if the generation of depfile is enabled.
auto& byProducts = useDepfile ? timestampByproducts : autogenByproducts;
for (auto const& file : this->Uic.UiHeaders) {
this->AddGeneratedSource(file.first, this->Uic);
autogenByproducts.push_back(file.second);
byProducts.push_back(file.second);
}
}

View File

@@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 3.16)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)

View File

@@ -0,0 +1,70 @@
include(RunCMake)
include(Autogen_common/utils)
if (DEFINED with_qt_version)
set(RunCMake_TEST_OPTIONS
-Dwith_qt_version=${with_qt_version}
"-DQt${with_qt_version}_DIR:PATH=${Qt${with_qt_version}_DIR}"
"-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}"
)
if (QtCore_VERSION VERSION_GREATER_EQUAL 5.15.0)
macro(set_test_variables_for_unwanted_builds)
if (RunCMake_GENERATOR MATCHES "Ninja")
set(RunCMake_TEST_NOT_EXPECT_stdout "widget2.cpp.o.d|mainwindow.cpp.o.d")
elseif (RunCMake_GENERATOR MATCHES "Make")
set(RunCMake_TEST_NOT_EXPECT_stdout "Building CXX object multi_ui_files/CMakeFiles/example.dir/src/widget2.cpp.o|\
Building CXX object multi_ui_files/CMakeFiles/example.dir/src/mainwindow.cpp.o")
elseif (RunCMake_GENERATOR MATCHES "Visual Studio")
set(RunCMake_TEST_NOT_EXPECT_stdout "widget2.cpp|mainwindow.cpp")
elseif (RunCMake_GENERATOR MATCHES "Xcode")
set(RunCMake_TEST_NOT_EXPECT_stdout "widget2.cpp|mainwindow.cpp")
endif()
endmacro()
function(uic_build_test test_name binary_dir source_dir file_to_touch test_config)
set(RunCMake_TEST_BINARY_DIR ${binary_dir})
set(RunCMake_TEST_SOURCE_DIR ${source_dir})
if (NOT RunCMake_GENERATOR MATCHES "Visual Studio")
set(test_verbose_arg "--verbose")
endif()
if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
set(config_desc "-${test_config}")
set(RunCMake_TEST_VARIANT_DESCRIPTION "${config_desc}")
set(multiconfig_config_arg "--config ${test_config}")
else()
set(RunCMake_TEST_VARIANT_DESCRIPTION "")
set(config_arg "-DCMAKE_BUILD_TYPE=Debug")
endif()
run_cmake_with_options(${test_name} ${RunCMake_TEST_OPTIONS} ${config_arg})
set(RunCMake_TEST_NO_CLEAN 1)
run_cmake_command("${test_name}-build" ${CMAKE_COMMAND} --build . ${test_verbose_arg} ${multiconfig_config_arg})
file(TOUCH ${file_to_touch})
set(RunCMake_TEST_VARIANT_DESCRIPTION "${config_desc}-first_build_after_touching")
set_test_variables_for_unwanted_builds()
run_cmake_command("${test_name}-build" ${CMAKE_COMMAND} --build . ${test_verbose_arg} ${multiconfig_config_arg})
message(STATUS "${test_name}-build${config_desc}-Only build files that were touched were built - PASSED")
endfunction()
if(RunCMake_GENERATOR MATCHES "Make|Ninja|Visual Studio|Xcode")
if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
set(configs "Debug" "Release")
else()
set(configs "single_config")
endif()
foreach(config IN ITEMS ${configs})
if (NOT ${config} STREQUAL "single_config")
set(config_desc "-${config}")
endif()
uic_build_test(multi_ui_files_touch_ui ${RunCMake_BINARY_DIR}/multi_ui_files_touch_ui${config_desc}-build
${RunCMake_SOURCE_DIR}/multi_ui_files ${RunCMake_SOURCE_DIR}/multi_ui_files/src/widget1.ui ${config})
uic_build_test(multi_ui_files_touch_cpp ${RunCMake_BINARY_DIR}/multi_ui_files_touch_cpp${config_desc}-build
${RunCMake_SOURCE_DIR}/multi_ui_files ${RunCMake_SOURCE_DIR}/multi_ui_files/src/widget1.cpp ${config})
endforeach()
endif()
endif()
endif ()

View File

@@ -0,0 +1,25 @@
cmake_minimum_required(VERSION 3.5)
project(UicIncrementalBuild LANGUAGES CXX)
find_package(Qt${with_qt_version} REQUIRED COMPONENTS Core Widgets Gui)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
add_executable(example
src/mainwindow.ui
src/widget1.ui
src/widget2.ui
src/mainwindow.h
src/widget1.h
src/widget2.h
src/main.cpp
src/mainwindow.cpp
src/widget1.cpp
src/widget2.cpp
)
target_link_libraries(example PRIVATE Qt${with_qt_version}::Widgets
Qt${with_qt_version}::Core
Qt${with_qt_version}::Gui)

View File

@@ -0,0 +1,11 @@
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

View File

@@ -0,0 +1,25 @@
#include "mainwindow.h"
#include <QVBoxLayout>
#include "src/ui_mainwindow.h"
#include "widget1.h"
MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
auto layout = new QVBoxLayout;
layout->addWidget(new Widget1);
QWidget* w = new QWidget(this);
w->setLayout(layout);
setCentralWidget(w);
}
MainWindow::~MainWindow()
{
delete ui;
}

View File

@@ -0,0 +1,22 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget* parent = nullptr);
~MainWindow();
private:
Ui::MainWindow* ui;
};
#endif // MAINWINDOW_H

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout"/>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,22 @@
#include "widget1.h"
#include "src/ui_widget1.h"
Widget1::Widget1(QWidget* parent)
: QWidget(parent)
, ui(new Ui::Widget1)
{
ui->setupUi(this);
connect(ui->lineEdit, SIGNAL(textChanged(const QString&)), this,
SLOT(onTextChanged(const QString&)));
}
Widget1::~Widget1()
{
delete ui;
}
void Widget1::onTextChanged(const QString& text)
{
ui->OnTextChanged->setText(text);
}

View File

@@ -0,0 +1,23 @@
#ifndef WIDGET1_H
#define WIDGET1_H
#include <QWidget>
namespace Ui {
class Widget1;
}
class Widget1 : public QWidget
{
Q_OBJECT
public:
explicit Widget1(QWidget* parent = nullptr);
~Widget1();
public slots:
void onTextChanged(const QString& text);
private:
Ui::Widget1* ui;
};
#endif // WIDGET1_H

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Widget1</class>
<widget class="QWidget" name="Widget1">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Input:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>OnTextChanged:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="OnTextChanged">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,22 @@
#include "widget2.h"
#include "src/ui_widget2.h"
Widget2::Widget2(QWidget* parent)
: QWidget(parent)
, ui(new Ui::Widget2)
{
ui->setupUi(this);
connect(ui->lineEdit, SIGNAL(textChanged(const QString&)), this,
SLOT(onTextChanged(const QString&)));
}
Widget2::~Widget2()
{
delete ui;
}
void Widget2::onTextChanged(const QString& text)
{
ui->OnTextChanged->setText(text);
}

View File

@@ -0,0 +1,24 @@
#ifndef WIDGET2_H
#define WIDGET2_H
#include <QWidget>
namespace Ui {
class Widget2;
}
class Widget2 : public QWidget
{
Q_OBJECT
public:
explicit Widget2(QWidget* parent = nullptr);
~Widget2();
public slots:
void onTextChanged(const QString& text);
private:
Ui::Widget2* ui;
};
#endif // WIDGET2_H

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Widget2</class>
<widget class="QWidget" name="Widget2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Input:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>OnTextChanged:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="OnTextChanged">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>