zoukankan      html  css  js  c++  java
  • Cmake实践(Cmake Practice)第一部分

    参考资料地址:https://github.com/Akagi201/learning-cmake/blob/master/docs/cmake-practice.pdf

    一、初识cmake

    1. Cmake特点

    • 开放源代码
    • 跨平台
    • 能够管理大型项目
    • 简化编译构建和编译过程(常用流程:cmake + make)
    • 高效率
    • 可扩展
    • 每个目录编写一份CMakeLists.txt

    二、初试cmake —— helloworld

    1. 准备工作

    mkdir -p /backup/cmake

    cd /backup/cmake

    mkdir t1

    cd t1

    在t1目录建立main.c和CMakeLists.txt文件:

    //main.c
    1
    #include<stdio.h> 2 int main() 3 { 4 printf("Hello World from t1 Main! "); 5 return 0; 6 }
    //CMakeLists
    1
    PROJECT(HELLO) 2 SET(SRC_LIST main.c) 3 MESSAGE(STATUS "This is BINARY dir " ${HELLO_BINARY_DIR} 4 MESSAGE(STATUS "This is SOURCE dir " ${HELLO_SOURCE_DIR}) 5 ADD_EXECTUABLE(hello SRC_LIST)

     2. 开始构建

    cmake .     //生成Makefile、CMakeFiles、CMakeCache.txt等文件

    make [VERBOSE=1]    //实际构建工程,VERBOSE=1可查看make构建的详细过程

    ./hello    //运行目标文件

    3. CMakeLists.txt代码解释

    (1)PROJECT指令的语法

    PROJECT(projectname [CXX] [C] [Java])  //定义工程名称,并指定支持的语言(默认支持所有语言)

    该指令隐式的定义了两个cmake变量:<projectname>_BINARY_DIR以及<projectname>_SOURCE_DIR,内部编译的情况下,两个变量相同,如上述工程中均为/backup/cmake/t1,外部编译则有所不同

    同时cmake系统也自动预定义了PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR变量,他们的值分别跟HELLO_BINARY_DIR与HELLO_SOURCE_DIR一致;建议直接使用PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR变量,避免工程名称的影响

    (2)SET指令的语法

    SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]])  //用来显式的定义变量
    如:SET(SRC_LIST main.c),如果有多个源文件:SET(SRC_LIST main.c t1.c t2.c)

    (3)MESSAGE指令的语法

    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)

    4. 基本语法规则

    (1)变量使用${var}方式取值,但是在IF控制语句中是直接使用变量名

    (2)指令(参数1 参数2...)  //参数使用括弧括起,参数之间使用空格或分号分开

    (3)指令是大小写无关的,参数和变量是大小写相关的。建议全部使用大写指令

    5. 清理工程:make clean

    6. 内部构建与外部构建(in-source build, out-of-source build)

    (1)内部编译不足:生成的中间临时文件与代码文件混在一起,且无法自动删除

    (2)外部编译过程

    • 清除上述t1目录中的除main.c和CMakeLists.txt之外的所有中间文件,特别是CMakeCache.txt
    • 在t1目录中新建build目录  //也可以建在其他位置
    • 进入build目录,运行cmake ..  //..代表父目录,也可以输入工程代码文件的全路径;最终在build目录中生成编译需要的Makefile和其他中间文件
    • 运行make  //在当前目录(build)中生成hello目标文件

    //外部编译优势:对原有的工程没有任何影响,所有的活动均发生在编译目录(build)

    //注意:此时的HELLO_SOURCE_DIR仍然指代工程路径,即/backup/cmake/t1;而HELLO_BINARY_DIR则指代编译路径,即/backup/cmake/t1/build

    三、更好的Hello World

    在采用外部构建的基础上(构建目录为build子目录),修改上述Hello World使得更像一个工程,实现目标如下:

    • 为工程添加一个子目录src,用来放置工程源代码
    • 添加一个子目录doc,用来放置这个工程的文档hello.txt
    • 在工程目录添加文本文件COPYRIGHT, README
    • 在工程目录添加一个runhello.sh脚本,用来调用hello二进制
    • 将构建后的目标文件放入构建目录的bin子目录
    • 最终安装这些文件:将hello二进制与runhello.sh安装至/usr/bin,将doc目录的内容以及COPYRIGHT/README安装到/usr/share/doc/cmake/t2

    1. 准备工作

    mkdir -p /backup/cmake/t2

    cd /back/cmake/t1  +  cp main.c CMakeLists.txt ../t2

    2. 添加子目录src

    cd /back/cmake/t2

    mkdir src

    mv main.c src

    每个目录的CMakeLists.txt如下:

    // /backup/cmake/t2/CMakeLists.txt
    1
    PROJECT(HELLO) 2 ADD_SUBDIRECTORY(src bin)  //bin目录为编译输出(包含编译中间结果)的目录
    // /backup/cmake/t2/src/CMakeLists.txt
    1
    ADD_EXECUTABLE(hello main.c)

    mkdir build  +  cd build

    cmake ..  +  make  //构建生成的hello目标文件位于build/bin目录中

    语法解释(ADD_SUBDIRECTORY指令):

    ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

    用于向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制文件存放的位置,EXCLUDE_FROM_ALL用于将指定目录从编译过程中排除,如工程中的example目录可以在工程构建完成后进行单独构建;如果未指定binary_dir则编译输出(包含中间结果)目录为build/src(与源文件src目录对应)

    3. 指定目标二进制的保存位置

    利用SET指令重新指定最终生成的目标二进制位置(指hello或者共享库,不包含编译生成的中间文件

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

    注:指令加到哪个CMakeLists.txt?添加原则:在哪里ADD_EXECUTABLE或ADD_LIBRARY,如果需要改变目标存放路径,就在哪里加入上述的定义,本例中为src子目录下的CMakeLists.txt

    4. 如何安装?

    (1)直接make install  //将hello安装到/usr/bin目录

    (2)直接make install DESTDIR=/tmp/test  //安装到/tmp/test/usr/bin目录(打包时常用

    5. 修改Helloworld支持安装 (用到cmake的INSTALL指令和CMAKE_INSTALL_PREFIX变量)

    (1)添加doc目录及文件

    cd /backup/cmake/t2

    mkdir doc

    vim doc/hello.txt  //填写任意内容并保存

    (2)在工程目录添加runhello.sh脚本、COPYRIGHT和README

    cd /backup/cmake/t2

    vim runhello.sh  //内容为hello

    touch COPYRIGHT

    touch README

    (3)改写各目录下的CMakeLists.txt文件

    • 安装COPYRIGHT和README,直接修改主工程目录CMakeLists.txt文件,加入如下指令:INSTALL(FILES COPYRIGHT README DESTINATION share/doc/cmake/t2)
    • 安装runhello.sh,直接修改主工程目录CMakeLists.txt文件,加入如下指令:INSTALL(PROGRAMS runhello.sh DESTINATION bin)
    • 安装doc中的hello.txt,有两种方式:一是通过在doc目录建立CMakeLists.txt并将doc目录通过ADD_SUBDIRECTORY加入工程来完成;另一种是直接在主工程目录通过INSTALL(DIRECTORY ...)实现——INSTALL(DIRECTORY doc/ DESTINATION share/doc/cmake/t2);其中“doc/”表明安装doc目录中的内容,而非整个目录

    注:DESTINATION均使用相对路径,安装后的路径为${CMAKE_INSTALL_PREFIX}/<DESTINATION定义的路径>,若采用绝对路径则CMAKE_INSTALL_PREFIX其实就无效的

    6. 运行修改内容

    cd build

    cmake -D CMAKE_INSTALL_PREFIX=/tmp/t2/usr ..  //CMAKE_INSTALL_PREFIX的默认定义是/usr/local

    make

    make install

    进入/tmp/t2目录查看安装结果:
    ./usr
    ./usr/share
    ./usr/share/doc
    ./usr/share/doc/cmake
    ./usr/share/doc/cmake/t2
    ./usr/share/doc/cmake/t2/hello.txt
    ./usr/share/doc/cmake/t2/README
    ./usr/share/doc/cmake/t2/COPYRIGHT
    ./usr/bin
    ./usr/bin/hello
    ./usr/bin/runhello.sh

  • 相关阅读:
    基于应用外壳的架构
    示例代码和环境配置
    获取元素位置信息:getBoundingClientRect
    nodejs学习记录
    网页整理 --- 要换工作了,把这一堆网页先存起来
    删除网页上的广告
    周数的处理
    十六进制
    [例]字体改变,文章位置不变
    haslayout和BFC
  • 原文地址:https://www.cnblogs.com/hg-love-dfc/p/10242391.html
Copyright © 2011-2022 走看看