Linux系统中编译大型C语言项目必备技能之:Makefile文件的编写
文章目录
- Makefile的介绍
- Makefile的编写规范——简单举例
- Makefile的编写规范——复杂举例
- 项目描述
- 编译需求
- 编译思路
Makefile的介绍
我们在阅读一些大型的C语言项目时,通常会在项目文件夹中看到一个名为makefile的文件。Makefile是Linux系统中用于编译C语言项目的一种编译脚本,传统的Linux通过gcc工具在命令行输入命令来编译C语言程序,但当需要编译的c文件过多时,频繁的输入编译指令显得十分繁琐。makefile文件能够帮助我们更快速更方便的编写C语言项目。
Makefile的编写规范——简单举例
以一个简单的例子来说明,当我们需要编译一个名为test.c的c语言文件时,我们通常需要在终端输入以下指令:
gcc test.c -o test
当然,这句指令同样可以写入makefile文件中。想要使用makefile来编译以上的代码,我们需要在代码所在文件夹新建一个名为Makefile的文件(写作makefile同样可以,目前的系统对于第一个字母m是否为大小写均认可),并输入以下内容:
test: test.cgcc test.c -o test
以上是makefile最简单的一种写法,它的含义为:
第一行:第一行顶头的test表示你想要生成的可执行文件名称,后面接一个冒号,冒号后的test.c表示生成该可执行文件所需要的依赖文件。
第二行:gcc编译指令。这里需要注意的是编译指令前必须用tab隔开,如果自己的编辑器不会自动替你用tab隔开,务必加上一个tab。四个空格都不行,必须是tab。
那么以上就是一种最简单的makefile文件的写法。写好该文件后,下次的编译只需要在终端输入:
make
即可代替原本的编译指令,完成对项目的编译了。
当然以上的写法只是最简单的一种写法,接下来我们看一个复杂的项目。
Makefile的编写规范——复杂举例
项目描述
我们有以下几个文件:
main_max.c
main_min.c
max.c
min.c
util.c
command.c
max.h
min.h
util.h
command.h
其中main_max.c和main_min.c是两个包含main函数的程序,
max.c,min.c,util.c和command.c是一些函数的文件,
max.h,min.h,util.h和command.h是其对应的头文件。
编译需求
我们需要将这些c文件和h文件编译出两个可执行文件,分别为main_max和main_min,
main_max需要使用max.c,util.c和command.c中的函数,
main_min需要使用min.c,util.c和command.c中的函数,
编译时需要加上链接选项-lm及debug选项-g。
编译思路
main_max可执行文件的依赖文件,除了包含main_max.c,还包含max.o,util.o和command.o。其中.o文件指.c文件编译出的目标文件。
而max.o文件,又可以通过max.c和max.h文件编译生成,其他同理。故我们可以采用以下写法:
CC = gcc
CFLAGS = -lm -gall: main_max main_minmain_max: main_max.c max.o util.o command.o$(CC) $(CFLAGS) main_max.c max.o util.o command.o -o main_maxmain_min: main_min.c min.o util.o command.o$(CC) $(CFLAGS) main_max.c min.o util.o command.o -o main_maxmax.o: max.c$(CC) $(CFLAGS) -c max.cmin.o: min.c$(CC) $(CFLAGS) -c min.cutil.o: util.c$(CC) $(CFLAGS) -c util.ccommand.o: command.c$(CC) $(CFLAGS) -c command.cclean:rm *.o main_max main_min.PHONY: all clean
以上内容看起来有些复杂,让我们看一下它与上面简洁版的有什么不同
第一行中的 CC = gcc
表示makefile中的变量。当我们在makefile文件需要频繁输入某段内容时,如gcc,链接指令等,可以将其写成便于理解与修改的变量,在下文将要写到该内容时,用 $(变量名称) 即可表示。这样也方便对重复的内容进行修改。
最后的.PHONY: all clean
.PHONY表示一个声明,声明的含义为冒号后面的内容是一个伪目标。
伪目标是一类不需要在文件中编译出来的目标,如这里的all的作用为批量生成多个可执行文件。如果没有此处的all,makefile文件在执行完第一个命令生成main_max之后,便不再继续生成main_min。需要在第四行处用伪目标all列出所有需要编译出的可执行文件,才能够批量编译。
目标(.o)文件的编译
如max.o文件的编译,需要在其依赖文件也就是.c文件前,加上一个-c选项,意为将该C文件编译为目标文件。先编译为目标文件的好处是,如果我们使用了这种编译方法,那么我们在之后修改代码的过程中,如果修改了其中一个.c文件,其他的.c文件没有修改,那么编译时我们只会对修改的.c文件进行重新编译,而不会对其他文件重复的编译,在工程量大的时候,节省了整个编译过程的时间。
clean命令
通过这种编译方式,会生成可执行文件和大量的目标文件,有时,当我们需要将自己的源代码发布出来的话,文件夹里的目标文件和可执行文件一般都是需要删除掉的。这时就需要使用clean功能。clean命令后是一段Linux的rm指令,“*.o”表示文件夹内所有后缀为.o的文件。在makefile中加入的clean的指令后,我们在终端输入:
make clean
这段指令,即可将所有目标文件和可执行文件全部删除了。
以上就是一段结构完整的makefile文件,当然makefile文件远不止这些功能,更多的功能我们需要通过之后的学习慢慢领悟。
Linux系统中编译大型C语言项目必备技能之:Makefile文件的编写相关推荐
- Linux编译mybatis,使用mybatis assembly插件打成tar包,在linux系统中运行服务-Go语言中文社区...
使用mybatis assembly插件打成tar包,在linux系统中运行服务 assembly插件插件地址: 链接:https://pan.baidu.com/s/1i6bWPxF 密码:gad5 ...
- Linux系统中编译、链接的基石-ELF文件:扒开它的层层外衣,从字节码的粒度来探索
初次见面 大家好,我是 ELF 文件,大名叫 Executable and Linkable Format. 经常在 Linux 系统中开发的小伙伴们,对于我肯定是再熟悉不过了,特别是那些需要了解编译 ...
- Linux系统中编译、链接的基石-ELF文件:扒开它的层层外衣,从字节码的粒度来探索...
初次见面 大家好,我是 ELF 文件,大名叫 Executable and Linkable Format. 经常在 Linux 系统中开发的小伙伴们,对于我肯定是再熟悉不过了,特别是那些需要了解编译 ...
- 怎样在Linux系统中编译,Linux操作系统如何编译程序?
每个人迟早都要下载程序的源码,然后试着编译它.如果你是RedHat或Debian的忠实追随者,你最终会发现一个程序不是太老就是太新,而去找已经编译过的二进制代码.坏的一方面是这些代码可能无论你怎么做, ...
- 交叉编译工具32位在64位的Linux系统中编译
1. 问题描述 将交叉编译工具链拷贝到新的虚拟机(Ubuntu16系统)中发现出现编译工具文件不存在的报错.一开始以为是由于公司电脑加密,拷贝下来有问题,无法识别,最后和同事讨论,发现是系统和交叉编译 ...
- Linux系统中普通用户输入命令后出现“不在sudoers文件中,此事将被报告”的问题
普通用户输入一些系统命令后出现:不在sudoers文件中,此事将被报告.这是因为当前操作用户的权限不够. ---------------- 解决问题步骤如下: 1.输入命令:"su root ...
- linux遍历所有文件包含字符串,Linux系统中使用grep命令,查找包含某字符串的文件...
我们在windows查找包含包含某些文字的文件时,通过高级查找工具可以很方便的做到,一次在linux要用到这一功能时却犯了难,我们知道使用find -name 命令可以根据文件名来查找,但具体到文件里 ...
- linux比较两个文件命令cmp,Linux系统中使用cmp和comm命令来比较两个文件
cmp cmp 命令:比较任意两个类型的文件,且吧结果输出到标准输出,默认文件相同不输出,不同的文件输出差异 必要参数 -c 显示不同的信息 -l 列出所有的不同信息 -s 错误信息不提示 选择参数 ...
- linux系统中 库分为静态库和,Linux系统中“动态库”和“静态库”那点事儿-【经典好文】...
今天我们主要来说说Linux系统下基于动态库(.so)和静态(.a)的程序那些猫腻.在这之前,我们需要了解一下源代码到可执行程序之间到底发生了什么神奇而美妙的事情. 在linux操作系统中,普遍使用E ...
最新文章
- mysql int 做排序_Mysql数据库按照varchar字符串类型排序和按照int整型类型排序的区别和注意点及解决方案...
- mysql 一周一月_mysql查询当天、本周,本月,上一个月的数据
- iOS 线程操作库 PromiseKit
- 自动生成Hibernate框架结构
- NSUInteger和NSInteger和int
- 站长如何拥抱腾讯云大生态
- 13.深度学习练习:Autonomous driving - Car detection(YOLO实战)
- 基本类型--枚举类型和位标志
- python @符号_Python金三角!python初学者很难绕过的坑,附教程资料
- shell脚本一键安装jdk
- Github上优秀的开源项目
- 电驴让分享继续 服务器不稳定,电驴快快跑—分流教程
- 火狐浏览器“正在检查您的附件组件与Firefox此版本的兼容性” -- 解决方案
- 计算机上网络怎么连接,手机怎么连接电脑上网
- 关于流程图的场景提炼,这一次终于说清楚业务流程图、功能流程图、页面流程图了
- 将FTP空间通过网络映射到本地电脑上
- Mysql(3):事务、锁及锁级别
- c#将PDF文件转成图片
- JS标准时间时间格式化
- 接口技术七段数码管c语言,031 实例7-七段数码管绘制