• 小知识·认识CMake


    目录

    一、CMake简介

    二、安装CMake

    三、最简单的例子:HelloWorld

    四、基本语法规则

    五、内部构建与外部构建

    六、小结


     

    一、CMake简介

    Make 工具里面,比较出名的有 GNU Make,Qt 的 qmake,微软的 MS nmake,BSD Make(pmake),Makepp,等等。这些 Make 工具遵循着不同的规范和标准,所执行的 Makefile 格式也千差万别。这样就带来了一个严峻的问题:如果软件想跨平台,必须要保证能够在不同平台编译。而如果使用上面的 Make 工具,就得为每一种标准写一次 Makefile ,这将是一件让人抓狂的工作。

    而每次对出现的问题进行解决,即是一次对效率化的贡献。因此 CMake 应运而生。

    它可以让程序员通过一个与开发平台无关的 CMakeList.txt 文件来定制整个编译流程,然后再根据目标用户的平台进一步生成所需的 Makefile 和工程文件,如 *nix 平台的 Makefile 或者 win 平台下面的 VS 工程。

    一些比较出名的开源项目以及商业项目,也都是采用 CMake 作为项目架构系统,比如 KDE 以及OpenCV,奈飞(Netflix),第二人生(Second Life),还有 LLVM 和 Clang,MySQL 等等。

    二、安装CMake

    CMake 目前已经成为各大 Linux 发行版提供的组件,比如 Ubuntu 直接在系统中包含,所以,需要自己动手安装的可能性很小。如果你使用的操作系统没有提供 CMake 或者包含的版本较旧,有以下两种下载方法。

    可以直接在命令行下载CMake:

    $ sudo apt-get install CMakek
    

    也可以从官网下载最新版本:

    http://www.CMake.org/HTML/Download.html
    

    三、最简单的例子:HelloWorld

    下面选择一个最简单的例子 Helloworld 来演练一下 CMake 的完整构建过程,并不会深入的探讨 CMake,仅仅展示一个简单的例子,并加以粗略的解释。

    1,准备工作

    首先,在 /backup 目录建立一个 CMake 目录,用来放置我们学习过程中的所有练习。

    $ mkdir -p /backup/CMake
    

    然后在 CMake 建立第一个练习目录 t1 。

    1. $ cd /backup/CMake
    2. $ mkdir t1
    3. $ cd t1

    在 t1 目录建立 main.c 和 CMakeLists.txt(注意文件名大小写)。

    main.c 文件内容:

    1. #include
    2. int main()
    3. {
    4. printf("Hello world!\n");
    5. return 0;
    6. }

    CMakeLists.txt 文件内容:

    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_EXECUTABLE(hello ${SRC_LIST})

    2,开始构建

    所有的文件创建完成后,t1 目录中应该存在 main.c 和 CMakeLists.txt 两个文件。接下来我们来构建这个工程,在这个目录运行(注意命令后面的点号,代表本目录):

    $ CMake .
    

    输出大概是这个样子:

    1. -- Check for working C compiler: /usr/bin/gcc
    2. -- Check for working C compiler: /usr/bin/gcc -- works
    3. -- Check size of void*
    4. -- Check size of void* - done
    5. -- Check for working CXX compiler: /usr/bin/c++
    6. -- Check for working CXX compiler: /usr/bin/c++ -- works
    7. -- This is BINARY dir /backup/CMake/t1
    8. -- This is SOURCE dir /backup/CMake/t1
    9. -- Configuring done
    10. -- Generating done
    11. -- Build files have been written to: /backup/CMake/t1

    再让我们看一下目录中的内容,你会发现,系统自动生成了: CMakeFiles、CMakeCache.txt、CMake_install.CMake 等文件,并且生成了 Makefile。

    现在不需要理会这些文件的作用,以后你也可以不去理会。最关键的是,它自动生成了Makefile.。

    然后进行工程的实际构建,在这个目录输入 make 命令,大概会得到如下的彩色输出:

    1. Scanning dependencies of target hello
    2. [100%] Building C object CMakeFiles/hello.dir/main.o
    3. Linking C executable hello
    4. [100%] Built target hello

    如果你需要看到 make 构建的详细过程,可以使用 make VERBOSE=1 或者 VERBOSE=1 make 命令来进行构建。

    这时候,我们需要的目标文件 hello 已经构建完成,位于当前目录,尝试运行一下:

    $ ./hello
    

    得到输出:

    Hello World from Main 
    

    恭喜您,到这里为止您已经完全掌握了 CMake 的使用方法。

    3,简单的解释

    我们来重新看一下 CMakeLists.txt,这个文件是 CMake 的构建定义文件,文件名是大小写相关的,如果工程存在多个目录,需要确保每个要管理的目录都存在一个CMakeLists.txt。(关于多目录构建,后面我们会提到,这里不作过多解释)。

    上面例子中的 CMakeLists.txt 文件内容如下:

    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_EXECUTABLE(hello ${SRC_LIST})

    PROJECT

    PROJECT 指令的语法是 :

    PROJECT(projectname  [CXX]  [C]  [Java]) 
    

    你可以用这个指令定义工程名称,并可指定工程支持的语言,支持的语言列表是可以忽略的,默认情况表示支持所有语言。

    这个指令隐式的定义了两个 CMake 变量:
    _BINARY_DIR以及_SOURCE_DIR,这里就是HELLO_BINARY_DIR 和HELLO_SOURCE_DIR(所以 CMakeLists.txt 中两个 MESSAGE指令可以直接使用这两个变量),因为采用的是内部编译,两个变量目前指的都是工程所在路径/backup/CMake/t1,后面我们会讲到外部编译,两者所指代的内容会有所不同。

    同时 CMake 系统也帮助我们预定义了 PROJECT_BINARY_DIR 和 PROJECT_SOURCE_DIR变量,他们的值分别跟 HELLO_BINARY_DIR 与 HELLO_SOURCE_DIR 一致。为了统一起见,建议以后直接使用PROJECT_BINARY_DIRPROJECT_SOURCE_DIR,即使修改了工程名称,也不会影响这两个变量。

    SET

    SET 指令的语法是 :

    SET(VAR [VALUE] [CACHE  TYPE  DOCSTRING [FORCE]]) 
    

    现阶段,你只需要了解 SET 指令可以用来显式的定义变量即可。

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

    SET(SRC_LIST  main.c  t1.c  t2.c)
    

    MESSAGE

    MESSAGE 指令的语法是:

    MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message to display" ...) 
    

    这个指令用于向终端输出用户定义的信息,包含了三种类型:

    • SEND_ERROR,产生错误,生成过程被跳过。
    • SATUS,输出前缀为—的信息。
    • FATAL_ERROR,立即终止所有 CMake 过程.

    我们在这里使用的是 STATUS 信息输出,演示了由 PROJECT 指令定义的两个隐式变量HELLO_BINARY_DIRHELLO_SOURCE_DIR

    ADD_EXECUTABLE

    ADD_EXECUTABLE 指令的语法是:

    ADD_EXECUTABLE(hello ${SRC_LIST}) 
    

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

    将本例改写成一个最简化的 CMakeLists.txt:

    1. PROJECT(HELLO)
    2. ADD_EXECUTABLE(hello main.c)

    可以使用 make clean 对构建结果进行清理。

    四、基本语法规则

    前面提到过,CMake 其实仍然要使用”CMake 语言和语法”去构建,上面的内容就是所谓的”CMake 语言和语法”,最简单的语法规则是:

    • 变量使用${}方式取值,但是在 IF 控制语句中可以直接使用变量名

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

    • 指令是大小写无关的,参数和变量是大小写相关的。但推荐你全部使用大写指令。

    五、内部构建与外部构建

    上面的例子展示的是“内部构建”,相信看到生成的临时文件比您的代码文件还要多的时候,估计这辈子你都不希望再使用内部构建。

    而外部编译的过程如下:

    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。

    上述过程就是所谓的 out-of-source 外部编译,一个最大的好处是,对于原有的工程没有任何影响,所有动作全部发生在编译目录。通过这一点,也足以说服我们全部采用外部编译方式构建工程。

    六、小结

    本小节描述了使用 CMake 构建 Hello World 程序的全部过程,并介绍了三个简单的指令:PROJECT、MESSAGE、ADD_EXECUTABLE 以及变量调用的方法,同时提及了两个隐式变量 _SOURCE_DIR 及 _BINARY_DIR,演示了变量调用的方法 。

  • 相关阅读:
    计算机毕业设计Java餐厅点餐系统(源码+系统+mysql数据库+lw文档)
    数据结构(十三)树
    C#应用程序界面开发基础——窗体控制
    2023最新最全【Nacos】零基础安装教程
    基于JAVA门诊预约挂号系统计算机毕业设计源码+数据库+lw文档+系统+部署
    service 自我升级遇到的问题
    YAPI介绍及Docker Compose部署指南
    系列十二、强引用、软引用、弱引用、虚引用分别是什么?
    IIS之WEB服务器
    烽火传递——单调队列优化dp问题
  • 原文地址:https://blog.csdn.net/m0_64560763/article/details/127421659