电子产业一站式赋能平台

PCB联盟网

搜索
查看: 80|回复: 0
收起左侧

一些通用的Makefile文件模板

[复制链接]

864

主题

864

帖子

8156

积分

高级会员

Rank: 5Rank: 5

积分
8156
发表于 2023-11-14 08:31:00 | 显示全部楼层 |阅读模式
点击上方“C语言与CPP编程”,选择“关注/置顶/星标公众号
8 w6 H/ `" m. [* A1 h( \. j干货福利,第一时间送达!
* \0 D  h+ c1 H: v1 S' T; |6 o* y9 R+ F

gz01dij4rxx64015579530.png

gz01dij4rxx64015579530.png
+ [9 u  x8 F% h; }
最近有小伙伴说没有收到当天的文章推送,这是因为微信改了推送机制,有一部分小伙伴刷不到当天的文章,一些比较实用的知识和信息,错过了就是错过了,建议大家加个星标??,就能第一时间收到推送。: W# V8 x5 L5 B8 T, U6 W& |

vzjwxdkqels64015579630.png

vzjwxdkqels64015579630.png

7 D% a8 W3 g3 [: w写在前面对于Windows下开发,很多IDE都集成了编译器,如Visual Studio,提供了“一键编译”,编码完成后只需一个操作即可完成编译、链接、生成目标文件。
. c0 ^& K8 g- x1 ~& v8 ~Linux开发与Windows不同,Linux下一般用的的gcc/g++编译器,如果是开发ARM下的Linux程序,还需用到arm-linux-gcc/arm-linux-g++交叉编译器。
, }: `& ~- q" X6 R% w9 c( ]4 nLinux下也可以实现“一键编译”功能,此时需要一个编译脚本“Makefile”,Makefile可以手动编写,也可以借助自动化构建工具(如scons、CMake)生成。手动编写Makefile是Linux和Windows程序员的区别之一,一般地一个通用的Makefile能够适合大部分Linux项目程序。9 S& G  c* j3 Q: K, Q& n6 t% B/ ]. y
3个Makefile模板2.1 编译可执行文件MakefileVERSION  =1.00( `) e& O& Y$ ?9 l; p8 u" Y8 I! ]/ a
CC   =gcc+ ?5 j. p5 c2 |9 M8 o& t7 }) `
DEBUG   =-DUSE_DEBUG
/ f3 P( G5 g" ]( nCFLAGS  =-Wall
+ |! |4 ^# Q& D! U" l* U. }8 j3 S: YSOURCES   =$(wildcard ./source/*.c): m1 U2 g% u( b: d7 b
INCLUDES   =-I./include; n1 N. S) f+ e8 R/ h& `' ^
LIB_NAMES  =-lfun_a -lfun_so- _3 }( F9 b5 I# d+ u* p
LIB_PATH  =-L./lib1 E) h/ \7 X5 K$ U' o9 Y) S
OBJ   =$(patsubst %.c, %.o, $(SOURCES))0 B/ [7 ^5 z5 B. s3 Y- |
TARGET  =app: J1 A* B, L3 ^
#links7 g, ~  v* `5 Q# m
$(TARGET):$(OBJ)8 k% r9 ^& P; \
@mkdir -p output
$ }: b* J0 \) r9 {. y8 l4 F* p, ` $(CC) $(OBJ) $(LIB_PATH) $(LIB_NAMES) -o output/$(TARGET)$(VERSION)
1 s, H4 z' Y- a1 T; h* W6 C' g @rm -rf $(OBJ)
1 Z& d  b7 H9 n # h3 T* Y0 \0 u# Z. i
#compile
( x0 H; h1 I4 s' j) Y% _* @%.o: %.c
8 B+ }8 Q3 f. Y. p2 r $(CC) $(INCLUDES) $(DEBUG) -c $(CFLAGS) $ -o $@
! H/ M4 P6 I: t7 g* }9 e( u8 f.PHONY:clean1 P: N$ d$ l9 n# e
clean:0 l  s6 \) W3 |. @/ b% o, k' B
@echo "Remove linked and compiled files......"
# e/ o$ k, {* N' i: P$ ` rm -rf $(OBJ) $(TARGET) output % T) O& ?; \  E$ x& Y$ {/ z
【要点说明】. h3 i: [! Q& w* o4 c( i& d& E
【1】程序版本
4 \; M2 X6 v$ x0 Q! _开发调试过程可能产生多个程序版本,可以在目标文件后(前)增加版本号标识。
. _. N) o, X( w! N, H; M7 X% b( FVERSION = 1.00( O4 ~$ {) n# M, }7 S
$(CC) $(OBJ) $(LIB_PATH) $(LIB_NAMES) -o output/$(TARGET)$(VERSION)
4 v: Q( l/ K- g: M6 N9 W【2】编译器选择
/ I2 P2 a, q: y, ^; ^Linux下为gcc/g++;arm下为arm-linux-gcc;不同CPU厂商提供的定制交叉编译器名称可能不同,如Hisilicon“arm-hisiv300-linux-gcc”。2 i) F* S5 g) J
CC = gcc
& f, q6 Y0 }& G! B+ B4 v【3】宏定义7 m) n& D, Q* O+ _8 c( a7 j
开发过程,特殊代码一般增加宏条件来选择是否编译,如调试打印输出代码。-D是标识,后面接着的是“宏”。
! o, ^0 T# v* T7 [% GDEBUG =-DUSE_DEBUG5 u& Q1 s( B# N
【4】编译选项7 C: X3 T: J" T: ?: }* ^2 a) B
可以指定编译条件,如显示警告(-Wall),优化等级(-O)。- y6 l) B, q$ @! K, w
CFLAGS =-Wall -O  D2 g0 {; l: m6 Q
【5】源文件
4 o5 S1 |: {& Y; `指定源文件目的路径,利用“wildcard”获取路径下所有依赖源文件。. T1 ~( J8 g6 g2 v5 k$ T' U2 X% w  y
SOURCES =$(wildcard ./source/*.c)
$ x  \: f9 N: h" I【6】头文件
/ W0 T' h9 E: S! `) z. ]包含依赖的头文件,包括源码文件和库文件的头文件。
4 Y7 X; z, i; S" O9 G. \INCLUDES =-I./include
' m+ m9 t3 t* W【7】库文件名称/ @, {* a* P7 E0 W/ t
指定库文件名称,库文件有固定格式,静态库为libxxx.a;动态库为libxxx.so,指定库文件名称只需写“xxx”部分,
& e8 J& ?+ d8 i( T# q) tLIB_NAMES =-lfun_a -lfun_so: M' o. v, s! J8 L* H& h2 r
【8】库文件路径
1 w! [9 T8 ]( f2 j7 H& E指定依赖库文件的存放路径。注意如果引用的是动态库,动态库也许拷贝到“/lib”或者“/usr/lib”目录下,执行应用程序时,系统默认在该文件下索引动态库。2 L2 G$ D8 h' q/ O
LIB_PATH =-L./lib
: K. e1 q) ?5 a【9】目标文件  a; K, ?# U( `: n: ^) H% ^) E
调用“patsubst”将源文件(.c)编译为目标文件(.o)。- s) H/ v$ r& q2 A$ l/ Q. H
OBJ =$(patsubst %.c, %.o, $(SOURCES))
3 V  ]0 y5 Z. Q* x【10】执行文件, _" s. [8 g  n# f, G) Q0 V
执行文件名称
1 F/ ^& h) J0 i# H- cTARGET =app
/ Z, G. B/ P! K9 t4 {; N# g8 j' s; q【11】编译" H4 [( k4 D: f( ~2 P
%.o: %.c
3 r- f# T* m# S $(CC) $(INCLUDES) $(DEBUG) $(CFLAGS) $ -o $@
0 Z0 }7 L. O0 Q$ H! `3 v/ I【12】链接! Z% p' I+ x7 u/ k8 U( o
可创建一个“output”文件夹存放目标执行文件。链接完输出目标执行文件,可以删除编译产生的临时文件(.o)。
$ @; [1 _7 X" {) o' Q$(TARGET):$(OBJ)/ c  u' \$ o5 @
@mkdir -p output; F" v' k& \2 \' S# m' z+ B
$(CC) $(OBJ) $(LIB_PATH) $(LIB_NAMES) -o output/$(TARGET).$(VERSION)
' I# Y- z! B0 z2 o @rm -rf $(OBJ)- X3 g1 Q6 I4 A
【13】清除编译信息& O" ]* a# w! w& X6 L
执行“make clean”清除编译产生的临时文件。
& z* w9 @! l# x- g.PHONY:clean
1 n2 e! b7 ~/ s! V) k: {clean:" ~5 X! a5 L) }  O, s: \5 [/ Z
@echo "Remove linked and compiled files......"
# y  h9 F8 L2 w rm -rf $(OBJ) $(TARGET) output . R' K7 Q- Z8 @! q% ?/ y  D8 Q4 B
2.2 编译静态库MakefileVERSION     =: z( B9 S/ r. j" F( N1 a
CC          =gcc
# [# Q. Y" g+ A- |* T1 C8 ?9 P3 r4 DDEBUG   =+ P! Q. y6 P. F
CFLAGS  =-Wall
& U, l" d6 t8 p. t7 K5 qAR   =ar/ G5 X: F% ?& W) g
ARFLAGS     =rv
5 e$ e. P  B4 L# ?( ]! _8 sSOURCES   =$(wildcard *.c)
% b$ r  [7 m# q9 s- \" iINCLUDES    =-I.8 ^- l+ v* W& R
LIB_NAMES   =
* F) h: l8 o9 NLIB_PATH  =
/ w$ z1 L0 _$ k% _+ M" ROBJ         =$(patsubst %.c, %.o, $(SOURCES))2 h% H( `1 G' y
TARGET      =libfun_a
* t; y  E0 {* F  H* v#link- z/ {, v* `+ U# D3 N3 W
$(TARGET):$(OBJ)8 ?3 y" R) g4 }' j5 D/ }5 N- |
@mkdir -p output8 g& r0 s" B) J
$(AR) $(ARFLAGS) output/$(TARGET)$(VERSION).a $(OBJ)
7 s9 g: {+ D3 n& O" K* j @rm -rf $(OBJ)
1 L% t) h) ?" T5 E# e#compile
( O" _) c2 c  I0 T%.o: %.c
. ~) @8 @  u8 U$ g+ H3 u $(CC) $(INCLUDES) $(DEBUG) -c $(CFLAGS) $ -o $@
" G6 n8 a2 u0 }( P  ) ?% ]0 O/ I/ K
.PHONY:clean' l3 W5 t; z( z6 P
clean:
& W% k! V* \# V' C5 i! U @echo "Remove linked and compiled files......"
' {  [2 L' o2 J rm -rf $(OBJ) $(TARGET) output 7 L4 I; ]5 h: j/ J' U  C7 A
【要点说明】
- L$ \$ R, S3 k- N# O2 a1 C; t( U基本格式与“编译可执行Makefile”一致,不同点包括以下。
' L! B6 \" X/ o2 k9 `4 k" [" H0 [; A【1】使用到“ar”命令将目标文件(.o)链接成静态库文件(.a)。静态库文件固定命名格式为:libxxx.a。
% D- V- @+ F  \, y4 O; V% ]5 s2.3 编译动态库MakefileVERSION   =
2 ]! ~* _0 I' T5 V& [+ y% RCC        =gcc
: T( i% ^# _1 n9 x3 c- j5 e, rDEBUG     =! U! z( p! P2 I8 E  h( m- ?
CFLAGS    =-fPIC -shared ( X0 ]# K8 Y3 {: V" `% b
LFLAGS   =-fPIC -shared 6 r7 {9 |2 L; W. A# n; {
SOURCES   =$(wildcard *.c)8 x3 y2 i9 Q/ f
INCLUDES  =-I.
: n! `1 i* G) B9 ALIB_NAMES =
% g6 ?5 ?3 Z4 Q" E8 x( KLIB_PATH  =
8 j) g/ L" d9 o6 s' xOBJ       =$(patsubst %.c, %.o, $(SOURCES))4 A' l/ h6 Z4 |+ n9 O
TARGET    =libfun_so
. S. S* v4 Z1 _4 ]9 f6 D* n# ~# x#link3 T& P6 K6 T* t+ R$ P
$(TARGET):$(OBJ)* A% T5 ?; ]- @9 Q
@mkdir -p output! r1 M$ z2 k0 m" o- N
$(CC) $(OBJ) $(LIB_PATH) $(LIB_NAMES) $(LFLAGS) -o output/$(TARGET)$(VERSION).so
7 D  D) f' S6 o/ ]3 I @rm -rf $(OBJ)
- L2 J/ E2 |. z  B. f
1 O2 q- @4 F$ ~3 H/ r( n#compile
) S; C% L# Q, |; Q& i%.o: %.c
& r1 ]3 r& v, |1 H $(CC) $(INCLUDES) $(DEBUG) -c $(CFLAGS) $ -o $@
* h! ?$ [& ^3 m.PHONY:clean
' y% s( k+ Y4 u7 c- \: xclean:( _. t* ^- W6 U* p/ ^3 @) T
@echo "Remove linked and compiled files......"
8 A* ]& x% d) p: [ rm -rf $(OBJ) $(TARGET) output
6 r8 Q9 X( ~/ f【要点说明】
3 U9 G3 O/ J7 s) u( W基本格式与“编译可执行Makefile”一致,不同点包括以下。
. |) P+ _; {( }0 w9 B0 W【1】编译选项和链接选项增加“-fPIC -shared ”选项。动态库文件固定命名格式为libxxx.so。+ d/ V) d, I/ E" o5 A1 x8 y
Demo3.1 编译应用程序编写测试例程,文件存放目录结构如下,头文件存放在“include”目录,库文件存放在“lib”目录,源文件存放在“source”目录,Makefile在当前目录下。
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


联系客服 关注微信 下载APP 返回顶部 返回列表