如何在 CMAKE 项目上正确添加子文件夹而不会收到链接器错误

问题描述

我在 CMAKE 项目中包含子文件夹时遇到了一些问题。 简而言之,下面是我拥有的 CMAKE 树的摘要。第一层工作正常,但第二层不能正常工作,抛出一个 linker error:

错误

src/ROstemplatesMsgs/CMakeLists.txt 中的 CMake 错误:17 (add_executable): 找不到源文件

actionlib_msgs/goalID/dbGoalID.cpp

尝试扩展 .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm .hpp .hxx .in .txx

CMake 错误:CMake 无法确定目标的链接器语言: goalID CMake 错误:无法确定目标的链接语言 “目标 ID”。生成完成

项目树如下图所示:

.
+-- Project-DriveAll[master]
+-- CMakeLists.txt
+-- src
|   +-- projectA
|   +-- projectB
|   +-- ROstemplatesMsgs
|       +-- CMakeLists.txt
|       +-- main
|           +-- geometry_msgs.h
|           +-- main.cpp
|           +-- pointField.h
|           +-- ros_headers.h
|       +-- src
|           +-- actionlib_msgs
|               +-- goalID
|                   +-- dbGoalID.cpp
|                   +-- dbGoalID.h
|                   +-- goalIDItem.cpp
|                   +-- goalIDItem.h
|               +-- goalStatus
|                   +-- dbGoalStatus.cpp
|                   +-- dbGoalStatus.h
|                   +-- goalStatusItem.cpp
|                   +-- goalStatusItem.h
|           +-- sensor_msgs
|               +-- laserscan
|               ........

要获得更好的可视化效果,另请参阅:

viz

所以文件在下面,效果很好:

cmake_minimum_required(VERSION 3.1)

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")

set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
set(INCLUDE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/include)

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -g") 
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g")

project(Project-DriveAll)
add_subdirectory(src/projectA)
add_subdirectory(src/projectB)
add_subdirectory(src/ROstemplatesMsgs)

但是,以下是未正确编译的项目 CMakeLists.txt 下的 src/ROstemplatesMsgs

cmake_minimum_required (VERSION 3.1)
project(ROstemplatesMsgs)
find_package(Qt5Widgets required)

set (OpenCV_DIR /home/to/opencv/build)
set (BOOST_LIBRARYDIR /usr/lib/x86_64-linux-gnu)

find_package( OpenCV required )
find_package(Boost COMPONENTS system thread filesystem required)
find_package(Qt5PrintSupport required)
find_package(Qt5 required COMPONENTS Core Quick sql)

include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)

include_directories(${OpenCV_INCLUDE_Dirs})
INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIR} )
INCLUDE_DIRECTORIES(${Qt5Widgets_INCLUDE_Dirs})

file(GLOB SRCS
    "src/*.h"
    "src/*.cpp"
    "src/*.hpp"

    "src/actionlib_msgs/goalID/dbGoalID.cpp"
    "src/actionlib_msgs/goalID/dbGoalID.h"
    "src/actionlib_msgs/goalID/dbGoalIDItem.cpp"
    "src/actionlib_msgs/goalID/dbGoalIDItem.h"

    "src/actionlib_msgs/goalStatusArray/dbGoalStatusArray.cpp"
    "src/actionlib_msgs/goalStatusArray/dbGoalStatusArray.h"
    "src/actionlib_msgs/goalStatusArray/goalStatusArrayItem.cpp"
    "src/actionlib_msgs/goalStatusArray/goalStatusArrayItem.h"


    "src/sensor_msgs/laserscan/*.h"
    "src/sensor_msgs/laserscan/*.cpp"
    "src/sensor_msgs/laserscan/*.hpp"

    "src/visualization_msgs/marker/*.h"
    "src/visualization_msgs/marker/*.cpp"
    "src/visualization_msgs/marker/*.hpp"

    "src/visualization_msgs/markerarray/*.h"
    "src/visualization_msgs/markerarray/*.cpp"
    "src/visualization_msgs/markerarray/*.hpp"

    "src/sensor_msgs/pointcloud2/*.h"
    "src/sensor_msgs/pointcloud2/*.cpp"
    "src/sensor_msgs/pointcloud2/*.hpp"

    "src/sensor_msgs/pointcloud/*.h"
    "src/sensor_msgs/pointcloud/*.cpp"
    "src/sensor_msgs/pointcloud/*.hpp"


    "main/*.h"
    "main/*.cpp"
    "main/*.hpp"
)

file(GLOB UI_SRCS
    "ui/*.h"
    "ui/*.cpp"
    "ui/*.hpp"
)

add_executable(ROstemplatesMsgs main/main.cpp ${SRCS})
target_link_libraries (ROstemplatesMsgs  Qt5::Widgets  ${Boost_LIBRARIES} ${OpenCV_LIBS} Qt5::PrintSupport Qt5::Core Qt5::Quick Qt5::sql)

add_library(ROstemplatesMsgs_lib SHARED ${SRCS} ${UI_HDRS} ${UI_SRCS})
target_include_directories (ROstemplatesMsgs_lib PUBLIC "src/actionlib_msgs/" )
target_include_directories (ROstemplatesMsgs_lib PUBLIC "src/sensor_msgs/" )
target_link_libraries (ROstemplatesMsgs_lib Qt5::Widgets  ${Boost_LIBRARIES} ${OpenCV_LIBS} Qt5::PrintSupport Qt5::Core Qt5::Quick Qt5::sql)

我查阅了很多资源,例如 this onethis one,但是就我而言,我没有使用 TARGET 选项,因为 CMAKE 文档中并不总是建议这样做。 但是,我也尝试按照这篇文章中的建议使用 set_target_properties,但没有任何改变。 我浏览了 this post,但没有帮助找出问题所在。

我也尝试通过以下方式add_subdirectory按照这篇文章的建议,但也没有奏效:

add_subdirectory(src/actionlib_msgs)
add_subdirectory(src/sensor_msgs)

我咨询的另一个来源是 this one,它实际上有助于理解处理复杂项目和处理复杂项目时的不同用途。如问题开头所示,我的项目还有其他子项目,其中包含多个 CMakeLists.txt,但项目 ROstemplatesMsgs 是具有多个子文件夹并且使树复杂化的项目。

root 有 add_subdirectory() 命令,实际上运行良好。 ProjectA 和 ProjectB 有自己的 CMakeLists.txt 并且没问题(但它们也没有多个子文件夹)。 当涉及到最后一个项目(带有子文件夹的项目)时,有些事情无法正常工作,我的想法已经用完了。

编辑

构建项目后的其他信息可以在下面的终端错误中看到:

在包含的文件中 /home/build-ultrasound_mapper-Desktop_Qt_5_12_2_GCC_64bit-Debug/src/ROstemplatesMsgs/ROstemplatesMsgs_autogen/mocs_compilation.cpp:3:0: /home/build-ultrasound_mapper-Desktop_Qt_5_12_2_GCC_64bit-Debug/src/ROstemplatesMsgs/ROstemplatesMsgs_autogen/WKFP3Z6SYI/moc_dbGoalStatus.cpp:57:6: 错误:“dbGoalStatus”尚未声明为无效 dbGoalStatus::qt_static_Metacall(QObject *_o,QMetaObject::Call _c,int _id,void **_a)

/home/build-ultrasound_mapper-Desktop_Qt_5_12_2_GCC_64bit-Debug/src/ROstemplatesMsgs/ROstemplatesMsgs_autogen/WKFP3Z6SYI/moc_dbGoalStatus.cpp:65:38: 错误:“dbGoalStatus”尚未声明 QT_INIT_MetaOBJECT const QMetaObject dbGoalStatus::staticMetaObject = { { ^~~~~~~~~~~~~

/home/labrat/build-ultrasound_mapper-Desktop_Qt_5_12_2_GCC_64bit-Debug/src/ROstemplatesMsgs/ROstemplatesMsgs_autogen/WKFP3Z6SYI/moc_dbGoalStatus.cpp:75:20: 错误:“dbGoalStatus”尚未声明为 const QMetaObject *dbGoalStatus::MetaObject() const ^~~~~~~~~~~~~

/home/build-ultrasound_mapper-Desktop_Qt_5_12_2_GCC_64bit-Debug/src/ROstemplatesMsgs/ROstemplatesMsgs_autogen/WKFP3Z6SYI/moc_dbGoalStatus.cpp:75:47: 错误:非成员函数‘const QMetaObject* MetaObject()’不能 有 cv 限定符 const QMetaObject *dbGoalStatus::MetaObject() const ^~~~~

这似乎指向链接错误

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)