hello-CMake
Hello, CMake#
CMake是一个用于构建C++项目的编译链工具。通过编写CMakeLists.txt文件,完成项目的构建。
一个基本的CMakeLists.txt需要有版本要求,项目名称,和项目目标(可执行文件或库文件)组成。
cmake_minimum_required(VERSION 3.20)
project(hello-CMake LANGUAGES CXX)
add_executable(hello main.cpp)
CMake语言不区分大小写,但是参数区分大小写。
CMake基本构建命令#
在源文件的根目录下,执行cmake -S. -Bbuild
,会生成一个和源文件根目录同级的build目录,并在其中生成项目所需的CMake配置文件,这一步等于先mkdir -p build
,然后进入build目录下执行cmake ..
。-B
可以指定build目录的路径。
在构建好了项目树后,进入build目录下,执行cmake --build .
生成项目的可执行文件或者生成库,这个.
表示了当前的build目录,当然也可以不进入build目录,在外面用相对路径或绝对路径代替这个.
。
另外,在生成过程中可以使用cmake -D CMAKE_CXX_COMPILER=clang++ ..
指定编译器。
使用-D CMAKE_BUILD_TYPE=Debug
来切换构建类型,其中类型有Debug,Release,RelWithDebInfo,MinSizeRel四种。
生成库#
CMake生成库的命令是add_library
,将项目中生成的库链接到目标上的命令是target_link_libraries
。
cmake_minimum_required(VERSION 3.20)
project(hello-CMake LANGUAGES CXX)
add_executable(hello main.cpp)
add_library(mylib STATIC some.hpp some.cpp)
target_link_libraries(hello mylib)
在执行完add_library
后,会在linux平台生成一个.a文件或者在windows平台生成一个.lib文件,这就是静态库文件。第二个参数可以是STATIC,SHARED,OBJECT,MODULE的其中一个,分别代表着静态库、动态库、对象库和模组。动态库和静态库很好理解,对象库会使要编译的文件先存起来,既不生成静态库,也不允许链接,然后在需要的时候一次性创建成静态库和动态库。MODULE生成的目标对象是动态库类型,不会被链接到项目中的目标,但又可以进行动态加载,一般用于构建运行时插件。
add_library(objs OBJECT some.hpp some.cpp)
add_library(mylib-static STATIC $<TARGET_OBJECTS:objs>)
set_target_properties(mylib-static PROPERTIES OUTPUT_NAME "mylib")
add_library(mylib-shared SHARED $<TARGET_OBJECTS:objs>)
set_target_properties(mylib-shared PROPERTIES OUTPUT_NAME "mylib")
CMake文件中的目标名是不可以重复的,但可以指定目标的属性,来修改其最后输出的名称。
变量和条件控制#
CMake中使用set(name value)
来定义一个全局变量name,其实际内容是value。
通过list(APPEND file.cpp)
可以向变量中追加内容
CMake中使用if() ... else() ... endif()
的方式书写条件控制语句,其中if()
的括号中可以指定变量。
option
命令可以指定一个开关,并且允许在构建的时候由外部来修改。
变量通过${}
来读取内容。
set(use_lib OFF)
if(use_lib)
add_library(mylib STATIC some.hpp some.cpp)
else()
add_library(mylib SHARED some.hpp some.cpp)
endif()
list(APPEND src else.hpp else.cpp)
option(use_lib_flag "switch" OFF)
if(use_lib_flag)
add_library(mylib STATIC some.hpp some.cpp)
endif()
编译器选项#
使用target_compile_options()
设置目标的编译选项,或者在命令行中使用-D CMAKE_CXX_FLAGS="..."
手动指定。
控制流#
使用foreach(val lists)
的形式来执行循环控制。
target_compile_options(geometry PRIVATE -O3)
list(
APPEND sources_with_lower_optimization
geometry_circle.cpp
geometry_rhombus.cpp
)
foreach(_source IN LISTS sources_with_lower_optimization)
set_source_files_properties(${_source} PROPERTIES COMPILE_FLAGS -O2)
endforeach()
foreach(_source ${sources_with_lower_optimization})
get_source_file_property(_flags ${_source} COMPILE_FLAGS)
endforeach()
foreach()有四种使用方式:
- foreach(loop_var arg1 arg2 ...) : 其中提供循环变量和显式项列表。当为sources_with_lower_optimization 中的项打印编译器标志集时,使用此表单。注意,如果项目列表位于变量中,则必须显式展开它;也就是说, ${sources_with_lower_optimization} 必须作为参数传递。
- 通过指定一个范围,可以对整数进行循环,例如: foreach(loop_var rangetotal) 或 foreach(loop_var range start stop [step]) 。
- 对列表值变量的循环,例如: foreach(loop_var IN LISTS [list1[...]]) 。参数解释为列表,其内容就会自动展开。
- 对变量的循环,例如: foreach(loop_var IN ITEMS [item1 [...]]) 。参数的内容没有展开。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性