cmake笔记

CMakeLists.txt内容

  1. PROJECT(projectname [CXX] [C] [Java]):
    定义工程名称,并可指定工程支持的语言,支持的语言列表是可以忽略的,默认情况表示支持所有语言。

    这个指令隐式的定义了两个cmake变量:< projectname >_BINARY_DIR 以
    < projectname>_SOURCE_DIR,因为采用的是内部编译,两个变量目前指的都是工程所在路径~/cmake_study,后面我们会讲到外部编译,两者所指代的内容会有所不同。同时cmake系统也帮助我们预定义了PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR变量,他们的值分别跟HELLO_BINARY_DIR与HELLO_SOURCE_DIR一致。为了统一起见,建议以后直接使用PROJECT_BINARY_DIR,PROJECT_SOURCE_DIR,即使修改了工程名称,也不会影响这两个变量。如果使用了< projectname >_SOURCE_DIR,修改工程名称后,需要同时修改这些变量。

  2. SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]]):

    SET指令可以用来显式的定义变量。

    比如我们用到的是SET(SRC_LIST main.c),如果有多个源文件,也可以定义成:
    SET(SRC_LIST main.c t1.c t2.c)。

  3. MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] “message to display”
    …)

    用于向终端输出用户定义的信息。

    包含了三种类型:
    SEND_ERROR,产生错误,生成过程被跳过。
    SATUS,输出前缀为—的信息。
    FATAL_ERROR,立即终止所有cmake过程.

  4. ADD_EXECUTABLE(hello ${SRC_LIST})

    生成可执行文件

    定义了这个工程会生成一个文件名为hello的可执行文件,相关的源文件是SRC_LIST中
    定义的源文件列表, 本例中你也可以直接写成ADD_EXECUTABLE(hello main.c)。

    在本例我们使用了${}来引用变量,这是cmake的变量应用方式,但是,有一些例外,比
    如在IF控制语句,变量是直接使用变量名引用,而不需要${}。如果使用了${}去应用变
    量,其实IF会去判断名为${}所代表的值的变量,那当然是不存在的了。实际上${}引用的是变量的值
    
  5. ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
    用于向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制存
    放的位置。EXCLUDE_FROM_ALL参数的含义是将这个目录从编译过程中排除,比如,工程
    的example,可能就需要工程构建完成后,再进入example目录单独进行构建(当然,你
    也可以通过定义依赖来解决此类问题)。
    ADD_SUBDIRECTORY(src bin)
    上面的例子定义了将src子目录加入工程,并指定编译输出(包含编译中间结果)路径为
    bin目录。如果不进行bin目录的指定,那么编译结果(包括中间结果)都将存放在
    build/src目录(这个目录跟原有的src目录对应),指定bin目录后,相当于在编译时
    将src重命名为bin,所有的中间结果和目标二进制都将存放在bin目录。

  6. ADD_LIBRARY(libname [SHARED|STATIC|MODULE] [EXCLUDE_FROM_ALL] source1 source2 … sourceN)
    例如: ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
    SHARED,动态库
    STATIC,静态库
    MODULE,在使用dyld的系统有效,如果不支持dyld,则被当作SHARED对待。
    EXCLUDE_FROM_ALL参数的意思是这个库不会被默认构建,除非有其他的组件依赖或者手
    工构建。

    如果你要指定libhello.so生成的位置,可以通过在主工程文件CMakeLists.txt中修
    改ADD_SUBDIRECTORY(lib)指令来指定一个编译输出位置或者

  7. SET_TARGET_PROPERTIES(target1 target2 … PROPERTIES prop1 value1 prop2 value2 …)
    这条指令可以用来设置输出的名称,对于动态库,还可以用来指定动态库版本和API版本。
    ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
    ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})
    SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME “hello”)
    这样,我们就可以同时得到libhello.so/libhello.a两个库了。

    8.INSTALL(TARGETS targets… [[ARCHIVE|LIBRARY|RUNTIME] [DESTINATION < dir >]
    [PERMISSIONS permissions…] [CONFIGURATIONS [Debug|Release|…] ] [COMPONENT < component >] [OPTIONAL] ] […])

    INSTALL指令用于定义安装规则,安装的内容可以包括目标二进制、动态库、静态库以及
    文件、目录、脚本等。

    参数中的TARGETS后面跟的就是我们通过ADD_EXECUTABLE或者ADD_LIBRARY定义的
    目标文件,可能是可执行二进制、动态库、静态库。

    目标类型也就相对应的有三种,ARCHIVE特指静态库,LIBRARY特指动态库,RUNTIME
    特指可执行目标二进制。

    DESTINATION定义了安装的路径,如果路径以/开头,那么指的是绝对路径,这时候
    CMAKE_INSTALL_PREFIX其实就无效了。如果你希望使用CMAKE_INSTALL_PREFIX来
    定义安装路径,就要写成相对路径,即不要以/开头,那么安装后的路径就是
    ${CMAKE_INSTALL_PREFIX}/<DESTINATION定义的路径>

    例如:
    INSTALL(TARGETS myrun mylib mystaticlib
    RUNTIME DESTINATION bin
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION libstatic
    )

    可执行二进制myrun安装到 $ {CMAKE_INSTALL_PREFIX}/bin目录
    动态库libmylib安装到$ {CMAKE_INSTALL_PREFIX}/lib目录
    静态库libmystaticlib安装到${CMAKE_INSTALL_PREFIX}/libstatic目录

    INSTALL(TARGETS hello hello_static
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib)

    安装库文件
    注意,静态库要使用ARCHIVE关键字

    INSTALL(FILES hello.h DESTINATION include/hello) 安装文件
    9. INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYSTEM] dir1 dir2 …)

    这条指令可以用来向工程添加多个特定的头文件搜索路径,路径之间用空格分割,如果路径
    中包含了空格,可以使用双引号将它括起来,默认的行为是追加到当前的头文件搜索路径的
    后面,你可以通过两种方式来进行控制搜索路径添加的方式:
    1,CMAKE_INCLUDE_DIRECTORIES_BEFORE,通过SET这个cmake变量为on,可以
    将添加的头文件搜索路径放在已有路径的前面。
    2,通过AFTER或者BEFORE参数,也可以控制是追加还是置前。

    INCLUDE_DIRECTORIES(/usr/include/hello)
    10. LINK_DIRECTORIES(directory1 directory2 …)和TARGET_LINK_LIBRARIES(target library1
    <debug | optimized> library2…)

    LINK_DIRECTORIES:添加非标准的共享库搜索路径,比如,在工程内部同时存在共享库和可
    执行二进制,在编译时就需要指定一下这些共享库的路径。
    TARGET_LINK_LIBRARIES:这个指令可以用来为target添加需要链接的共享库

CMake基本语法规则

  1. 变量使用${}方式取值,但是在IF控制语句中是直接使用变量名
  2. 指令(参数1 参数2…)
    参数使用括弧括起,参数之间使用空格或分号分开。
    以上面的ADD_EXECUTABLE指令为例,如果存在另外一个func.c源文件,就要写成:
    ADD_EXECUTABLE(hello main.c func.c)或者ADD_EXECUTABLE(hello main.c;func.c)
  3. 指令是大小写无关的,参数和变量是大小写相关的。但,推荐你全部使用大写指令。

清理工程:make clean 即可对构建结果进行清理。
建议使用外部构建

内部构建和外部构建

对于cmake,内部编译上面已经演示过了,它生成了一些无法自动删除的中间文件,所以,
引出了我们对外部编译的探讨,外部编译的过程如下:
1,首先,请清除t1目录中除main.c CmakeLists.txt之外的所有中间文件,最关键
的是CMakeCache.txt。
2,在t1目录中建立build 目录,当然你也可以在任何地方建立build目录,不一定必
须在工程目录中。
3,进入build目录,运行cmake …(注意,…代表父目录,因为父目录存在我们需要的
CMakeLists.txt,如果你在其他地方建立了build目录,需要运行cmake <工程的全
路径>),查看一下build目录,就会发现了生成了编译需要的Makefile以及其他的中间
文件.
4,运行make构建工程,就会在当前目录(build目录)中获得目标文件hello。

这里需要特别注意的是:
通过外部编译进行工程构建,HELLO_SOURCE_DIR仍然指代工程路径,即~/cmake_study
而HELLO_BINARY_DIR则指代编译路径,即~/cmake_study/build

换个地方保存目标二进制

不论是SUBDIRS还是ADD_SUBDIRECTORY指令(不论是否指定编译输出目录),我们都可
以通过SET指令重新定义EXECUTABLE_OUTPUT_PATH和LIBRARY_OUTPUT_PATH变量
来指定最终的目标二进制的位置(指最终生成的hello或者最终的共享库,不包含编译生成
的中间文件)

SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)

可执行二进制的输出路径为build/bin和库的输出路径为build/lib.

在哪里ADD_EXECUTABLE或ADD_LIBRARY,如果需要改变目标存放路径,就在哪里加入上述的定义。

< projectname >_BINARY_DIR和PROJECT_BINARY_DIR变量,他
们指的编译发生的当前目录,如果是内部编译,就相当于PROJECT_SOURCE_DIR也就是
工程代码所在目录,如果是外部编译,指的是外部编译所在目录,也就是本例中的build
目录。

如何安装

安装的需要有两种,一种是从代码编译后直接make install安装,一种是打包时的指定目录安装。

cmake -DCMAKE_INSTALL_PREFIX=/usr

INSTALL指令用于定义安装规则,安装的内容可以包括目标二进制、动态库、静态库以及
文件、目录、脚本等。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值