I have an interesting problem with a CMake project that uses QT and the AUTOGEN approach (AUTOMOC and AUTOUIC in my case).
I have this minimal sample structure:
MinimalCMakeProject/
├── CMakeLists.txt
├── src/
│ ├── CMakeLists.txt
│ ├── libA/
│ │ ├── CMakeLists.txt
│ │ ├── include/
│ │ │ └── libA/
│ │ │ ├── bla/
│ │ │ │ └── file1.h
│ │ │ └── blubb/
│ │ │ └── file2.h
│ │ └── src/
│ │ ├── bla/
│ │ │ └── file1.cpp
│ │ └── blubb/
│ │ └── file2.cpp
│ └── libB/
│ ├── CMakeLists.txt
│ ├── include/
│ │ └── libB/
│ │ └── file3.h
│ └── src/
│ └── file3.cpp
LibB depends on libA. All files need to be handled by AUTOMOC and AUTOUIC. If I use target_sources in libA’s topmost CMakeLists.txt like this
target_sources(libA
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src/bla/file1.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/blubb/file2.cpp
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include/libA/bla/file1.h
${CMAKE_CURRENT_SOURCE_DIR}/include/libA/blubb/file2.h
)
everything works fine.
But now I have e real-life project where libA contains ~30 subfolders like bla and blubb, each containing up to 50 source files. I dont want to pollute libA’s CMakeLists.txt with the target_sources definition containing everything. So I added separate CMakeLists.txt like this:
MinimalCMakeProject/
├── CMakeLists.txt
├── src/
│ ├── CMakeLists.txt
│ ├── libA/
│ │ ├── CMakeLists.txt
│ │ ├── include/
│ │ │ └── libA/
│ │ │ ├── CMakeLists.txt
│ │ │ ├── bla/
│ │ │ │ ├── CMakeLists.txt
│ │ │ │ └── file1.h
│ │ │ └── blubb/
│ │ │ ├── CMakeLists.txt
│ │ │ └── file2.h
│ │ └── src/
│ │ ├── CMakeLists.txt
│ │ ├── bla/
│ │ │ ├── CMakeLists.txt
│ │ │ └── file1.cpp
│ │ └── blubb/
│ │ ├── CMakeLists.txt
│ │ └── file2.cpp
│ └── libB/
│ ├── CMakeLists.txt
│ ├── include/
│ │ └── libB/
│ │ └── file3.h
│ └── src/
│ └── file3.cpp
In libA’s CMakeLists.txt I replaced the target_sources with
add_subdirectory(include/libA)
add_subdirectory(src)
The CMakeLists.txt of include/libA
and src
use add_subdirectory()
with all the subfolders. The file include/libA/bla/CMakeLists.txt
has this content:
target_sources(libA
PUBLIC
file1.h
)
and similar for all other files.
Now the project compiles nearly fine with one drawback: during processing of libB all the moc and ui files from libA are generated again. In the build directory there is a file src/libA/libA_autogen/mocs_compilation.cpp
which summarizes all moc files. But src/libB/libB_autogen/mocs_compilation.cpp
has the content of the file from libA plus the additional moc files from libB.
Similar behaviour with ui files, they are generated a second time during processing of libB.
How can I fix this?