c++ - 验证我对 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})
第一行的
set
命令只是定义HEADER_DIR
. 这很简单。target_include_directories(sql-writer-demo PUBLIC ${HEADER_DIR})
必须在第一个之后add_execuable
包含,否则头文件将需要包含在相对路径中。那正确吗?为什么会来?我听说 cmake 将包含目录视为与“源”(cmake 源不是 .cpp 文件)“分开”。这意味着什么?target_link_libraries(sql-writer-demo sql-writer-lib mysqlcppconn ${Boost_LIBRARIES})
也需要紧随其后add_executable(sql-writer-demo main.cpp ${HEADER_DIR})
,它告诉如何链接到其他库。file(GLOB SOURCES ${sql-writer_SOURCE_DIR}/src/*.cpp)
以前不推荐只是因为目录/文件结构可能会改变,然后这将不再起作用target_link_libraries(sql-writer-lib mysqlcppconn ${Boost_LIBRARIES})
需要add_library(sql-writer-lib ${HEADERS} ${SOURCES})
紧随其后,因为我的库的计算sql-writer-lib
需要使用其他库,这就是我们告诉 cmake 留意那些的地方。
解决方案
您通常不将标头包含在
add_executable
andadd_library
中,而仅包含实现文件:add_executable(sql-writer-demo main.cpp) add_library(sql-writer-lib ${SOURCES})
add_executable
并add_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}
您项目的结构。我仅将其指定为示例。
推荐阅读
- jsf - 如何在没有 CDI 的情况下使用 omnifaces 套接字?
- ansible - 在 Ansible 中使用 vars 和模板
- javascript - PHP如何默认输入字段
- html - HTML 图像不会出现在我的本地主机上。我的路径正确吗?
- linq - 基于方法的 linq 总是比基于查询的 linq 更好,还是有一些限制?
- react-proptypes - 在 React 中只指定这些道具类型?
- python - 无法解决 Python 3 中的运行时错误
- matlab - 在不使用 min/max 命令的情况下查找矩阵的坐标最小值和最大值
- reactjs - 如何使用 React Router v4 处理重定向到同一路由(使用查询参数)
- html - 为什么最后一段没有在下面的 HTML 代码中着色?