Makefile 文件不容许多余的空格,开头不能是空格
1,makefile文件中命令行的行首不能用空格,而要用Tab键。
2,makefile文件中的字符格式有要求,必须是英文字符,不能有中文字符。
Makefile中$@,$^,$<
$@——目标文件;
$^——所有依赖文件;
$<——第一个依赖文件。
例如:下面是一个Makefile:
main:main.o mytool1.o mytool2.o
gcc -o main main.o mytool1.o mytool2.o
gcc -o $@ $^
main.o:main.c mytool1.h mytool2.h
gcc -c main.c
gcc -c $<
mytool1.o:mytool1.c mytool1.h
gcc -c mytool1.c
gcc -c $<
mytool2.o:mytool2.c mytool2.h
gcc -c mytool2.c
通过$@,$^,$<可以简化为:
main:main.o mytool1.o mytool2.o
gcc -o $@ $^
main.o:main.c mytool1.h mytool2.h
gcc -c $<
mytool1.o:mytool1.c mytool1.h
gcc -c $<
mytool2.o:mytool2.c mytool2.h
gcc -c $<
---------------------
下面这个例子表示了,把所有的[.c]文件都编译成[.o]文件.
%.o : %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
SRC = ydetect.c threadpool.c message.c scaner.c cJSON.c glob.c mylinux.c mymemc.c base64.c mySnmp.c myZlog.c mymap.c
OBJ = $(SRC:.c=.o)
SRC 变量代表的一系列 %.c文件, $(SRC:.c=.o) 等于 $(SRC:%.c=%.o) ,相当于把 SRC 变量中 .c文件换成.o文件
OBJ就等于换成.o后的一系列文件。
%.o:%.c
$(CC) -c $(INCLUDE) $(LIBRARY) $(CPFLAGS) $<
%.o:%.c 的意思是 通配.o文件依赖同名的.c文件
${MODS:%=%.beam} 是Makefile 变量替换的一种方式.
其格式是 $(var:%.c=%.o)或${var:.c=.o},其意思是把.c 为结尾的变量替换成.o
%则代表任意匹配之外的字符串.
实例:
source: main.c onvif.c
object: $(var:%.c=%.o)
这个时候 %分别等于 main 与 onvif
而 object 则等于 main.o 与 onvif.o
在楼主的例子中${MODS:%=%.beam}
第一个%没有带任何过滤条件.%则表示任意字符串.
第二个%表示在字符串后面添加一个 .beam
${MODS:%=%.beam} 的意思是把为变量添加一个 .beam 后缀
1. ${MODS:%=%.beam} 是Makefile 变量替换的一种方式.
其格式是 $(var:%.c=%.o)或${var:.c=.o},其意思是把.c 为结尾的变量替换成.o
2. %则代表任意匹配之外的字符串.
实例:
1 2 |
|
这个时候 %分别等于 main 与 onvif
而 object 则等于 main.o 与 onvif.o
注意:
在楼主的例子中${MODS:%=%.beam}
第一个%没有带任何过滤条件.%则表示任意字符串.
第二个%表示在字符串后面添加一个 .beam
${MODS:%=%.beam} 的意思是把为变量添加一个 .beam 后缀
makefile——小例子:
《Erlang程序设计》第六章中的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
hello.erl
-module(hello).
-export([start/
0
]).
start() ->
io:format(
"Hello world ~n"
).
shop.erl
-module(shop).
-export([cost/
1
]).
cost(oranges) ->
5
;
cost(newspaper) ->
8
;
cost(apples) ->
2
;
cost(pears) ->
9
;
cost(milk) ->
7
.
makefile
.SUFFIXES: .erl .beam
.erl.beam:
erlc -W $<
ERL = erl -boot start_clean
MODS = hello shop
all: compile
compile: ${MODS:%=%.beam}
@echo
"make clean - clean up"
clean:
rm -rf *.beam erl_crash.dump
编译成功,会出现hello.beam和shop.beam。
通过makefile将当前目录下的所有.c文件编译成.o文件
CC = gcc
CFLAGS = -Wall -O –g
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
已经从高手那得到了比较好的Makefile文件,就分享给大家吧
SRC = ${wildcard *.c}
OBJ = ${patsubst %.c, %.o, $(SRC)}
CFLAGS = -g -Wall
all : $(OBJ) move
$(OBJ):%.o : %.c
$(CC) $(CFLAGS) -c $^ -o $@
move :
mv $(OBJ) ../OBJS
clean:
$(RM) $(OBJ) .*.sw?
.PHONY:all clean
例子 [1] :(一个相对复杂的例子,嵌入式编程中经常用到的,详细情况请参考 嵌入式linux应用开发完全手册)
01 src := $(shell ls *.c) /*把当前目录下所有c源代码赋给变量src*/
02 objs := $(patsubst %.c,%.o,$(src)) /*调用makefile 中的函数patsubst, 用.o文件代替.c文件*/
03
04 test: $(objs)
05 gcc -o $@ $^
06
07 %.o:%.c
08 gcc -c -o $@ $<
09
10 clean:
11 rm -f test *.o
上述Makefile中的“$@", "$^", "$<" 称为自动变量。
Makefile中wildcard的介绍
在Makefile规则中,通配符会被自动展开。但在变量的定义和函数引用时,通配符将失效。这种情况下如果需要通配符有效,就需要使用函数“wildcard”,它的用法是:$(wildcard PATTERN...) 。在Makefile中,它被展开为已经存在的、使用空格分开的、匹配此模式的所有文件列表。如果不存在任何符合此模式的文件,函数会忽略模式字符并返回空。需要注意的是:这种情况下规则中通配符的展开和上一小节匹配通配符的区别。
一般我们可以使用“$(wildcard *.c)”来获取工作目录下的所有的.c文件列表。复杂一些用法;可以使用“$(patsubst %.c,%.o,$(wildcard *.c))”,首先使用“wildcard”函数获取工作目录下的.c文件列表;之后将列表中所有文件名的后缀.c替换为.o。这样我们就可以得到在当前目录可生成的.o文件列表。因此在一个目录下可以使用如下内容的Makefile来将工作目录下的所有的.c文件进行编译并最后连接成为一个可执行文件:
#sample Makefile
objects := $(patsubst %.c,%.o,$(wildcard *.c))
foo : $(objects)
cc -o foo $(objects)
这里我们使用了make的隐含规则来编译.c的源文件。对变量的赋值也用到了一个特殊的符号(:=)。
1、wildcard : 扩展通配符
2、notdir : 去除路径
3、patsubst :替换通配符
例子:
建立一个测试目录,在测试目录下建立一个名为sub的子目录
$ mkdir test
$ cd test
$ mkdir sub
在test下,建立a.c和b.c2个文件,在sub目录下,建立sa.c和sb.c2 个文件
建立一个简单的Makefile
src=$(wildcard *.c ./sub/*.c)
dir=$(notdir $(src))
obj=$(patsubst %.c,%.o,$(dir) )
all:
@echo $(src)
@echo $(dir)
@echo $(obj)
@echo "end"
执行结果分析:
第一行输出:
a.c b.c ./sub/sa.c ./sub/sb.c
wildcard把 指定目录 ./ 和 ./sub/ 下的所有后缀是c的文件全部展开。
第二行输出:
a.c b.c sa.c sb.c
notdir把展开的文件去除掉路径信息
第三行输出:
a.o b.o sa.o sb.o
在$(patsubst %.c,%.o,$(dir) )中,patsubst把$(dir)中的变量符合后缀是.c的全部替换成.o,
任何输出。
或者可以使用
obj=$(dir:%.c=%.o)
效果也是一样的。
这里用到makefile里的替换引用规则,即用您指定的变量替换另一个变量。
它的标准格式是
$(var:a=b) 或 ${var:a=b}
它的含义是把变量var中的每一个值结尾用b替换掉a
规则
target ... : prerequisites ...
command
...
...
目标:依赖
执行指令 ...
target也就是一个目标文件,可以是Object File,也可以是执行文件。还可以是一个标签(Label)。
① prerequisites就是,要生成那个target所需要的文件或是目标。
② command也就是make需要执行的命令。(任意的Shell命令)
gcc -o hello hello.c -I /home/hello/include -L /home/hello/lib -lworld
上面这句表示在编译hello.c时:
(大写I小写i的I)-I /home/hello/include表示将/home/hello/include目录作为第一个寻找头文件的目录,寻找的顺序是:/home/hello/include-->/usr/include-->/usr/local/include
-L /home/hello/lib表示将/home/hello/lib目录作为第一个寻找库文件的目录,寻找的顺序是:/home/hello/lib-->/lib-->/usr/lib-->/usr/local/lib
(大写L小写l的l)-lworld表示在上面的lib的路径中寻找libworld.so动态库文件(如果gcc编译选项中加入了“-static”表示寻找libworld.a静态库文件) 如 -lpthread 寻找线程库
以下的例子,有引用静态库 ,必须把$(LDFLAGS) 代表库的变量 放在 -o $@ $(OBJ) 后面。
$(BIN): $(OBJ)
# $(CC) $(INCLUDE) $(LIBRARY) $(MATHFLAG) $(CPFLAGS) $(LDFLAGS) -o $@ $(OBJ) /home/software/curl-7.53.1/lib/libcurl.a /home/software/zlog-master/src/libzlog.a /home/software/c_map-master/lib/libMyMap.a $(BUILDLIBS)
$(CC) $(INCLUDE) $(LIBRARY) $(MATHFLAG) $(CPFLAGS) -o $@ $(OBJ) $(LDFLAGS) $(BUILDLIBS)
linux makefile点滴记录 Makefile 连接静态库注意事项
linux makefile点滴记录 Makefile 连接静态库注意事项
2014年03月04日 ⁄ 综合 ⁄ 共 1745字 ⁄ 字号 小 中 大 ⁄ 评论关闭
$? :列出当前目标所依赖的文件列表中比当前目标文件还要新的文件。
$@:当前目标的名字。
$<: 当前依赖文件的名字。
$* : 不包括后缀名的当前依赖文件的名字。
-ldl 是告诉程序,要引入动态链接库。
Makefile 连接静态库注意事项
Linux的静态库是以.a结尾的,要连接静态库有两种方法:
一种是,在编译命令最后直接加上库路径/库名称。
例如你的库在绝对目录/lib/libtest.a下面你就可以这样来编译
$(CC) $(CFLAGS) $^ -o $@ /lib/libtest.a
另外一种方法是,你可以用-L制定库德路径,用-l指定库的名称
例如库的名称为libtest.a 那么就用-ltest
CROSS_COMPILE = arm-linux-uclibc-
CC = $(CROSS_COMPILE)gcc
EXEC = armsimplescan
OBJS = simplescan.o
CFLAGS = -Wall -I/home/user/blueZ/bluez_arm/bluez-libs/include
LDFLAGS = -L/home/user/blueZ/bluez_arm/bluez-libs/lib -lbluetooth
#default:$(EXEC)
%.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
#all:$(EXEC)
$(EXEC):$(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $@ $(LDFLAGS) -static
clean:
rm -f $(EXEC) $(OBJS)
上面的Makefile中$(LDFLAGS)要放在$@的后面,不然不会起作用。
---------------------------------------------------------------------------------------------------------------------------------------------------------------
一.编译和链接选项:
第一步:预编译。
gcc -E hello.c -o hello.i
-E参数:GCC在完成预处理后,停止编译过程。
预处理的宏定义展开到hello.i中。
第二步:生成目标代码。
gcc -c hello.i -o hello.o
-c参数:生成目标代码。
将hello.i编译为目标代码,也可以通过源文件直接生成。
gcc -c hello.c
第三步:链接。
gcc hello.o -o hello
将生成的目标文件链接成可执行文件。
也可以通过源文件直接生成。
gcc -o hello hello.c
二.设置警告选项:
1、-pedantic 选项:
使用扩展语法的地方将产生相应的警告信息
2、-Wall 选项:
要求GCC将产生尽可能多的警告信息
3、-Werror选项:要求GCC将所有的警告当成错误进行处理
三.库依赖选项:
1、Linux下头文件和库文件默认目录:
头文件(.h): /usr/include/目录
库文件(.so, .a): /usr/lib/目录
2、常用选项:
-I选项:向GCC的头文件搜索路径中添加新的目录。
gcc -o hello hello.c -I /home/crosstar/include
要求gcc在/home/crosstar/include/目录下寻找所需要的头文件。
-L选项:向GCC的库文件搜索路径中添加新的目录。
gcc -o test test.c -L /home/crosstar/lib –lfoo
要求gcc在/home/crosstar/lib/目录下寻找所需的库文件libfoo.so
-l选项:要求GCC链接库文件libfoo.so。
注:Linux下的库文件命名约定:
通常以lib三个字母开头。
由于所有的库文件都遵循同样的规范,因此在用-l选项指定链接的库文件名时可以省去lib三个字母,也就是说GCC在对-lfoo进行处理时,会自动去链接名为libfoo.so的文件。
-static选项:
强制使用静态链接库
gcc -o test test.c -L /home/crosstar/lib-static –lfoo
要求GCC链接时静态链接/home/crosstar/lib/目录下的libfoo.a
方法1
-static : 所有的库文件使用静态库链接
g++ -static -ltest -lfoo
注意:libtest libfoo 都将只使用静态库,如果没有提供链接无法通过
1
2
方法 2:
这里有2个命令介绍一下:
–Bdynamic : 用于在各种可能的情况下为共享动态绑定设置首选项。
-Bstatic : 将绑定只限制于静态库。
当库的静态和动态版本都可用时,使用这2个选项在命令行首选项间进行切换。
注意: 使用这2个命令需要配合 -Wl 选项
一个例子
g++ -Wl,-Bstatic -ltest -lfoo -Wl,-Bdynamic -ltest2
使用libtest.a 和 libfoo.a 静态库
使用libtest2.so 动态库
1
2
3
4
还有一个选项 -Wl,–as-needed 抛弃所有的无用的动态库