C/C++从零开始的cmake教程

C/C++从零开始的CMake教程

如果你有过在linux系统上源码安装某款软件的经历,那么肯定对这三部曲一点都不会陌生——配置(configure)、编译(make)、安装(make install)。几乎每次都是机器人般的操作,这背后其实是make(准确地说应该是GNU Make)在默默为你干了不少活。

1.编译hello.c——单一源文件的编译

//hello.c
#include <stdio.h>
int main(){
 puts("hello, world!");
 return 0;
}

为了编译生成对应的可执行文件,你可能会使用下面的命令:

$ cc -o hello hello.c
$ ./hello
hello, world!

但是,如果使用make(前提是你的操作系统已经安装了GCC和GNU Make),会显得更清爽一些。

$ make hello
cc hello.c -o hello
$ ./hello
hello, world!

1.1编写Makefile

什么?你连“make hello”都懒得写?看完这部分,你的“妄念”应该就能实现了,到时候你只需要慢悠悠地打出4个字母——”make”,然后按下回车键,比图形界面IDE还要方便(至少你不用到处去找那个该死的“运行”按钮在哪。

这时候你只要在hello.c的同一个目录下新建一个文件Makefile作为make命令的配置文件即可。它的内容很简单:

hello:

1.2设定编译器

什么?你不想使用默认的cc,而想使用gcc来编译程序?那还不简单,只用在Makefile文件中把CC变量的值赋为gcc就可以了。

CC := gcc
hello:

如果你这时候想运行make试下效果,请注意:make根本就不会重新编译生成hello。为什么啊?因为make很“懒”,因为它检测到hello.c和上一次编译时一模一样,再重新编译生成的可执行文件肯定也一样啊,那就没有运行的必要了,直接返回结果了。这时候可以用上些“小手段”,反正make很好骗。输入下面的命令,更新下hello.c的最近修改日期。

$ touch hello.c

或者干脆直接把hello文件删掉。但是删文件的方式也有高招和低招之分,如果你使用的是下面的命令:

$ rm -f hello

那么这就是低招了,因为这很可能误删了其他很重要的源文件,造成十分严重的后果。那么高招是什么呢?那就是在Makefile中添加下面的内容:

clean:
 $(RM) hello

运行方式也很简单,运行make clean命令即可。

1.3增加编译选项

如果你想为gcc增加-g -Wall -Wextra选项,那么只要设定变量CFLAGS的值即可。

CC := gcc
CFLAGS := -g -Wall -Wextra
hello:
clean:
 $(RM) hello

这时候,运行make clean和make的结果如下所示:

$ make clean
rm -f hello
$ make
gcc -g -Wall -Wextra hello.c -o hello

2.分块编译——编译有多个源文件的程序

如果程序不再只有一个源文件,那么结合Make的内置编译规则,也可以很简洁地编写Makefile文件完成编译任务。下面是一个简单的例子:

LDLIBS := -lncurses
block: block.o function.o
block.o function.o: function.h
clean:
 $(RM) *.o
 $(RM) block

其中程序需要用到ncurses,它是一个字符终端下屏幕控制的基本库,因此在编译时需要在最后增加-lncurses选项。这时候,可能你已经发现了,其实编写Makefile主要内容就是编写依赖关系,block: block.o function.o就是表示由block.o和function.o链接生成可执行文件block。同时bolck.o和function.o就是根据需要从bolck.c和function.c编译生成,因为make有如下内置规则:*.o由同名的c源文件生成,因此不必写多余的bolck.o:bolck.cfunction.o:function.c 。运行结果如下

$ make
cc -c -o block.o block.c
cc -c -o function.o function.c
cc block.o function.o -lncurses -o block

3.Make的内置规则

输入make -p命令,可以查看所有的make的内置规则,比如上面提到的*.o由同名的c源文件生成,在make -p的输出结果中显示如下:

%.o: %.c
# recipe to execute (内置):
 $(COMPILE.c) $(OUTPUT_OPTION) $<

其中,%为通配符,$(COMPILE.c)是取COMPILE.c这个变量的值,如果你好奇这个值到底是什么,可以再继续查找,发现下面的语句

# 默认
COMPILE.C = $(COMPILE.cc)

在进一步找,得到:

# 默认
COMPILE.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c

上面的变量可以像之前的实例那样重新赋值(默认为空),从而自定义编译方式。

自动变量

除了像$(COMPILE.c)和$(COMPILE.cc)这样形式的变量,make中还存在一类很常用、无比重要的变量——自动变量。
下面列出最常用的自动变量:

  • $@ 规则的生成目标
  • $% 档案文件成员结构中的文件名元素
  • $< 第一个依赖文件名
  • $^ 所有的依赖文件名(已经消重),以空格分隔
  • $+ 所有的依赖文件名(未经消重),以空格分隔
  • $* 所有除掉后缀的依赖文件名,以空格分隔,仅适用于模式规则。注:文件名包含stem和suffix,去掉suffix就剩下了stem。比如hello.cpp的stem是hello,suffix就是cpp。
  • $? 比目标文件新的依赖文件。

比如下面这条规则:

 %: %.c
# commands to execute (built-in):
 $(LINK.c) $^ $(LOADLIBES) $(LDLIBS) -o $@

LINK.c的定义如下:

LINK.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH)

CC的定义如下:

CC = cc

而且CFLAGS、CPPFLAGS、LDFLAGS、TARGET_ARCH默认都为空。
最后原来的规则等同于:

%: %.c
 cc $^ -o $@

所以本文开头的编译hello,只需简简单单的Makefile:

hello:

就可得到最终的编译命令:

cc hello.c -o hello

所以,参考make -p命令输出的make内置规则,编写自己程序的Makefile是个不错的编程习惯和学习如何熟练使用Make的途径。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。如果你想了解更多相关内容请查看下面相关链接

(0)

相关推荐

  • Makefile/cmake/node-gyp中区分判断不同平台的方法

    最近用QTK开发一个下载(下载到开发板)工具,同时用到了Makefile/cmake和node-gyp,而且都要针对不同平台做不同的处理.这里做个记录,以备以后有需要时查阅. Makefile 在Makefile中,可以用OS变量判断当前系统是否是Windows,然后用uname来判断当前系统是MacOS还是其它系统. ifeq ($(OS),Windows_NT) PLATFORM="Windows" else ifeq ($(shell uname),Darwin) PLATFOR

  • cmake 学习笔记

    最近接触到一些工程上的代码,都是用cmake来编译的,每次看着CMakeLists.txt 就各种懵逼,决定从0 开始学习 1 set set(var hello) message(${var}) 输出 hello 其实并不是单单输出hello,还有很多其他信息,会生成很多文件 files 2 CMAKE_C(XX)_FLAGS 变量 CMAKE_C_FLAGS 存放的内容会被传给 C 编译器,作用在所有的编译组态上.如果希望只针对特定一种组态有效,可以设定 CMAKE_C_FLAGS_<编译组

  • Android Studio中通过CMake使用NDK并编译自定义库和添加预编译库

    Note:这篇文章是基于Android Studio 3.01版本的,NDK是R16. step1:创建一个包含C++的项目 其他默认就可以了. C++ Standard 指定编译库的环境,其中Toolchain Default使用的是默认的CMake环境:C++ 11也就是C++环境.两种环境都可以编库,至于区别,后续会跟进,当前博文使用的是CMake环境. Exceptions Support 如果选中复选框,则表示当前项目支持C++异常处理,如果支持,在项目Module级别的build.g

  • Python实现生成简单的Makefile文件代码示例

    在linux下写几个测试程序,还要一行行的输入g++命令进行编译,当经常改测试代码的时候,那一次次的敲(或者一次次的上线箭头选)也感觉不爽,不如make来的快.用Makefile的好处就不用多说了,这里我写了个脚本,其功能是自动搜索当前目录(不包括子目录)下的".c"文件生成Makefile文件. 代码在这里,功能有限(适用于单个文件是一个独立的测试代码的情况),需要的朋友可以稍作修改以满足需求. 复制代码 代码如下: #! /usr/bin/python '''  File     

  • Linux里Makefile是什么?它是如何工作的?

    用这个方便的工具来更有效的运行和编译你的程序 makefile是用于自动编译和链接的,一个工程有很多文件组成,每一个文件的改变都会导致工程的重新链接-----但是不是所有的文件都需要重新编译,makefile能够纪录文件的信息,决定在链接的时候需要重新编译哪些文件! 当你需要在一些源文件改变后运行或更新一个任务时,通常会用到 make 工具.make 工具需要读取一个 Makefile(或 makefile)文件,在该文件中定义了一系列需要执行的任务.你可以使用 make 来将源代码编译为可执行

  • 关于MariaDB安装问题小记(CMake Error at)

    今日在安装MariaDB的时候始终提示如下错误,但是我已经安装了libaio-devel库: CMake Error at cmake/build_configurations/mysql_release.cmake:128 (MESSAGE): aio is required on Linux, you need to install the required library: Debian/Ubuntu: apt-get install libaio-dev RedHat/Fedora/Or

  • 基于make命令与makefile文件详解

    一.多个源文件带来的问题 在编写c/c++测试程序时,我们习惯每次修改一处代码,然后就马上编译运行来查看运行的结果.这种编译方式对于小程序来说是没有多大问题的,可对于大型程序来说,由于包含了大量的源文件,如果每次改动一个地方都需要编译所有的源文件,这个简单的直接编译所有源文件方式对程序员来说简直是噩耗. 我们看一个例子: // main.c #include "a.h" // 2.c #include "a.h" #include "b.h" /

  • Linux makefile 和shell文件相互调用实例详解

    shell 文件内调用makefile文件: #!/bin/bash cd ctemplate-2.1 ./configure sudo make -f install cd ../ cd TemplateProcesser make 说明:./configure文件是shell脚本文件,即shell内调用shell文件是很容易的:TemplateProcesser目录内有Makefile文件,调用方式,直接:make makefile文件内调用shell脚本文件: SHELL := /bin/

  • C/C++从零开始的cmake教程

    C/C++从零开始的CMake教程 如果你有过在linux系统上源码安装某款软件的经历,那么肯定对这三部曲一点都不会陌生--配置(configure).编译(make).安装(make install).几乎每次都是机器人般的操作,这背后其实是make(准确地说应该是GNU Make)在默默为你干了不少活. 1.编译hello.c--单一源文件的编译 //hello.c #include <stdio.h> int main(){ puts("hello, world!")

  • Nginx中Location从零开始的配置教程

    基础知识 location的匹配顺序是"先匹配正则,在匹配普通". location的匹配顺序其实是"先匹配普通,在匹配正则".造成误解的原因是:正则匹配会覆盖普通匹配 Nginx location 配置语法 1. location [ = | ~ | ~* | ^~ ] uri { ... } 2. location @name { ... } location 配置可以有两种配置方法 1.前缀 + uri(字符串/正则表达式) 2.@ + name 前缀含义 =

  • Python调用C++,通过Pybind11制作Python接口

    我是在ubuntu系统进行实验的,所以和window可能会有区别. python调用C/C++有不少的方法,如boost.python, swig, ctypes, pybind11等,这些方法有繁有简,而pybind11的优点是对C++ 11支持很好,API比较简单,现在我们就简单记下Pybind11的入门操作. 1. pybind11简介与环境安装 pybind11是一个轻量级的只包含头文件的库,它主要是用来在已有的 C++代码的基础上做扩展,它的语法和目标非常像Boost.Python,但

  • linux下使用cmake编译安装mysql的详细教程

    一.安装cmake 1.解压cmake压缩包 [root@mysql tools]# tar -zvxf cmake-2.8.8.tar.gz [root@mysql tools]# ls cmake-2.8.8 cmake-2.8.8.tar.gz mysql-5.5.16.tar.gz scripts 2.解析 [root@mysql tools]# cd cmake-2.8.8 [root@mysql cmake-2.8.8]# ./configure ------------------

  • win10下VSCode+CMake+Clang+GCC环境搭建教程图解

    打算用C/C++把基本的数据结构与算法实现一遍, 为考研做准备, 因为只是想实现算法和数据结构, 就不太想用VisualStudio, 感觉VSCode不错, 遂在网上找了一些教程, 结合自己的需求, 配置一下开发环境. 安装软件 CMake CMake是一个跨平台的自动化建构系统,它使用一个名为 CMakeLists.txt 的文件来描述构建过程; 官网下载安装, 傻瓜式操作; 记得把安装目录下的bin文件添加到系统环境变量, 这个可以在安装的时候勾选, 勾选了就不用自己添加了; 检测是否安装

  • 从零开始安装VMwareTools的详细步骤(图文教程)

    VMware Tools是VMware虚拟机中自带的一种工具,相当于VirtualBox中的增强功能(Sun VirtualBox Guest Additions),是VMware提供的增强虚拟显卡和硬盘性能.以及同步虚拟机与主机时钟的驱动程序.它的功效不仅仅如此,我们可以通过它进行虚拟机和物理机之间的文件传输的,前提是我们要先安装它.那到底怎么安装VMware Tools呢? 一.准备工具 1.VMware Workstation Pro 2.rhel-server-6.3-x86_64-dv

  • Windows配置VSCode+CMake+Ninja+Boost.Test的C++开发环境(教程详解)

    平时习惯了在Linux环境写C++,有时候切换到Windows想继续在同一个项目上工作,重新配置环境总是很麻烦.虽然Windows下用Visual Studio写C++只需要双击个图标,但我还是想折腾一下VS Code的环境配置.原因主要有两点:一是个人习惯上各种语言都在VS Code里面写,利用Git同步代码可以很方便地在不同平台开发同一个项目:二是有些情形下无法使用图形化界面,比如为Git配置CI(持续性集成)时显然不能用Visual Studio这个图形化的IDE来执行Windows环境的

  • centos 7 vscode cmake 编译c++工程的教程详解

    一.环境说明 1)gcc/g++  cmake安装建议 gcc/g++内核自带的即可,如果需要新的自行安装, cmake也一样,如有需要新的版本自行安装. 2)vscode安装插件 必要的插件c/c++ 0.28.1 cmake 0.0.17 cmake tools 1.4  (这几个插件的版本可能会不同,以扩展搜索到的最新的为准) 二.创建项目实验 1)打开项目文件夹 第一步:打开vscode,点击左上角文件,在下拉菜单选择打开文件夹!注意,是打开文件夹,不是工作区,也不是其它的!! 第二步:

  • 从零开始用DataGrip的安装及使用教程

    mysql的安装 官网下载mysql-8.0.19-winx64 这里随便下载一个版本就行了(群里下也行) 解压后加入环境变量 在path(环境变量里面)加上mysql路径(/bin). 例如,我的安装路径是C:\Users\skywf\mysql-8.0.19-winx64,那么我就要像下图一样配置环境变量 第三步:进入命令指示符(cmd)管理员权限, 输入mysqld --initialize-insecure --user=mysql, 我这里先配置无密码的,后面再加密码(因为懒得记那个随

  • Spring MVC温故而知新系列教程之从零开始

    Spring MVC简介 Spring MVC是一款基于MVC架构模式的轻量级Web框架,目的是将Web开发模块化,对整体架构进行解耦. Spring MVC有一下优点: 作为Spring框架的一部分,拥有Spring的优点(IOC,AOP等) 支持灵活的URL到页面控制器的映射 提供灵活的数据验证.格式化.数据绑定机制 支持RESTful风格 Spring MVC请求流程 Spring MVC框架的整体请求流程如下: 上图中涉及到Spring MVC的几个功能组件: 前端控制器(Dispatc

随机推荐