You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CMake与AUTOGEN在特定项目结构下的重复生成问题

QT CMake AUTOGEN重复生成moc/ui文件问题解决

问题场景

在使用QT的AUTOMOC、AUTOUIC特性的CMake项目中,LibB依赖LibA,所有文件均需AUTOGEN处理。为简化LibA的顶层CMakeLists.txt(避免罗列几十个子目录的文件),给LibA的每个子目录都添加了单独的CMakeLists.txt,通过add_subdirectory递归引入,并用target_sources给LibA添加源文件和头文件。

项目结构(修改后)

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

问题现象

项目可正常编译,但构建目录中出现重复生成的moc/ui文件:

  • src/libA/libA_autogen/mocs_compilation.cpp包含LibA所有moc文件
  • src/libB/libB_autogen/mocs_compilation.cpp同时包含LibA和LibB的moc文件
  • UI文件存在同样的重复生成情况

问题原因

当LibA通过target_sources(libA PUBLIC ...)将带Q_OBJECT等需要moc的头文件设为PUBLIC时,这些头文件会被加入LibA的INTERFACE_SOURCES。LibB链接LibA时,CMake默认会让LibB的AUTOMOC扫描这些INTERFACE头文件,导致重复处理生成moc/ui。

解决方案

核心修复

在LibB的CMakeLists.txt中添加以下配置,让LibB的AUTOGEN跳过处理来自依赖库的INTERFACE头文件:

# 让LibB的AUTOMOC跳过依赖库的INTERFACE头文件
set_target_properties(libB PROPERTIES AUTOMOC_SKIP_INTERFACE_HEADERS ON)
# 让LibB的AUTOUIC跳过依赖库的INTERFACE头文件
set_target_properties(libB PROPERTIES AUTOUIC_SKIP_INTERFACE_HEADERS ON)

辅助配置(确保LibA正确处理AUTOGEN)

在LibA的顶层CMakeLists.txt中,确保启用AUTOMOC和AUTOUIC:

add_library(libA)
# 启用AUTOMOC和AUTOUIC
set_target_properties(libA PROPERTIES AUTOMOC ON)
set_target_properties(libA PROPERTIES AUTOUIC ON)
# 设置头文件包含目录,让LibB能找到LibA的头文件
target_include_directories(libA
    PUBLIC
        include
)
# 递归引入子目录添加源文件
add_subdirectory(include/libA)
add_subdirectory(src)

额外优化(可选)

如果不想维护大量子目录CMakeLists.txt,可以在LibA顶层用file(GLOB_RECURSE)批量添加文件(适合文件结构稳定的项目):

file(GLOB_RECURSE LIB_A_SRC src/**/*.cpp)
file(GLOB_RECURSE LIB_A_PUB_HEADERS include/libA/**/*.h)

target_sources(libA
    PRIVATE
        ${LIB_A_SRC}
    PUBLIC
        ${LIB_A_PUB_HEADERS}
)

内容的提问来源于stack exchange,提问作者gk017

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 12:25:56