[翻译] CMake 和 Make 之间的区别

本贴最后更新于 3076 天前,其中的信息可能已经东海扬尘

本文翻译的是一篇英文文档,主要讲述的是 CMake 和 Make 之间的区别。下文中首先列出文章的中文翻译,然后紧接着的是英文原文。


下面是中文翻译部分:
    编程人员已经使用 CMake 和 Make 很长一段时间了。当你加入一家大公司或者开始在一个具有大量代码的工程上开展工作时,你需要注意所有的构建。你需要看到处跳转的"CMakeLists.txt"文件。你应该会在终端使用"cmake"和"make"。很多人都是盲目的跟着操作说明而并不在意我们已何种方式去做我们需要做的事。构建的整个过程是什么?为什么要用这种方式去组织?Cmake 和 Make 之间有什么区别?这有关系吗?他们可以互相转换吗?
    事实证明,它们之间有很多的不同。理解它们之间的不同很重要,这样你可以确保在使用的过程中不会陷入麻烦。在讲述它们之间的区别之前,我们首先来看看它们是什么。
Make
    要设计一个软件系统,我们首先编写源码,然后通过编译器编译和创建可执行文件。可执行文件就是要实现最终功能的文件。“Make”是一个工具,它控制可执行程序和程序源文件中非源码文件的生成。
    “Make”工具需要清楚的知道如何构建程序。 它通过一个叫做“makefile”的文件知晓如何构建你的程序。这个文件列出了所有的非源码文件以及如何由别的文件来计算它。当你编写了一个程序,你应该为它写一个 makefile 文件,这样才有可能通过使用“Make”来构建和安装你的程序。 很简单的事情。如果你不理解的话,多读几遍这一段文字,因为理解这一段文字对于接下来的篇幅很重要。
为什么需要“Make”
    需要”make”的一个原因是,它可以使得终端用户构建和安装你的应用包,而不用去详细的了解它具体是如何做到的。每一个工程都有它自己的规则和细微的差别,这会使得每次在复用的时候会变得很痛苦。这就是我们创建这个 makefile 文件的原因。 构建步骤精确的记录在你提供的这个 makefile 文件中。“Make” 当源码文件发生变化时自动的指出哪一个文件需要更新。 同时它也自动确定以适当的顺序进行更新文件,当一个非源码文件依赖的另一个非源码文件发生改变时。
    每次当我们改变了系统中的一小部分源码的时候,重新编译整个程序的效率是很低的。因此,党我们改变了一小部分的源码文件的时候重新执行“Make”,它将不会重新编译整个程序。它仅仅更新那些直接或者间接依赖这些改变了的源码文件的非源码文件。很酷吧!“Make” 不局限于具体的语言。对于程序中的每一个非源码文件,makefile 文件详细的说明了执行需要的 shell 命令。这些 shell 命令能够启动编译器产生目标文件,链接器产生可执行文件,ar 更新库,镜像生成器格式化文档,等等。。。Make 不仅仅局限于构建一个包。你也可以安装或者卸载一个包,生成索引表或者其他一些你经常做的值得你写下来怎么去做的事情。
CMake
    CMake 支持跨平台 Make。 CMake 辨别使用那种编译器去编译给出的源码种类。如果你不知道使用何种编译器,你不能使用相同的编译器去编译所有不同种类的源码。你可以手动的指用何种编译器,但是这将变得繁琐和痛苦。CMake 为每一种类型的目标平台按照正确的顺序调用命令。因此,将有很多非显式的命令,比如 $(CC).
    如果你是代码强迫症,请继续往下读。如果你不喜欢这一切,你可以跳过这一部分。一般的编译/链接标识处理头文件、库文件、以及重定位其他平台无关和构建系统独立命令。调试标识被包含,通过设置变量 CMAKE_BUILD_TYPE 为“debug”,或者在调用程序的使用传递给 CMake:cmake -DCMAKE——BUILD——TYPE:STRING=Debug。
    CMake 也提供平台无关的包含,通过‘-fPIC’标志(POSITION_INDEPENDENT_CODE 属性)。因此,更多隐式的设置能够在 CMake 命令中实现,在 makefile 文件中也可以(通过使用 COMPILE_FLAGS 或者相关的属性)。当然,CMake 在集成第三方库(像 OpenGL)方面也变得更加轻便。
它们之间有什么不同点?
    如果你要使用编译脚本,构建的过程中有一个步骤,也就是需要在命令行中输入”make”。 对于 CMake,需要进行 2 步:第一,你需要配置你的编译环境(可以通过在你的编译目录中输入 cmake <source_dir>,也可以通过使用 GUI 客户端)。这将创建一个等效的,依赖你选择的编译环境的编译脚本或其他。编译系统可以传递给 CMake 一个参数。总之,CMake 根据你的系统配置选择合理的的默认的选择。第二,你在你选择的编译系统中执行实际的构建。
    你将进入 GNU 构建系统领域。 如果你不熟悉这个,这一段对于你来说就是碎碎念了。现在,说完了一些严肃的警告,往下走把! 我们可以使用 Autotool 来比较 CMake。当我们这样做的时候,我们会发现 Make 的缺点,而且这就是 Autotool 产生的理由了。我们可以看到 CMake 明显比 Make 优越的理由了。Autoconf 解决了一个重要的问题,也就是说与系统有关的构建和运行时信息的的可信赖发现。但是,这仅仅是轻便软件的开发中的一小部分。作为结尾,GNU 工程已经开发了一系列集成的实用程序,用于完成 Autoconf 开始之后的工作:GNU 构建系统中最重要的组件是 Autoconf, Automake, and Libtool.
    “Make”就不能那样做了,至少不修改任何东西是做不到的。你可以自己做所有的跨平台工作,但是这将花费很多时间。CMake 解决了这个问题,但是与此同时,它比 GNU 构建系统更有优势:

  • 用于编写 CMakeLists.txt 文件的语言具有可读性和很容易理解。
  • 不仅可以使用“Make” 来构建工程。
  • 支持多种生产工具,比如 Xcode, Eclipse, Visual Studio, etc.
        CMake 与 Make 对比具有以下优点:
  • 自动发现跨平台系统库。
  • 自动发现和管理的工具集
  • 更容易将文件编译进共享库, 以一种平台无关的方式或者以比 make 更容易使用的的生成方式。
        CMake 不仅仅只“make”,所以它变得更复杂。从长远来看,最好能够学会使用它。如果你仅仅在一个平台上构建小的工程,“Make”更适合完成这部分工作。

下面是本文的英文原文部分:
CMake vs Make
    Programmers have been using CMake and Make for a long time now. When you join a big company or start working on a project with a large codebase, there are all these builds that you need to take care of.You must have seen those “CMakeLists.txt” files floating around. You are supposed to run “cmake” and “make” commands on the terminal. A lot of people just follow the instructions blindly, not really caring about why we need to do things in a certain way. What is this whole build process and why is it structured this way? What are the differences between CMake and Make? Does it matter? Are they interchangeable?
    As it turns out, they are quite different. It is important to understand the differences between them to make sure you don’t get yourself in trouble. Before getting into the differences, let’s first see what they are.
Make
    The way in which we design a software system is that we first write code, then the compiler compiles it and creates executable files. These executable files are the ones that carry out the actual task. “Make” is a tool that controls the generation of executables and other non-source files of a program from the program’s source files.
    The “Make” tool needs to know how to build your program.It gets its knowledge of how to build your program from a file called the “makefile”. This makefile lists each of the non-source files and how to compute it from other files. When you write a program, you should write a makefile for it, so that it is possible to use “Make” to build and install the program.Simple stuff! If you didn’t understand it, go back and read the paragraph again because it’s important for the next part.
Why do we need “Make”?
    The reason we need “Make” is because it enables the end user to build and install your package without knowing the details of how it’s done. Every project comes with its own rules and nuances, and it can get quite painful every time you have a new collaborator. That’s the reason we have this makefile.The details of the build process are actually recorded in the makefile that you supply. “Make” figures out automatically which files it needs to update, based on which source files have changed.It also automatically determines the proper order for updating the files, in case one non-source file depends on another non-source file.
    Recompiling the entire program every time we change a small part of the system would be inefficient.Hence, if you change a few source files and then run “Make”, it doesn’t recompile the whole thing. It updates only those non-source files that depend directly or indirectly on the source files that you changed.Pretty neat!“Make” is not limited to any particular language. For each non-source file in the program, the makefile specifies the shell commands to compute it. These shell commands can run a compiler to produce an object file, the linker to produce an executable, ar to update a library, Makeinfo to format documentation, etc.“Make” is not limited to just building a package either. You can also use “Make” to control installing or uninstalling a package, generate tags tables for it, or anything else you want to do often enough to make it worth while writing down how to do it.
CMake
    CMake stands for Cross-platform Make. CMake recognizes which compilers to use for a given kind of source.In case you didn’t know, you can’t use the same compiler to build all the different kinds of sources. You can do this manually every time you want to build your project, but it would be tedious and painful. CMake invokes the right sequence of commands for each type of target. Therefore, there is no explicit specification of commands like $(CC).
    For coding junkies who really want the gory details, read on. If you are not into all that, you can skip to the next section. All the usual compiler/linker flags dealing with the inclusion of header files, libraries, etc are replaced by platform independent and build system independent commands.Debugging flags are included by either setting the variable CMAKE_BUILD_TYPE to “Debug”, or by passing it to CMake when invoking the program:cmake -DCMAKE_BUILD_TYPE:STRING=Debug.
    CMake also offers the platform independent inclusion of the ‘-fPIC’ flag (via the POSITION_INDEPENDENT_CODE property) and many others. Still, more obscure settings can be implemented by hand in CMake just as well as in a Makefile (by using COMPILE_FLAGS and similar properties). Of course CMake really starts to shine when third party libraries (like OpenGL) are included in a portable manner.
What is the difference?
    The build process has one step if you use a Makefile, namely typing “make” at the command line.For CMake, there are two steps: First, you need to setup your build environment (either by typing cmake <source_dir> in your build directory or by running some GUI client).This creates a makefile or something equivalent, depending on the build system of your choice (e.g. Make on *nix, VC++ or MinGW on Windows, etc). The build system can be passed to CMake as a parameter. However, CMake makes reasonable default choices depending on your system configuration. Second, you perform the actual build in the selected build system.
    We are going to jump into the GNU build system territory here.If you are not familiar with that, this paragraph might look like jibber-jabber to you. Alright, now that I have given the statutory warning, let’s move on!We can compare CMake with Autotools. When we do that, we can see the shortcomings of Make, and they form the reason for the creation of Autotools. We can also see the obvious advantages of CMake over Make. Autoconf solves an important problem i.e. reliable discovery of system-specific build and runtime information. But this is only a small part in the development of portable software. To this end, the GNU project has developed a suite of integrated utilities to finish the job Autoconf started: the GNU build system, whose most important components are Autoconf, Automake, and Libtool.
    “Make” can’t do that, at least not without modifying it anyway!You can make it do all that stuff but it would take a lot of time maintaining it across platforms. CMake solves the same problem, but at the same time, it has a few advantages over the GNU Build System:

  • The language used to write CMakeLists.txt files is readable and easier to understand.
  • It doesn’t only rely on “Make” to build the project.
  • It supports multiple generators like Xcode, Eclipse, Visual Studio, etc.

    When comparing CMake with Make, there are several advantages of using Cmake:

  • Cross platform discovery of system libraries.
  • Easier to compile your files into a shared library in a platform agnostic way, and in general easier to use than make.
  • Automatic discovery and configuration of the toolchain.

    CMake does more than just “make”, so it can be more complex. In the long run, it’s better to learn how to use it. If you have just a small project on only one platform, then maybe “Make” can do a better job.

  • C

    C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

    85 引用 • 165 回帖 • 2 关注
  • Make
    4 引用
  • 翻译
    58 引用 • 84 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1063 引用 • 3454 回帖 • 189 关注
  • 七牛云

    七牛云是国内领先的企业级公有云服务商,致力于打造以数据为核心的场景化 PaaS 服务。围绕富媒体场景,七牛先后推出了对象存储,融合 CDN 加速,数据通用处理,内容反垃圾服务,以及直播云服务等。

    27 引用 • 225 回帖 • 163 关注
  • IDEA

    IDEA 全称 IntelliJ IDEA,是一款 Java 语言开发的集成环境,在业界被公认为最好的 Java 开发工具之一。IDEA 是 JetBrains 公司的产品,这家公司总部位于捷克共和国的首都布拉格,开发人员以严谨著称的东欧程序员为主。

    181 引用 • 400 回帖
  • Shell

    Shell 脚本与 Windows/Dos 下的批处理相似,也就是用各类命令预先放入到一个文件中,方便一次性执行的一个程序文件,主要是方便管理员进行设置或者管理用的。但是它比 Windows 下的批处理更强大,比用其他编程程序编辑的程序效率更高,因为它使用了 Linux/Unix 下的命令。

    123 引用 • 74 回帖 • 2 关注
  • MySQL

    MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是最流行的关系型数据库管理系统之一。

    692 引用 • 535 回帖
  • C

    C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

    85 引用 • 165 回帖 • 2 关注
  • Bootstrap

    Bootstrap 是 Twitter 推出的一个用于前端开发的开源工具包。它由 Twitter 的设计师 Mark Otto 和 Jacob Thornton 合作开发,是一个 CSS / HTML 框架。

    18 引用 • 33 回帖 • 667 关注
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    23014 引用 • 92572 回帖
  • WebComponents

    Web Components 是 W3C 定义的标准,它给了前端开发者扩展浏览器标签的能力,可以方便地定制可复用组件,更好的进行模块化开发,解放了前端开发者的生产力。

    1 引用 • 4 关注
  • Telegram

    Telegram 是一个非盈利性、基于云端的即时消息服务。它提供了支持各大操作系统平台的开源的客户端,也提供了很多强大的 APIs 给开发者创建自己的客户端和机器人。

    5 引用 • 35 回帖
  • Ruby

    Ruby 是一种开源的面向对象程序设计的服务器端脚本语言,在 20 世纪 90 年代中期由日本的松本行弘(まつもとゆきひろ/Yukihiro Matsumoto)设计并开发。在 Ruby 社区,松本也被称为马茨(Matz)。

    7 引用 • 31 回帖 • 216 关注
  • Facebook

    Facebook 是一个联系朋友的社交工具。大家可以通过它和朋友、同事、同学以及周围的人保持互动交流,分享无限上传的图片,发布链接和视频,更可以增进对朋友的了解。

    4 引用 • 15 回帖 • 440 关注
  • Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的操作系统上。容器完全使用沙箱机制,几乎没有性能开销,可以很容易地在机器和数据中心中运行。

    492 引用 • 926 回帖
  • MongoDB

    MongoDB(来自于英文单词“Humongous”,中文含义为“庞大”)是一个基于分布式文件存储的数据库,由 C++ 语言编写。旨在为应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似 JSON 的 BSON 格式,因此可以存储比较复杂的数据类型。

    90 引用 • 59 回帖 • 1 关注
  • webpack

    webpack 是一个用于前端开发的模块加载器和打包工具,它能把各种资源,例如 JS、CSS(less/sass)、图片等都作为模块来使用和处理。

    41 引用 • 130 回帖 • 253 关注
  • jQuery

    jQuery 是一套跨浏览器的 JavaScript 库,强化 HTML 与 JavaScript 之间的操作。由 John Resig 在 2006 年 1 月的 BarCamp NYC 上释出第一个版本。全球约有 28% 的网站使用 jQuery,是非常受欢迎的 JavaScript 库。

    63 引用 • 134 回帖 • 724 关注
  • JSON

    JSON (JavaScript Object Notation)是一种轻量级的数据交换格式。易于人类阅读和编写。同时也易于机器解析和生成。

    52 引用 • 190 回帖 • 1 关注
  • Vue.js

    Vue.js(读音 /vju ː/,类似于 view)是一个构建数据驱动的 Web 界面库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

    265 引用 • 666 回帖 • 1 关注
  • 尊园地产

    昆明尊园房地产经纪有限公司,即:Kunming Zunyuan Property Agency Company Limited(简称“尊园地产”)于 2007 年 6 月开始筹备,2007 年 8 月 18 日正式成立,注册资本 200 万元,公司性质为股份经纪有限公司,主营业务为:代租、代售、代办产权过户、办理银行按揭、担保、抵押、评估等。

    1 引用 • 22 回帖 • 772 关注
  • JetBrains

    JetBrains 是一家捷克的软件开发公司,该公司位于捷克的布拉格,并在俄国的圣彼得堡及美国麻州波士顿都设有办公室,该公司最为人所熟知的产品是 Java 编程语言开发撰写时所用的集成开发环境:IntelliJ IDEA

    18 引用 • 54 回帖
  • Love2D

    Love2D 是一个开源的, 跨平台的 2D 游戏引擎。使用纯 Lua 脚本来进行游戏开发。目前支持的平台有 Windows, Mac OS X, Linux, Android 和 iOS。

    14 引用 • 53 回帖 • 538 关注
  • Solidity

    Solidity 是一种智能合约高级语言,运行在 [以太坊] 虚拟机(EVM)之上。它的语法接近于 JavaScript,是一种面向对象的语言。

    3 引用 • 18 回帖 • 401 关注
  • DevOps

    DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

    51 引用 • 25 回帖
  • 反馈

    Communication channel for makers and users.

    123 引用 • 913 回帖 • 250 关注
  • PostgreSQL

    PostgreSQL 是一款功能强大的企业级数据库系统,在 BSD 开源许可证下发布。

    22 引用 • 22 回帖
  • 大数据

    大数据(big data)是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。

    93 引用 • 113 回帖
  • 房星科技

    房星网,我们不和没有钱的程序员谈理想,我们要让程序员又有理想又有钱。我们有雄厚的房地产行业线下资源,遍布昆明全城的 100 家门店、四千地产经纪人是我们坚实的后盾。

    6 引用 • 141 回帖 • 584 关注