首页 > 解决方案 > 验证我对 CMakeLists.txt 文件的理解

问题描述

我成功地用一个文件试错了CMakeLists.txt,现在一切都建立起来了。但是,我想确保我对它的工作原理的理解是正确的。

我有一个具有以下结构的项目:

./
├── bin
├── CMakeLists.txt
├── include
│   └── sql-writer
│       ├── credentials.h
│       ├── database.h
│       ├── datetime.h
│       ├── market_bar.h
│       └── writer.h
├── README.md
├── src
│   ├── CMakeLists.txt
│   ├── database.cpp
│   ├── main.cpp
│   └── writer.cpp
└── test
    ├── CMakeLists.txt
    ├── test-main.cpp
    ├── test_sym_table_pairs
    └── writer_tests.cpp

这将构建一个可执行文件、一个静态库和一个测试可执行文件。问题是src/CMakeLists.txt

set(HEADER_DIR ${sql-writer_SOURCE_DIR}/include/sql-writer)

add_executable(sql-writer-demo main.cpp ${HEADER_DIR})
target_include_directories(sql-writer-demo PUBLIC ${HEADER_DIR}) #!
target_link_libraries(sql-writer-demo sql-writer-lib mysqlcppconn ${Boost_LIBRARIES})

file(GLOB SOURCES ${sql-writer_SOURCE_DIR}/src/*.cpp)
file(GLOB HEADERS ${HEADER_DIR}/*.h)
add_library(sql-writer-lib ${HEADERS} ${SOURCES})
target_link_libraries(sql-writer-lib mysqlcppconn ${Boost_LIBRARIES})
target_include_directories(sql-writer-lib PUBLIC ${HEADER_DIR})
  1. 第一行的set命令只是定义HEADER_DIR. 这很简单。

  2. target_include_directories(sql-writer-demo PUBLIC ${HEADER_DIR})必须在第一个之后add_execuable包含,否则头文件将需要包含在相对路径中。那正确吗?为什么会来?我听说 cmake 将包含目录视为与“源”(cmake 源不是 .cpp 文件)“分开”。这意味着什么?

  3. target_link_libraries(sql-writer-demo sql-writer-lib mysqlcppconn ${Boost_LIBRARIES})也需要紧随其后add_executable(sql-writer-demo main.cpp ${HEADER_DIR}),它告诉如何链接到其他库。

  4. file(GLOB SOURCES ${sql-writer_SOURCE_DIR}/src/*.cpp)以前不推荐只是因为目录/文件结构可能会改变,然后这将不再起作用

  5. target_link_libraries(sql-writer-lib mysqlcppconn ${Boost_LIBRARIES})需要add_library(sql-writer-lib ${HEADERS} ${SOURCES})紧随其后,因为我的库的计算sql-writer-lib需要使用其他库,这就是我们告诉 cmake 留意那些的地方。

标签: c++cmake

解决方案


  • 您通常不将标头包含在add_executableandadd_library中,而仅包含实现文件:

    add_executable(sql-writer-demo main.cpp)
    add_library(sql-writer-lib ${SOURCES})
    
  • add_executableadd_library创建一个目标,target_include_directories为此目标指定包含目录。文档很清楚:

    命名的对象<target>必须由诸如add_executable()or之类的命令创建的,add_library()并且不能是IMPORTED目标。

  • 如果使用target_include_directories(sql-writer-lib PUBLIC ${HEADER_DIR})withPUBLIC说明符,则不需要为target_include_directories链接到该库的目标指定包含目录,因为依赖项将自动传播。这同样适用于target_link_libraries

所以,src/CMakeLists.txt

file(GLOB SOURCES ${sql-writer_SOURCE_DIR}/src/*.cpp)
add_library(sql-writer-lib ${SOURCES})
target_link_libraries(sql-writer-lib PUBLIC mysqlcppconn ${Boost_LIBRARIES})
target_include_directories(sql-writer-lib PUBLIC ${HEADER_DIR})

add_executable(sql-writer-demo main.cpp)
target_link_libraries(sql-writer-demo sql-writer-lib)

应该管用。是否要使用PUBLIC取决于mysqlcppconn ${Boost_LIBRARIES}您项目的结构。我仅将其指定为示例。


推荐阅读