2021-09-08 cmake之从可执行文件到库_cmake c++将可执行文件变成库文件

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

# 三个参数:option(<option_variable> "help string" [initial value])
# <option_variable> - 变量的名称
# "help string" - 描述选项的字符段;
# [initial value] - 选项的默认值

```
 
```
# 编译时使用
...
cd build
cmake -D USE_LIBRARY=ON .. # -D开关用于为CMake设置任何类型的变量,如逻辑变量、路径等 
cmake --build .

```
  • 指定编译器

    • CMake将语言的编译器存储在CMAKE__COMPILER 变量中,选择特定的编译器时,可以通过CMAKE__COMPILER进行选择,其中,可以是受支持的任意一种语言
    # 指定编译器的方式有两种
    # 第一种
    cmake -D CMKAE_CXX_COMPILER=clang++ ..
    
    # 第二种
    env CXX=clang++ cmake ..
    
    
    • 建议使用第二种编译器指定方式,因为环境变量可能被设定为不适合当前项目的值;
    • 可以通过命令cmake --system-information来查看可用的比那一起和对应的编译器的标志;
  • 切换构建类型

    • 构建类型如Debug、Release等;
    • 控制生成构建系统使用的配置变量为CMAKE_BUILD_TYPE,该变量默认为空;
    • 使用
    # 准备
    ...
    # 设置默认的构建类型,并打印一条消息
    if(NOT CMAKE_BUILD_TYPE)
        set(CMAKE_BUILD_TYPE Release CACHE STRING "BUILD_TYPE" FORCE) # 设置该变量为缓存变量,可以通过缓存进行编辑
    endif()
    message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
    
    
    • 切换构建类型时可以使用如下命令进行切换
    ...
    cmake -D CMAKE_BUILD_TYPE=Debug ..
    ..
    
    
  • 设置编译器选项,即控制项目的编译标志

    • 计算不同的形状面积的函数位于不同文件中

    在这里插入图片描述

    • CMakeLists
    # 控制编译器标志的第一种方法
    ...
    # 主要代码
    message("C++ compiler flags: ${CMAKE_CXX_FLAGS}")
    # 为目标准备标志列表
    list(APPEND flags "-fPIC" "-Wall")
    if(NOT Win32)
        list(APPEND flags "-Wextra" "-Wpedantic")
    endif()
    # 添加新的目标库并附加依赖源
    add_library(geometry
        STATIC
        geometry_circle.cpp
        geometry_circle.hpp
        geometry_polygon.cpp
        geometry_polygon.hpp
        geometry_rhombus.cpp
        geometry_rhombus.hpp
        geometry_square.cpp
        geometry_square.hpp
    )
    # 设置编译选项
    target_compile_options(geometry PRIVATE ${flags})
    # 创建可执行目标
    add_executable(compute-areas compute-areas.cpp)
    # 为可执行目标设置编译选项
    target_compille_options(compute-areas PRIVATE "-fPIC")
    
    #链接可目标文件与库文件
    target_link_libraries(compute-areas geometry)
    ...
    
    
    • 控制编译器标志的第二种方法:不用对CMakeLists.txt进行修改,修改geometry和compute-areas目标的编译器选项可以使用CMAKE的参数进行配置:
...
cmake -D CMAKE_CXX_FLAGS="-fno-exceptions -fno-rtti" .. # 这个命令将编译项目, 禁用异常和运行时类型标识(RTTI)
...

# 也可以使用全局标志,即使用CMakeLists.txt运行下面的命令
cmake -D CMAKE_CXX_FLAGS="-fno-exceptions -fno-rtti" ..

  • 使用控制流

    • CMake提供了创建循环的语言工具: foreach-endforeach 和 while-endwhile,实际使用样例可以参考如下的foreach:
    # 准备
    ...
    add_library(geometry STATIC 文件列表)
    target_compile_options(PRIVATE -03)
    list(APPEND sources_with_lower_optimization geometry_circle.cpp geometry_rhombus.cpp)# 生成源文件列表
    
    # 循环以上文件列表中的文件,并将其优化级别调到-02
    message(STATUS "Setting source properties using IN LISTS syntax:")
    foreach(_source IN LISTS sources_with_lower_optimization)
    	set_source_files_properties(${_source} PROPERTIES COMPILE_FLAGS -02)
    	message(STATUS "Appending -02 flag for ${_source}")
    endforeach()
    
    # 检查是否设置正确
    message(STATUS "Querying source properties using IN plain syntax:")
    foreach(_source IN LISTS sources_with_lower_optimization)
    	get_source_file_property(${_source} PROPERTIES COMPILE_FLAGS)
    	message(STATUS "Source ${_source} has the following extra COMPILE_FLAGS:${_flags}")
    endforeach()
    ...
    
    
  • polo

[4]: http://adrai.github.io/flowchart.js/### 从可执行文件到库

  • 一些基础的注意事项
# set minimum cmake version 项目构建的开始需要设置最小的cmake版本,并定义不满足这一要求时的cmake行为
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)

# project name and language 项目名称和支持的编程语言
project(recipe-01 LANGUAGES CXX)
# 编译和链接源文件hell0-world.cpp以生成可执行文件hello-world
add_executable(hello-world hello-world.cpp)

+ 上述文件命名为CMakeLists.txt,区分大小写,否则无法解析;
+ CMake语言不区分大小写,但是参数区分大小写;
+ CMake中,c++是默认编程语言,但最好使用LANGUAGES选项在project中显示声明项目的语言;
+ 一些基础指令:

 
```
mkdir -p build # 创建生成构建器的位置
cd build 
cmake .. # 指定CMakeLists.txt所在位置

```
 为了不和源代码混淆,一般在源外创建生成构建其目录;
+ CMake是一个构建系统生成器,描述构建系统(VS, Ninja、Makefile等)如何操作才能编译代码;然后CMake为所选的构建系统生成相应的指令;
+ 如何切换生成器:


	- 通过生成器列表确定是否存在所需要的生成器:
	
	 
	```
	cmake -help
	
	```
	- 切换生成器:
	
	 
	```
	...
	cd build
	cmake -G Ninja .. # 即添加-G参数切换所需要使用的生成器
	cmake --build . 
	
	```
	 每个生成器都有自己的文件集,构建结果其生成的文件是不同的;
  • 构建和链接静态库和动态库

    • 构建所需要的CMakeLists.txt
    # ---准备操作---
    # set minimum cmake version
    cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
    
    # project name and language
    project(recipe-03 LANGUAGES CXX)
    
    # 创建目标-静态库
    # 生成必要的构建指令,将指定的源码编译到库中
    # 第二个参数为其他值时:
    # STATIC - 用于创建静态库,即编译文件的打包存档,用于在链接其他目标时使用;
    # SHARED - 用于创建动态库链接,并在运行时加载;
    # OBJECT - 将列表中的源码编译到目标文件,不将其进行归档到静态库和共享对象中;
    # MODULE - DSO组,不链接到项目中的任何目标,不过可以进行动态加载,用于构建运行时插件;
    add_library(message STATIC Message.hpp Message.cpp) 
    
    # 创建可执行文件
    # 将库链接到可执行文件,确保hello-world可执行文件正确依赖于message库
    add_executable(hello-world hello-world.cpp)
    
    # 目标库连接到可执行文件
    target_link_libraries(hello-world message)
    
    

    编译完成之后,会生成一个message.lib静态库文件;

    • 要保证编译的目标文件与生成位置无关, 可以通过使用 set_target_properties 命令;
    set_target_properties(message-objs
    	PROPERTIES
    	POSITION_INDEPENDENT_CODE 1
    )  
    
    
  • 条件语句控制编译

    • 条件结构为 if-else- else-endif ;
    • 如果需要在不同的行为之间进行切换,如构建静态库或动态库再生成可执行文件和直接生成可执行文件两种选择,则CMake中的文件条件语部分可以编写为:
    ...
    set(USE_LIBRARY OFF) # 设置变量
    message(STATUS "COMPILE SOURCE INTO A LIBRARY? ${USE_LIBRARY}")
    set(USE_SHARED_LIBS OFF)
    list(APPEND _source Message.hpp Message.cpp) # 将文件装入列表
    
    if(USED_LIBRARY)
        add_library(message ${_sources}) #_source是局部变量,前面加下划线,不应该再当前范围之外使用
        add_excutable(hello-world hello-world.cpp)
        target_link_libraries(hell-world message)
    else()
        add_excutable(hell-world hello-world.cpp ${_sources}) #添加方式有所不同
    endif()
    ...
    
    
  • 向用户显示选项,可以被用户选择性设置

    • 在CMake中使用option(),用于外部设置,从而切换构建系统的生成行为
    • 使用选项替换set(USE_LIBRARY OFF)命令,使得其在命令行可以被修改
    option(USE_LIBRARY "Compile sources into a library" OFF)
    # 三个参数:option(<option_variable> "help string" [initial value])
    # <option_variable> - 变量的名称
    # "help string" - 描述选项的字符段;
    # [initial value] - 选项的默认值
    
    
    # 编译时使用
    ...
    cd build
    cmake -D USE_LIBRARY=ON .. # -D开关用于为CMake设置任何类型的变量,如逻辑变量、路径等 
    cmake --build .
    
    
  • 指定编译器

    • CMake将语言的编译器存储在CMAKE__COMPILER 变量中,选择特定的编译器时,可以通过CMAKE__COMPILER进行选择,其中,可以是受支持的任意一种语言
    # 指定编译器的方式有两种
    # 第一种
    cmake -D CMKAE_CXX_COMPILER=clang++ ..
    
    # 第二种
    env CXX=clang++ cmake ..
    
    
    • 建议使用第二种编译器指定方式,因为环境变量可能被设定为不适合当前项目的值;
    • 可以通过命令cmake --system-information来查看可用的比那一起和对应的编译器的标志;
  • 切换构建类型

    • 构建类型如Debug、Release等;
    • 控制生成构建系统使用的配置变量为CMAKE_BUILD_TYPE,该变量默认为空;
    • 使用
    # 准备
    ...
    # 设置默认的构建类型,并打印一条消息
    if(NOT CMAKE_BUILD_TYPE)
        set(CMAKE_BUILD_TYPE Release CACHE STRING "BUILD_TYPE" FORCE) # 设置该变量为缓存变量,可以通过缓存进行编辑
    endif()
    message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
    
    
    • 切换构建类型时可以使用如下命令进行切换
    ...
    cmake -D CMAKE_BUILD_TYPE=Debug ..
    ..
    
    
  • 设置编译器选项,即控制项目的编译标志

    • 计算不同的形状面积的函数位于不同文件中

    image-20210908151927939

    • CMakeLists

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

 ![image-20210908151927939]()
+ CMakeLists

[外链图片转存中…(img-dD0njJOz-1715499831540)]
[外链图片转存中…(img-YrJ6bCcT-1715499831540)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值