分享一个很通用c语言的Makefile

编写Makefile是一个苦乐交织的事情,快乐是因为从一堆需要手工逐个处理的编译过程,进步到一条命令完成,看着代码顺畅的在屏幕上滚动,编译为最终的产品,那个过程无比愉悦;而痛苦则是,写代码已经很累了,写完代码还要编写Makefile,这多出来的一点工作,很有点最后一根稻草的感觉。 最近整理手头的几个项目,把C语言类的Makefile抽象、合并了一下,形成了一个比较通用的编译脚本,这里分享一下:

#定义编译器
CC=gcc
#自己特定的编译参数,这里仅为示例,这个参数是消除mac编译openssl类程序用的
CFLAGS += -Wno-deprecated-declarations

#定义输出文件夹,outs默认等于是./outs
OUTSDIR = outs
#定义.o中间文件的路径,这个路径编译完成可以清除
TMPSDIR = objs

#源代码路径
VPATH=src

#扫描所有的c源码,这里默认src中所有文件都是相当于库文件,最终编译为.o
#搜索出来的文件包含了src路径,这里也去掉,便于后面编译到临时目录
OBJSSOURCE = $(notdir $(wildcard src/*.c))  
OBJS = $(patsubst %.c,%.o,$(OBJSSOURCE))  

#主程序名
KEYS = main
DEPS  = $(addprefix $(TMPSDIR)/,$(OBJS))  

.PHONY : all
all:$(OBJS) $(KEYS) 

#编译所有的库文件由.c至.o
#因为VPATH的存在,源文件会自动检索src目录
$(filter %.o,$(OBJS)) : %.o : %.c
    $(CC) $(CFLAGS) -c -o $(TMPSDIR)/$@ $<

#利用所有的库文件编译主程序      
$(KEYS): $(DEPS)
    $(CC) $(CFLAGS) -o $(OUTSDIR)/$(notdir $@) $(notdir $@).c $(DEPS)

#清理 
.PHONY : clean 
clean:
    -rm $(OUTSDIR)/* $(TMPSDIR)/*

这个编译脚本的主要特点是自动扫描所有的源文件,然后逐个编译,对于大多c类的项目,基本只需要定义一下主程序就可以完成编译了,其实根据同样的原理连主程序都一起扫描、编译也是可以的,只是似乎自由度太差了。 脚本简单修改可以适应各种环境,比如下面再贴一个ios使用的,ios如果非越狱的话,直接编译成可执行文件是没有意义的,这里我们假设编译成.a库文件,供xcode来调用:

#ios交叉编译器
CC=$(shell xcrun --sdk iphoneos --find clang)
_SFLAG=$(shell xcrun --sdk iphoneos --show-sdk-path)
#iphone6以后都是arm64了,所以这里不再考虑armv7,另外也不考虑模拟器运行了
#如果有需要可以根据自己的需求修改
CFLAGS += -Wno-deprecated-declarations -isysroot $(_SFLAG) -arch arm64 -mios-version-min=9.3 -fembed-bitcode

OUTSDIR = outs
TMPSDIR = objs

VPATH=src

OBJSSOURCE = $(notdir $(wildcard src/*.c))  
OBJS = $(patsubst %.c,%.o,$(OBJSSOURCE))  
DEPS  = $(addprefix $(TMPSDIR)/,$(OBJS))  

#最后生成的库
KEYS = libcallfunctions.a

.PHONY : all
all:$(OBJS) $(KEYS) 

#编译所有的库文件由.c至.o
$(filter %.o,$(OBJS)) : %.o : %.c
    $(CC) $(CFLAGS) -c -o $(TMPSDIR)/$@ $<

#将.o文件打包为库
libcallfunctions.a : $(DEPS)
    ar -r $(OUTSDIR)/libcallfunctions.a $(DEPS)

#清理 
.PHONY : clean 
clean:
    -rm $(OUTSDIR)/* $(TMPSDIR)/*

在主要的编译环节,还有下面这种常用的办法,只是自己运算得到了源文件名而没有用Make系统的自动搜索功能而已:

%.o:
    $(CC) $(CFLAGS) -c -o $(TMPSDIR)/$@ src/$(patsubst %.o,%.c,$@)

对于更复杂的编译模式,建议把每个编译环节定义成子程序来执行,可以具备更多的灵活性。另外当前这个脚本有一个bug就是每次编译实际上所有的.o文件都会完整重新编译一遍,而没有判断源文件是否更新并忽略没有更新的源文件,所以不适合大的系统。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏沈唁志

USpider~一只超级污的司机蜘蛛

之前就看到了狂放小朋友的PHP版本的污言爬虫,然后我就征求了一下小朋友的意见,就改成了Python版本的爬虫,也算是当做练手了

1192
来自专栏FreeBuf

Kali Linux下社工密码字典生成工具Cupp和Cewl教程

Cupp是一款用Python语言写成的可交互性的字典生成脚本。尤其适合社会工程学,当你收集到目标的具体信息后,你就可以通过这个工具来智能化生成关于目标的字典。当...

4126
来自专栏比原链

剥开比原看代码17:比原是如何显示交易的详细信息的?

Gitee地址:https://gitee.com/BytomBlockchain/bytom

711
来自专栏Spark生态圈

spark任务之Task失败监控

在spark程序中,task有失败重试机制(根据 spark.task.maxFailures 配置,默认是4次),当task执行失败时,并不会直接导致整个应用...

3633
来自专栏前端大白专栏

一次性比较目前前端最流行的状态管理,mobx,vuex,redux-saga使用方式用方式

3313
来自专栏高性能服务器开发

(六)关于网络编程的一些实用技巧和细节

这些年,接触了形形色色的项目,写了不少网络编程的代码,从windows到linux,跌进了不少坑,由于网络编程涉及很多细节和技巧,一直想写篇文章来总结下这方面的...

4165
来自专栏从零开始学自动化测试

python接口自动化21-规范的API接口文档示例

前言 接口文档到底长啥样?做接口测试最大的障碍在于没有接口文档,很多公司不注重接口文档的编写,导致测试小伙伴没见过接口文档。 运气好一点的测试小伙伴可能厚着脸皮...

1.2K8
来自专栏IT派

数据工程师推荐你用的几个工具

作为数据工程师或者数据分析师,经常会跟各种数据打交道,其中,获取数据这一关是无法避免的,下面,我就将自己时常工作中用到的数据连接配置模型分享出来,供大家交流。

1054
来自专栏逍遥剑客的游戏开发

基于Unity的编辑器开发(二): 进程间通信

先要做的, 是需要编辑器和Unity共享一部部分代码, 至少协议定义和解析我不想写两遍. 虽然有protobuf这样的工具库, 但是如果不是跨语言的话, 我觉得...

46416
来自专栏魏琼东

一步一步教你使用AgileEAS.NET基础类库进行应用开发-WinForm应用篇-演示使用报表构建UI-入库业务查询模块

回顾与说明     前面我们把“商品字典”、“商品入库”、“商品库存查询”三个模块已经概括或者详细的演示完了,这些模块涉及到简单数据的增、删、修,也涉及到复杂业...

2175

扫码关注云+社区