丁致宇第二周学习报告 深入中大型项目的Cmakelists
作者:丁致宇,时间:2024.1.28 ]
正文
中大型项目常用cmake语法(查找表)
项目基本设置
-
指定CMake最低版本要求:
cmake_minimum_required(VERSION 3.12.0 FATAL_ERROR) -
项目声明:
project(roms VERSION 3.9 LANGUAGES Fortran) -
设置变量和CMake模块路径:
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") -
设置构建类型:
set(CMAKE_BUILD_TYPE Release)
编译器和链接器配置
-
添加编译器选项:
add_compile_options(-Wall -Wextra) -
设置目标特定的编译定义:
target_compile_definitions(roms_executable PRIVATE -DUSE_NETCDF4) -
设置目标特定的编译选项:
target_compile_options(roms_executable PRIVATE -O2) -
设置目标特定的链接选项:
target_link_options(roms_executable PRIVATE -L/path/to/lib)
环境检测与条件分支
- 检查环境变量:
if(DEFINED ENV{ECBUILD_MODULE_PATH})
# 做一些特定于ecbuild的配置
endif()
包含其他脚本和模块
-
包含自定义CMake脚本:
include(roms_functions) -
查找并链接依赖库:
find_package(NetCDF REQUIRED COMPONENTS Fortran)
源代码和资源管理
-
添加子目录:
add_subdirectory(src) -
指定头文件和库目录:
include_directories(${NetCDF_INCLUDE_DIRS})
link_directories(${NetCDF_LIBRARY_DIRS}) -
设置源文件属性:
set_property(SOURCE file.F90 PROPERTY COMPILE_FLAGS "-special-flag") -
自动生成源码:
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/generated_source.f90
COMMAND generate_source_script
DEPENDS script_input.dat
) -
处理文件和目录:
file(GLOB MY_SOURCES "src/*.cpp")
file(COPY ${CMAKE_SOURCE_DIR}/data/ DESTINATION ${CMAKE_BINARY_DIR}/data)
目标定义和链接
-
创建对象库:
add_library(Objects OBJECT ${All_f90s}) -
创建静态库和共享库:
add_library(ROMS_static STATIC $<TARGET_OBJECTS:Objects>)
add_library(ROMS_shared SHARED $<TARGET_OBJECTS:Objects>) -
构建可执行文件:
add_executable(roms_executable ${master_f90})
target_link_libraries(roms_executable ${NetCDF_LIBRARIES})
安装和测试
-
安装目标和文件:
install(TARGETS roms_executable DESTINATION bin)
install(FILES readme.txt DESTINATION share/doc)
install(DIRECTORY docs/ DESTINATION share/doc) -
启用和添加测试:
enable_testing()
add_test(NAME MyTest COMMAND TestExecutable)
打包和项目导出
-
设置CPack打包:
set(CPACK_PACKAGE_NAME "MyApp")
include(CPack) -
导出和安装目标:
export(TARGETS roms_executable FILE ROMSExecutableTargets.cmake)
install(EXPORT ROMSExecutableTargets FILE ROMSExecutableTargets.cmake DESTINATION lib/cmake/ROMS)
自定义构建步骤和清理
-
添加自定义构建命令和目标:
add_custom_target(clean-all COMMAND ${CMAKE_MAKE_PROGRAM} clean)
add_custom_command(TARGET roms_executable POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo "Build complete!") -
提供开关选项:
option(USE_MY_LIB "Use the provided library" ON) -
设置CMake策略:
cmake_policy(SET CMP0074 NEW)
Cmakelists解读实践
示例项目见文件夹内的 示例项目cmakelists+详细注释.txt文件
分析示例项目cmakelists整体结构与思路
-
基本配置:
- 设置最小所需的CMake版本。
- 定义模块路径,用于搜索自定义的CMake模块。
- 检查是否在ecbuild构建系统下运行,根据此条件调整后续配置。
-
项目定义:
- 使用
project()命令定义名为“roms”的项目,指定版本号及主要编程语言为Fortran。 - 在ecbuild环境下,启用Fortran并设置相关构建选项。
- 使用
-
ROMS相关的CMake文件引入:
- 引入一系列自定义的CMake函数、编译器标志和配置文件。
-
依赖管理:
- 根据环境变量检测NetCDF库的位置并进行链接。
- 如果在ecbuild环境下,使用ecbuild自带的MPI查找功能,并添加MPI Fortran库链接。
- 根据SCORPIO的开启状态,添加相应的头文件目录。
-
ROMS源码组织:
- 添加各个子目录作为子构建目录,这些子目录包含了ROMS的核心组件、驱动程序以及各种功能模块。
- 设置公共的包含目录和链接目录。
- 收集所有源文件到一 个列表中,并根据ADJOINT、REPRESENTER、TANGENT等选项决定是否包含相应子目录的源文件。
-
ROMS特定规则:
- 为特定源文件设置特殊的预处理器定义和编译标志。
- 针对某些需要超过标准Fortran行长度限制的文件,设置自由格式编译标志。
-
清理依赖关系:
- 通过Perl脚本清理CMake生成的依赖信息文件,确保正确的依赖关系。
- 创建一个自定义目标“fix”,并在Objects目标上依赖它。
-
对象库创建:
- 使用
preprocess_fortran函数处理源代码,生成.f90文件,并将它们作为一个OBJECT库目标“Objects”。 - 根据LIBSHARED和LIBSTATIC选项分别生成动态库(ROMS_shared)和静态库(ROMS_static),并安装。
- 使用
-
构建可执行文件:
- 当ROMS_EXECUTABLE被启用时,从Master子目录中的master.F文件构建可执行文件。
- 设置合适的链接目录与链接库,包括NetCDF、ARPACK(如果需要)以及SCORPIO(如果开启了并行I/O)。
- 将Objects目标、ROMS库以及其他依赖项链接到最终的可执行文件中,并安装至合适位置。
示例项目cmakelists+详细注释
见文件夹内的 示例项目cmakelists+详细注释.txt文件