如何编写CMakeLists.txt构建源码及示例?单根文件实现多示例构建问询
当然可以!完全不用给每个示例目录单独写CMakeLists.txt,只需要在ProjectRepoDir根目录下写一个顶层CMake配置就能搞定所有构建需求。我给你详细拆解怎么写,以及每个部分的作用:
1. 基础配置
首先开头要做一些CMake的基础设置,指定最低版本、项目名称和C++标准,确保编译环境兼容:
cmake_minimum_required(VERSION 3.10) project(MyProject) # 设置C++标准,根据你的代码需求调整版本,比如C++17 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON)
2. 编译核心库
你的src目录里有liba.cpp和module1.cpp,咱们把它们编译成一个静态库(也可以改成动态库,看你需求),这样主程序和所有示例都能直接链接复用,不用重复编译这些代码:
# 收集核心库的源码文件 set(CORE_SOURCES src/liba.cpp src/module1.cpp ) # 编译成静态库 add_library(core_lib STATIC ${CORE_SOURCES}) # 指定头文件目录,让编译时能找到include下的头文件 target_include_directories(core_lib PUBLIC ${PROJECT_SOURCE_DIR}/include)
这里用PUBLIC是为了让链接这个库的目标(主程序、示例)自动继承include目录,不用重复设置。
3. 编译主程序
接下来处理src目录下的main.cpp,生成主程序可执行文件,链接咱们刚才编译的核心库:
add_executable(main_program src/main.cpp) target_link_libraries(main_program PRIVATE core_lib)
4. 批量编译所有示例
这部分是重点,不用每个示例目录写CMake,咱们通过CMake的目录遍历功能自动处理samples下的所有子目录:
# 遍历samples下的所有子目录 file(GLOB SAMPLE_DIRS RELATIVE ${PROJECT_SOURCE_DIR}/samples ${PROJECT_SOURCE_DIR}/samples/*) foreach(DIR ${SAMPLE_DIRS}) # 把目录名里的'-'换成'_',避免CMake识别问题 string(REPLACE "-" "_" EXEC_NAME ${DIR}) # 收集当前示例目录下的所有源码文件 aux_source_directory(${PROJECT_SOURCE_DIR}/samples/${DIR} SAMPLE_SOURCES) # 生成对应可执行文件 add_executable(${EXEC_NAME} ${SAMPLE_SOURCES}) # 链接核心库 target_link_libraries(${EXEC_NAME} PRIVATE core_lib) endforeach()
如果你的示例目录里只有main.cpp,也可以直接指定这个文件代替aux_source_directory,效果是一样的。
5. 可选:统一可执行文件输出目录
默认情况下,可执行文件会生成在build目录对应的子目录里(比如build/src、build/samples/example1-dir),如果想把所有可执行文件都放到build/bin目录下,方便查找运行,可以加这几行:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/bin) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/bin)
把上面的部分整合起来,就是完整的顶层配置文件,直接放在ProjectRepoDir根目录下即可:
cmake_minimum_required(VERSION 3.10) project(MyProject) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 统一输出目录(可选) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/bin) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/bin) # 编译核心库 set(CORE_SOURCES src/liba.cpp src/module1.cpp ) add_library(core_lib STATIC ${CORE_SOURCES}) target_include_directories(core_lib PUBLIC ${PROJECT_SOURCE_DIR}/include) # 编译主程序 add_executable(main_program src/main.cpp) target_link_libraries(main_program PRIVATE core_lib) # 批量编译示例 file(GLOB SAMPLE_DIRS RELATIVE ${PROJECT_SOURCE_DIR}/samples ${PROJECT_SOURCE_DIR}/samples/*) foreach(DIR ${SAMPLE_DIRS}) string(REPLACE "-" "_" EXEC_NAME ${DIR}) aux_source_directory(${PROJECT_SOURCE_DIR}/samples/${DIR} SAMPLE_SOURCES) add_executable(${EXEC_NAME} ${SAMPLE_SOURCES}) target_link_libraries(${EXEC_NAME} PRIVATE core_lib) endforeach()
直接执行你说的命令就行:
mkdir build && cd build && cmake .. && make
构建完成后,所有可执行文件都会在build/bin目录下(如果加了统一输出目录),你可以直接运行./bin/main_program、./bin/example1_dir等测试。
内容的提问来源于stack exchange,提问作者ywiyogo




