程序猿的自我修养 Weilit

CMake相关

2019-11-11

Make or CMake, What’s different?

转载至CMake 学习笔记

Make

Make是什么

要设计一个软件系统,我们首先编写源码,然后通过编译器编译和创建可执行文件。可执行文件就是要实现最终功能的文件。“Make”是一个工具,它控制可执行程序和程序源文件中非源码文件的生成

“Make”工具需要清楚的知道如何构建程序。 它通过一个叫做“makefile”的文件知晓如何构建你的程序。这个文件列出了所有的非源码文件以及如何由别的文件来计算它。当你编写了一个程序,你应该为它写一个makefile文件,这样才有可能通过使用“Make”来构建和安装你的程序。 很简单的事情。如果你不理解的话,多读几遍这一段文字,因为理解这一段文字对于接下来的篇幅很重要。

为什么需要“Make”

首先,它可以使得终端用户构建和安装你的应用包,而不用去详细的了解它具体是如何做到的。每一个工程都有它自己的规则和细微的差别,这会使得每次在复用的时候会变得很痛苦。这就是我们创建这个makefile文件的原因。 构建步骤精确的记录在你提供的这个makefile文件中。“Make” 当源码文件发生变化时自动的指出哪一个文件需要更新。 同时,当一个非源码文件依赖的另一个非源码文件发生改变时,它也自动确定以适当的顺序进行更新文件。

其次,每次当我们改变了系统中的一小部分源码的时候,重新编译整个程序的效率是很低的。因此,当我们改变了一小部分的源码文件的时候重新执行“Make”,它将不会重新编译整个程序。它仅仅更新那些直接或者间接依赖这些改变了的源码文件的非源码文件。

很酷吧!“Make” 不局限于具体的语言。对于程序中的每一个非源码文件,makefile文件详细的说明了执行需要的shell命令。这些shell命令能够启动编译器产生目标文件,链接器产生可执行文件、更新库、镜像生成器格式化文档,等等。Make不仅仅局限于构建一个包,你也可以安装或者卸载一个包,生成索引表 或者其他一些你经常做的值得你写下来怎么去做的事情。

废话了那么多,简而言之就是自动化项目编链过程,及控制生成最终的目标文件。

CMake - “cross platform make”

相较 make 而言

CMake 支持跨平台 Make。 如果你不知道使用何种编译器,你不能使用相同的编译器去编译所有不同种类的源码。你可以手动的指用何种编译器,但是这将变得繁琐和痛苦。CMake 辨别使用哪种编译器去编译给出的源码种类,为每一种类型的目标平台按照正确的顺序调用命令。因此,将有很多非显式的命令,比如$(CC)。

如果你是代码强迫症,请继续往下读。如果你不喜欢这一切,你可以跳过这一部分。

一般的 编译/链接标识 处理头文件、库文件、以及重定位其他平台无关和构建系统独立命令。调试标识被包含,通过设置变量CMAKE_BUILD_TYPEdebug,或者在调用程序时传递给CMakecmake -DCMAKE——BUILD——TYPE:STRING=Debug

CMake 也提供平台无关的包含,通过‘-fPIC’标志(POSITION_INDEPENDENT_CODE属性)。因此,更多隐式的设置能够在 CMake 命令中实现,在 makefile 文件中也可以通过使用COMPILE_FLAGS或者相关的属性。当然,CMake在集成第三方库(像OpenGL)方面也变得更加轻便。你可以自己做所有的跨平台工作,但是这将花费很多时间。

CMake解决了这个问题,但是与此同时,它比GNU构建系统更有优势:

  • 用于编写CMakeLists.txt文件的语言具有可读性和很容易理解
  • 不仅可以使用“Make” 来构建工程
  • 支持多种生产工具,比如Xcode, Eclipse, Visual Studio, etc

CMake与Make对比具有以下优点:

  • 自动发现跨平台系统库
  • 自动发现和管理的工具集
  • 更容易将文件编译进共享库, 以一种平台无关的方式或者以比make更容易使用的的生成方式

CMake不仅仅只“make”,所以它变得更复杂。从长远来看,最好能够学会使用它。如果你仅仅在一个平台上构建小的工程,“Make”更适合完成这部分工作。

下面主要介绍 CMake

cmake生成makefile文件

cmake语法

用法:cmake dir_path                     (dir_path为CMakeLists.txt所在的路径,当前路径为pwd,可使用相对路径)
例:cmake -DCMAKE_BUILD_TYPE=release  ../../ncnn/    
    内部变量
        CMAKE_CXX_FLAGS                   编译时的选项,可以通过add_definitions添加编译选项
        CMAKE_BUILD_TYPE                  build类型,当前为release
        CMAKE_CURRENT_LIST_DIR            为dir_path (CMakeLists.txt文件所在的路径)
    命令
        project                           指定项目名称
        include_directories               指定头文件的搜索路径,相当于指定gcc的-I参数
        link_directories                  动态或静态链接库的搜索路径,相当于gcc的-L参数
        add_subdirectory                  包含子目录
        add_excutable                     编译可执行程序
        add_definitions                   添加编译参数
        target_link_libraries             添加链接库
        aux_source_directory              获得目录下的所有源文件
        option                            外部执行cmake命令时可指定值

cmake option

所有option定义的变量均可以在cmake的时候指定值,若不指定则使用默认值initial value。

option(<option_variable> "描述选项的帮助性文字" [initial value默认值])

# 举例说明:
option(BUILD_TEST "Build test" OFF)
# 使用cmake时:cmake -DBUILD_TEST=ON -DCMAKE_BUILD_TYPE=Debug ...
# 其中变量名前要加字母"D",以CMAKE开头的变量为cmake自带option

make 根据makefile文件进行编译

make VERBOSE=1 -j
    VERBOSE=1                             打印make的输出
    -j                                    使用多核进行编译(加快速度)

make的原理是执行一个叫Makefile文件里的指令,make的基本用处是自动根据makefile里的指令来编译源文件。它还可以用来做比如安装软件,卸载软件等事情,但前提是作者在makefile里写了。比如makefile里有这么些内容:

install :  
    < commands >

然后用make install的话,make程序就会按照上面install:后面的指令< commands >执行安装,uninstall也是一样的道理,大部分的作者会写有卸载的部分,这时只要简单地执行make unistall就可以,如果作者懒没有写,那就只有根据make install中的步骤,看它把什么文件拷到哪去了,然后分别手动删除。还有关键的一点是,编译安装完成后,不要删除源代码,不然就算作者写了unnistall目标,你也没有makefile可以执行了。


如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

¥ 打赏博主

类似文章

上一篇 C++学习笔记

下一篇 git常用命令

留言