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.
  • Automatic discovery and configuration of the toolchain.
  • Easier to compile your files into a shared library in a platform agnostic way, and in general easier to use than make.

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.

Reprint: CMake or Make的更多相关文章

  1. 使用cmake自动构建工程

    公司引擎是用cmake根据目标平台来构建工程的,刚接触的时候深深体会到cmake的方便:如果目标平台是windows,它可以帮你自动构建出vs工程:如果是安卓,自动构建出eclipse工程,如果是IO ...

  2. CMake

    使用CMake编译跨平台静态库 http://www.tuicool.com/articles/3uu2Yj cmake命令 安装.用法简介 https://fukun.org/archives/04 ...

  3. CMake学习笔记

    C++开发者必备技能CMake  先简单介绍一下,CMake是一个跨平台的编译工具,它可以根据不用的平台,不同的编译环境,生成不同的MakeFile,从而控制编译的过程. 使用CMake的步骤: 1. ...

  4. VS 2013编译64位版本QT 4.8.6及使用cmake为依赖QT生成VS项目时Could NOT find Qt4

    对于一些已经解决的问题,本博客不再讨论.只将本人遇到的问题做简单的说明. 一.VS 2013编译64位版本QT 4.8.6 QT项目官网中,对于QT4,其只提供了windows X86的版本,并且支持 ...

  5. cmake cannot find package

    cmake 找不到package,如 find_package (OpenMesh REQUIRED) 出现错误 在项目的文件夹中找到 FindOpenMesh.cmake 文件,将其所在路径添加到 ...

  6. Cmake的交叉编译

    http://www.cmake.org/Wiki/CMake_Cross_Compiling

  7. CMake命令/函数汇总(翻译自官方手册)

    查看官方文档 cmake命令 选项 CMake变量 CMake命令汇总 / add_custom_command add_custom_target/add_definitions/add_depen ...

  8. 《CMake实践》笔记一:PROJECT/MESSAGE/ADD_EXECUTABLE

    <CMake实践>笔记一:PROJECT/MESSAGE/ADD_EXECUTABLE <CMake实践>笔记二:INSTALL/CMAKE_INSTALL_PREFIX &l ...

  9. 《CMake实践》笔记二:INSTALL/CMAKE_INSTALL_PREFIX

    <CMake实践>笔记一:PROJECT/MESSAGE/ADD_EXECUTABLE <CMake实践>笔记二:INSTALL/CMAKE_INSTALL_PREFIX &l ...

随机推荐

  1. darkflow测试和训练yolo

    转自 https://blog.csdn.net/u011961856/article/details/76582669参考自github:https://github.com/thtrieu/dar ...

  2. [MySQL] MySQL存储过程 事务transaction 数据表重建

    直接上代码 -- 删除存储过程 DROP PROCEDURE IF EXISTS `renew_message_queue`; -- 添加; 的转义 DELIMITER ;; CREATE PROCE ...

  3. Invoke 和 BeginInvoke 的真正涵义

    BeginInvoke 方法真的是新开一个线程进行异步调用吗? 参考以下代码: public delegate void treeinvoke(); private void UpdateTreeVi ...

  4. node.js执行shell命令进行服务器重启

    nodejs功能强大且多样,不只是可以实现 服务器端 与 客户端 的实时通讯,另一个功能是用来执行shell命令 1.首先,引入子进程模块var process = require('child_pr ...

  5. Java之数组类型

    如果我们有一组类型相同的变量.例如,5位同学的成绩,可以这么写 public class Main { public static void main(String[] args) { // 5位同学 ...

  6. POWER 740硬盘更换步骤

    把mirror解掉,再从rootvg里面提出来,再用diag确认下,再用命令删掉hdisk1,更换 更换前的准备 1.查看报错日志. 执行errpt列出报错条目 IDENTIFIER TIMESTAM ...

  7. 【sqlserver】【mysql】用NavicatPremium12把sqlserver的数据迁移到mysql上

    1.在NavicatPremium的mysql,选择到迁移到的表,然后右键[导入向导]

  8. Qt中 布局管理器失效问题

    1 问题描述 在Qt5.12.0 版本中,使用 自动管理器发生,无法生效 2 问题代码 Widget::Widget(QWidget *parent) : QWidget(parent), butto ...

  9. Deleaker – 内存泄漏猎人(RAD Studio 的附加组件)

    程序员面临(并希望我们意识到)的常见问题之一是内存泄漏或任何其他类型的资源泄漏.例如,Windows限制了进程一次可以分配的GDI或USER32对象的数量.当事情走错路时,您可能希望拥有一些工具来帮助 ...

  10. Vue框架(三)——Vue项目搭建和项目目录介绍、组件、路由

    Vue项目环境搭建 1) 安装node,在官网下载好,然后在本地安装 官网下载安装包,傻瓜式安装:https://nodejs.org/zh-cn/ 2) 换源安装cnpm >: npm ins ...