cmake Targets:CMake如何构建简单的Target

  • Post author:
  • Post category:其他


CMake有三个基本命令,用于定义CMake Target,分别是:

  • add_executable()                                // 构建exe
  • add_library()                                       // 构建库
  • add_custom_target()                         // 自定义构建目标在camke构建阶段运行的

add_executable()

add_executable(<name> [WIN32] [MACOSX_BUNDLE]
                [EXCLUDE_FROM_ALL]
                [source1] [source2 ...])

尖括号是必须要填的方括号是表示可选的.

该命令用于定义一个可以构建可执行程序的Target.

第一个参数是Target的名字,这个参数必须提供.

第二个参数

WIN32

是可选的参数,Windows平台特定的参数.

第三个参数

MACOSX_BUNDLE

跟第二个参数类似是Mac平台特有的参数.

第四个参数

EXCLUDE_FROM_ALL

如果存在,那CMake默认构建的时候是不会构建这个Target.

后续source1等等,可选参数均为该构建可执行文件所需的源码.

例如:

add_executable(Tutoral ${CMAE_CURRENT_SOURCE_DIR}main/main.cpp)

我构建了一个Tutoral可执行文件,使用的源码是这个路径下的${CMAE_CURRENT_SOURCE_DIR}main/main.cpp 源码

${CMAE_CURRENT_SOURCE_DIR} 这个参数是当前cmake文件的路径.

add_library()

 add_library(<name> [STATIC | SHARED | MODULE]
             [EXCLUDE_FROM_ALL]
             [<source>...])

和add_executable()非常相似,该命令用于构建成库文件的Target.

add_library()命令支持可选的三个互斥参数: STATIC | SHARED | MODULE.这三个参数要么都不写,要么只写一个.这个三个参数的意思是STATIC(静态库),SHARED(动态库),MODULE(类似于动态库,不过不会被其他库或者可执行程序链接,用于插件式框架的软件的插件构建)

当然最佳的实践是不要自己在CMakeLists.txt中指定这几个参数,而是把主动权交给构建者,通过cmake -DBUILD_SHARED_LIBS=YES 的形式告诉其需要构建那种库.

add_custom_target()

add_custom_target(Name [ALL] [command1 [args1...]]
                   [COMMAND command2 [args2...] ...]
                   [DEPENDS depend depend depend ... ]
                   [BYPRODUCTS [files...]]
                   [WORKING_DIRECTORY dir]
                   [COMMENT comment]
                   [JOB_POOL job_pool]
                   [VERBATIM] [USES_TERMINAL]
                   [COMMAND_EXPAND_LISTS]
                   [SOURCES src1 [src2...]])

关于Target链接

Target之间在构建的时候可能会出现A依赖B,B依赖C等情况.一般这种依赖都是因为某个Target需要链接另外一个Target.用C++的知识来说就是编译器在链接阶段需要的库.

在CMake中我们使用target_link_libraries()命令来实现这一点.

target_link_libraries(<targetName> <PRIVATE | PUBLIC | INTERFACE> ... <item>... ...)

第一个参数必须指定,改名字由add_executable()或者add_libraries()命令创建的Target的名字.

后续可以接多个PRIVATE,PUBLIC,INTERFACE选项,这三个选项类似于C++类定义的private,public,protect.

这三个选项后面跟着iterms 一般是一些类库的名字,这些库由add_libraries()命令创建的Target的名字.也可以是其他方式引入的库的名字.

PRIVATE选项的含义是:targetName这个target会链接PRIVATE选项后的iterms指定的这些库,这些库只有targetName这个Target本身需要,其他任何链接这个target的其他Target都不知道这些iterms的存在.

PUBLIC选项的含义:不止targetName本身这个Target需要这些iterms,其他链接到targetName的Target也需要依赖这些iterms并链接这些iterms.

INTERFACE选项的含义:targetName本身不需要这些iterms,但是其他链接targetName的Target需要依赖这些iterms,并链接这些iterms.

最佳实践

  • 不要将Target的名字设置为${projectName}
  • 给库命名的时候避免lib前缀
  • 如果没有足够的理由,在定义库目标的时候不要使用STATIC或SHARED关键字,控制权应该交给构建时的开发者(BUILD_SHARED_LIBS)
  • target_link_libraries()总是指明PROIVATE,PUBLIC,INTERFACE



版权声明:本文为m0_38036750原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。