Makefile

Makefile

1、编译参数

-o并非编译参数,而是gcc内部的重命名参数。真正参与编译的参数有-c -s -e等。html

gcc -o test  main.c
若不制定相似于-c -s -e这样的编译参数,直接使用-o参数,gcc会自动默认执行-c -s -e参数,并根据-o参数指定的名称生成可执行文件。

https://www.cnblogs.com/zhangpengshou/p/3587751.htmllinux

2、Makefile语法

2.一、编译规则

2.1.一、变量定义与变量操做shell

https://blog.csdn.net/naughfy/article/details/80150312tcp

obj = test.c
obj := test.c
二者之间的区别?函数

变量追加、变量替换
makefile 文件变量赋值有如下几种 
=               // 最通用的用法,用在递归展开方式较多   
:=                 //变量必须以前就定义了,用在直接展开方式较多
?=                  若是该变量没有赋值,则对该变量赋值
+=                 给变量追加赋值
@echo $(OPT)        //  变量使用 
make OPT=add        //make 传递参数

2.1.一、变量参数传递
https://blog.csdn.net/darennet/article/details/9003010学习

//宏定义参数传递,用于源代码中宏开关。
CFLAGS += -D POSGP730

-D*表示:#define *
如:-DPOSGP730等价于#define POSGP730
-Wall 表示打开全部编译告警信息
-O2表示优化级别

在makefile中能够预先使用一个未定义的变量, 这个变量能够在make执行时传递给它
好比makefile中有这么一行
include $(M)/$(COMPAT_CONFIG)
这个M能够经过make传递过来
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
其中的M就是$(PWD)
甚至能够进行更复杂的操做, 就像在Makefile中同样
make CFLAG=-DDEBUG优化

2.1.一、编译查找规则
一、入口: makefile认为"第一个目标做为入口。 重点:第一个、目标。
二、依赖性查找
三、若能找到,则执行对应的操做。(显示)
四、若找不到,makefile强大的自动推倒能力,执行隐士的相关操做。(隐士)ui

//显示
all:test1.o test2.o
    gcc -o $@ $^
test1.o:test1.c
    gcc -o test1.o test1.c
test2.o:test2.c
    gcc -o test2.o test2.c

//隐士
all:test1.o test2.o
    gcc -o $@ $^
test1.o:  //自动推倒依赖test1.c  并编译cc -c -o test1.0 test1.c
test2.o:

//隐士
all:test1.o test2.o
    gcc -o $@ $^
//自动推倒目标与依赖,并编译cc -c -o test1.0 test1.c

2.1.二、可执行文件生成规则
makefile最终编译生成的可执行程序与伪目标没有任何关系,仅仅取决于arm-linux-gcc -o 以后所定义的名称。 (通常也采用@<)使其名字与伪目标相同。.net

2.1.二、新旧比对编译
一、若是目标不存在,执行命令。(包括依赖和命令)
二、若是目标存在,依赖文件有更新(依赖文件是递归的,找依赖的依赖,若是有更新,就更新)。执行命令。
三、若是目标存在,且依赖没有更新,(递归的,包括依赖的依赖。。。),不更新,不执行命令。code

2.二、通配符

https://www.cnblogs.com/warren-wong/p/3979270.html

2.二、特殊符号

$@:目标的名字
$^:构造所需文件列表全部全部文件的名字
$<:构造所需文件列表的第一个文件的名字
$?:构造所需文件列表中更新过的文件
 
//$@:就是test1.o  $<:就是test1.c
test1.o:test1.c
   gcc -o $@ $<
   
// $^:就是test1.c head.c
test1.o:test1.c head.c
   gcc -o $@ $^

%与*通配符的关系:

 转义符的使用:

2.三、逻辑判断

https://blog.csdn.net/liuzhuchen/article/details/51776820

if then else then

ifep

2.四、经常使用函数

wildcard扩展通配符

Makefile规则中,通配符会被自动展开。但在变量的定义和函数引用时,通配符将失效。这种状况下若是须要通配符有效,就须要使用函数“wildcard”,它的用法是:$(wildcard PATTERN...) 。在Makefile中,它被展开为已经存在的、使用空格分开的、匹配此模式的全部文件列表。若是不存在任何符合此模式的文件,函数会忽略模式字符并返回空。

//使用说明
obj = $(wildcard *.c)
//变量定义与函数引用通配符失效,举例说明
//好比函数为swapfun,使用通配符的方式去引用函数
obj = %.c
$(*fun argument)

notdir去除路径
去除全部的目录信息,SRC2里的文件名列表将只有文件名,去除掉已xx.c命名的文件夹信息。

SRC = $(wildcard *.c) 
SRC2 = $(notdir wildcard)

patsubst 替换通配符
patsubst( patten substitude, 匹配替换的缩写)函数。
它须要3个参数:第一个是一个须要匹配的式样,第二个表示用什么来替换它,第三个是一个须要被处理的由空格分隔的字列。例如,处理那个通过上面定义后的变量,
OBJS = $(patsubst %.c,%.o,$(SRC2 ))
这行将处理全部在 SRC2 列个中的字(一列文件名),若是它的 结尾是 '.c' ,就用'.o' 把 '.c' 取代。

//使用举例
SOURCES = $(wildcard *.c)
FILES   = $(notdir$(SOURCES))
OBJS   = $(patsubst %.c, %.o, $(FILES) )

SRC = $(wildcard *.c)
OBJ = $(patsubst %.c,%.o,$(notdir ${SRC}))

3、Makefile例程分析

TARGET = arm-none-linux-gnueabi
CC    = $(TARGET)-gcc
AR    = $(TARGET)-ar
LD    = $(TARGET)-ld
STRIP = $(TARGET)-strip

CFLAGS  = -Wall -I../../include -I../../../include -fPIC
LDFLAGS = -L../../lib -ldrivercomm -lmodbus -lmodbustcp -lprintmanage  -L ../../lib.arm -lxmlrpcsys

ifeq (1,${release})
CFLAGS += -Os
else
CFLAGS += -g -DDEBUG_PRINTF
endif

NAME = CL_DL_JG_YJ_BMU-H1
PROGRAM_OUTPUT = $(NAME).so
PAC_OUTPUT     = $(NAME).pac
PROGRAM_OBJS   = Driver.o

TEST_OUTPUT = test
TEST_OBJS   = Test.o

all: program test

program: version.h  $(PROGRAM_OBJS)
    $(CC) -shared $(PROGRAM_OBJS) $(LDFLAGS) -o $(PROGRAM_OUTPUT)
    ../../pack/pack $(NAME)

test: version.h  $(TEST_OBJS)
    $(CC) $(TEST_OBJS) -o $(TEST_OUTPUT) $(LDFLAGS) -ldl

newversion:
    @if [ ! -f .version ]; then \
        echo 1 > .version; \
    else \
        expr 0`cat .version` + 1 > .version; \
    fi

compile.h: newversion
    @echo \#define SOFTWARE_COMPILE_TIME \"`date +%H:%M:%S`\" >> .ver
    @echo \#define SOFTWARE_COMPILE_DATE \"`date +%Y/%m/%d`\" >> .ver
    @echo \#define SOFTWARE_COMPILE_BY \"`logname`\" >> .ver
    @echo \#define SOFTWARE_COMPILE_HOST \"`hostname`\" >> .ver
    @echo \#define SOFTWARE_COMPILER  \"`$(CC) -v 2>&1 | tail -1`\" >> .ver
    @mv -f .ver $@

version.h: compile.h
    @echo \#define SOFTWARE_BUILD_VERSION   `cat .version` >> .ver
    @mv -f .ver $@

.PHONY: clean
clean:
    @rm -f *.o *.d version.h compile.h
    @rm -f $(PROGRAM_OUTPUT) $(TEST_OUTPUT) $(PAC_OUTPUT)

%.o: %.c
    $(CC) $(CFLAGS) -c -o $@ $<

以上述makefile为例,分析makefile的查找规则与执行熟悉。

Makefile经常使用参数

https://blog.csdn.net/skywalkzf/article/details/6926395

附录

makefile学习笔记: https://www.cnblogs.com/wang_yb/p/3990952.html

strip:
函数名称:去空格函数—strip。
函数功能:去掉字串开头和结尾的空字符, 若字串中间部分也包含空格,则会多个连续空字符合并为一个空字符。
示例:
STR = a b c
LOSTR = $(strip $(STR))
结果是“a b c”。

makefeil:fileter函数 foreach函数

https://www.cnblogs.com/lengbingshy/p/3936116.html

https://www.cnblogs.com/yuguangyuan/p/10929967.html

https://blog.csdn.net/zhoudengqing/article/details/41777957
https://www.cnblogs.com/GyForever1004/category/1155268.html

makefiel中使用shell的语法进行判断
在Makefile中执行shell命令,一行建立一个进程来执行。这也是为何不少Makefile中有不少行的末尾都是“; ”,以此来保证代码是一行而不是多行,这样Makefile能够在一个进程中执行

http://ju.outofmemory.cn/entry/322934

# 适用与.h与.c处于同一文件的工程

CC = gcc
CFLAGS = -Wall 
LIB = -lpthread -levent  -lssl  -ldl -lcrypto -levent_openssl
#去除编译连接的文件
CLIENT_IGNORE_SOURCE := https-server.c 
SERVER_IGNORE_SOURCE := https-client.c 

#分别获取须要连接的文件
CLIENT_LOCAL_SOURCE = $(filter-out $(CLIENT_IGNORE_SOURCE),$(wildcard *.c))
SERVER_LOCAL_SOURCE = $(filter-out $(SERVER_IGNORE_SOURCE),$(wildcard *.c))

CLIENT_LOCAL_OBJ = $(patsubst %.c,%.o,$(notdir ${CLIENT_LOCAL_SOURCE}))
SERVER_LOCAL_OBJ = $(patsubst %.c,%.o,$(notdir ${SERVER_LOCAL_SOURCE}))


all:
    @echo "Wrong build option, please run 'make client' or "make server" to build.";
    @exit 13;
    
client:${CLIENT_LOCAL_OBJ}
    $(CC) $(CLIENT_LOCAL_OBJ) -o  $@ $(LIB) 

server:${SERVER_LOCAL_OBJ}
    $(CC) $(SERVER_LOCAL_OBJ) -o  $@ $(LIB) 

%.o:%.c
    $(CC) $(CFLAGS) -c $< -o $@ 

clean:
    rm *.o client server
相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息