从零开始学习构建系统之cmake(二)

概述

一个基于cmake的构造系统是通过一系列逻辑上的target组织起来的,一个target对应于一个可执行文件或者库,或者是一个自定义的一个target,其包含了一些自定义的命令,target之间的依赖关系决定了构建的顺序以及对于修改的重新生成的规则。

二进制 Target

可执行文件和库是通过使用add_executable()和add_library()命令来定义的,其产生的结果二进制文件会有一些前缀、后缀和一些基于平台的扩展,二进制文件只见的依赖关系是通过使用target_link_library()命令表达的:

add_library(archive archive.cpp zip.cpp lzma.cpp)
add_executable(zipapp zipapp.cpp)
target_link_libraries(zipapp archive)

archive是被定义成一个静态库,archive是由archive.cpp,zip.cpp和lzma.cpp编译而来,zipapp被定义为一个二进制文件,通过编译连接zipapp.cpp得来,在链接的时候会将之前生成的静态库archive链接进来。

二进制可执行文件

通过add_executable命令可以定义一个可执行target

add_excutable(mytool mytool.cpp)

在cmake中的一些命令如add_custom_command可以产生一些在运行时使用的规则,从而当作一个可执行的target看起来就象一个命令可执行文件,这个可执行文件是由一系列的命令组成而不是有源文件编译而成,构建系统会保证在运行这些命令前这个命令可执行文件已经生成。

二进制库

如果没有指定库的类型,默认情况下add_library命令定义的是静态库,可以通过以下命令来指定库的类型:

add_library(archive SHARED archive.cpp zip.cpp lzma.cpp)
add_library(archive STATIC archive.cpp zip.cpp lzma.cpp)

除了上述的这种方式,还可以通过全局标志位BUILD_SHARED_LIBS来设置编译的二进制库的类型,当这个标志位为true,如果没有特别指定二进制库的类型就会编译为动态库。在构建系统定义的上下文中,是动态库还是静态库并没有太大关系,因为命令、依赖规范和其他的API的工作方式对于静态库和动态库是相同的。但是MODULE库有点特殊,因为其通常不会链接,所以不能在target_link_libraries()中使用MODULE库,其会在运行时当一个插件使用,如果库不会导出任何符号那么就不能编译为动态库,因为动态库会至少到处一个符号,可以通过以下命令编译一个MODULE库

add_library(archive MODULE 7z.cpp)

Apple Frameworks

一个动态库可以通过FRAMEWORK属性去创建一个macOS或者iOS Framework Bundle,如果一个库带有FRAMEWORK属性那么应该同时设置FRAMEWORK_VERSION属性,这个属性按照macOS的惯例设置为"A",MACOSX_FRAMEWORK_IDENTIFIER设置bundle的唯一标识符。

add_library(MyFramework SHARED MyFramework.cpp)
set_target_properties(MyFramework PROPERTIES
    FRAMEWORK TRUE
    FRMAEWORK_VERSION A
    MACOSX_FRAMEWORK_IDENTIFIER org.cmake.MyFramework)

Object 库

一个OBJECT库类型定义了一系列从源码编译得来的object文件,object文件集合可以通过$<TARGET_OBJECT:name>语法来作为其他target的输入,这是一个生成表达式可以用来给其他target提供OBJECT库:

add_library(archive OBJECT archive.cpp zip.cpp lzma.cpp)

add_library(archiveExtras STATIC $<TARGET_OBJECT:archive> extras.cpp)

add_executable(test_exe $<TARGET_OBJECT:archive> test.cpp)

其他的target在链接阶段除了使用自己的源文件外,也会使用object文件的集合,与此同时,一个Object库可以被多个target链接:

add_library(archive OBJECT archive.cpp zip.cpp lzma.cpp)

add_library(archiveExtras STATIC extras.cpp)
target_link_library(archiveExtras PUBLIC archive)

add_execurable(test_exe test.cpp)
target_link_library(test_exe archive)

其他target的链接步骤将会使用链接的OBJECT库的object文件,此外,在那些其他目标中编译源代码时,将遵守 OBJECT 库的使用要求。此外,这些使用要求将传递给那些其他目标的依赖者,在使用 add_custom_command(TARGET) 命令签名时,对象库不能用作TARGET。但是,通过使用 $<TARGET_OBJECTS:objlib>,add_custom_command(OUTPUT)或file(GENERATE)可以使用对象列表。

最后

这篇文章主要介绍了cmake构建系统各种库文件的内容,更多文章可以关注公众号QStack。

猜你喜欢

转载自blog.csdn.net/QStack/article/details/129034858