AUTOMOC: generated files include full relative path, breaking certain reproducible builds
CMake currently invokes moc in a way such that the relative path between the source and build directory affects the build. Steps to reproduce:
- Put the following project in the
src
directory. mkdir ../build && cd ../build
cmake -GNinja ../src
ninja
grep 'my_label.h"' qtui_autogen/IMAN36LHMA/moc_my_label.cpp
Expected result:
The included header is relative, for example widgets/my_label.h
or my_label.h
(depending on the include directories).
Actual result:
#include "../../../src/widgets/my_label.h"
Further information:
The command invoked by cmake -E cmake_autogen /tmp/x/build/CMakeFiles/qtui_autogen.dir/AutogenInfo.cmake ""
is:
/usr/bin/moc
-I/usr/include/qt
-I/usr/include/qt/QtWidgets
-I/usr/include/qt/QtGui
-I/usr/include/qt/QtCore
-I/usr/lib/qt/mkspecs/linux-g++
-I/usr/include
-DQT_CORE_LIB
-DQT_GUI_LIB
-DQT_NO_DEBUG
-DQT_WIDGETS_LIB
--include
/tmp/x/build/qtui_autogen/moc_predefs.h
-o
/tmp/x/build/qtui_autogen/IMAN36LHMA/moc_my_label.cpp
/tmp/x/src/widgets/my_label.h
It appears that (for at least Qt 5, I did not check older versions), the include prefix can be controlled with the -p
option. The special value ./
will avoid adding any prefix at all (#include "my_label.h"
). Any other prefix will be displayed verbatim (-pwidgets
results in #include "widgets/my_label.h"
).
Could CMake be modified to avoid Qt moc
from calculating such relative paths (by using the -p
option)? Would there be any issues if this happened by default?
This issue is now documented at https://reproducible-builds.org/docs/deterministic-build-systems/#cmake-notes
Reproducer
CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(TestMoc LANGUAGES CXX)
set(CMAKE_AUTOMOC ON)
find_package(Qt5 COMPONENTS Widgets REQUIRED)
add_library(qtui widgets/my_label.cpp)
target_link_libraries(qtui Qt5::Widgets)
widgets/my_label.h
#ifndef MY_LABEL_H
#define MY_LABEL_H
#include <QLabel>
class MyLabel : public QLabel {
Q_OBJECT
public:
MyLabel();
};
#endif // MY_LABEL_H
widgets/my_label.cpp
#include "my_label.h"
MyLabel::MyLabel() : QLabel() {
}
Cc @sebholt