Makefile详解

Makefile详解一、Makefile规则格式Makefile是由一系列的单一规则指令组合起来:目标XX1:依赖文件<TAB>命令1<TAB>命令2目标XX2:依赖文件<TAB>命令1<TAB>命令2……指令1:命令1命令2指令2:命令1命令2……示例:Tag:a….

大家好,又见面了,我是你们的朋友全栈君。

一、Makefile规则格式

Makefile是由一系列的单一规则指令组合起来:

目标XX1:依赖文件
<TAB>命令1
<TAB>命令2

目标XX2:依赖文件
<TAB>命令1
<TAB>命令2

... ...

指令1:
    命令1
    命令2
指令2:
    命令1
    命令2
... ...

示例:

Tag:a.o b.o c.o
    gcc -o Tag a.o b.o c.o
a.o: a.c
    gcc -c a.c
b.o: b.c
    gcc -c b.c
c.o: c.c

clean:
    rm .o
    rm Tag

二、Makefile变量

1、赋值符号“=”

Makefile详解     Makefile详解

实验结果显示被“=”赋值的变量,其值取决于最后一次赋值。

指令“print”中echo前加上“@”和省略其命令执行过程,结果如下:

Makefile详解       Makefile详解

2、赋值符“:=”

Makefile详解       Makefile详解

不再像“=”一样显示最后一次赋值。

3、赋值符“?=”

Makefile详解       Makefile详解

如果“name”已经被赋值则用之前的值“zhao”,否则用“li”

4、变量追加“+=”

Makefile详解      Makefile详解

在变量“name”之后追加“wang”

三:Makefile模式规则

a.o : a.c
    gcc -c a.c
b.o : b.c
    gcc -c b.c

运行模式规则“%”:当目标中重现“%”时,目标中“%”所代表的值决定了依赖文件中的“%”的值

%.o : %.c
    gcc -c $<

四、Makefile伪目标

伪目标主要是为了避免Makefile中定义的执行指令和工作目录下的实际文件出现名字冲突。

举例说明:当前目录下如果有一个名为“clean”的文件,执行make clean指令,因为没有依赖文件,所以后续的rm指令不会被执行。解决方法为在Makefiel中将指令声明为伪目标即可“.PHONY”

.PHONY

clean:
    rm *.o
    ... ...

五、Makefile函数

1、函数“subst”:完成字符串替换

$(subst <from>, <to>, <text>)

$(subst aaa, AAA, 3a transform 3A aaa)

将字符串“3a transform 3A aaa ”中的“aaa”替换为“AAA”即:“3a transform 3A AAA”

2、函数“patsubst”:完成模式字符串替换

$(patsubst <pattern>, <replacement>, <text>)

$(patsubst %.c, %.o, a.c b.c c.c)

将字符串“a.c b.c c.c”替换为“a.o b.o c.o”

如果text = a.c b.c c.c

那么,“$(text: .c = .o)”等同于“$(patsubst %.c, %.o, $(text))”

3、函数“dir”:获取目录

$(dir <name...>)

$(dir </src/a.c>)

提取文件“/src/a.c”的目录部分“/src”

4、函数“notdir”:提取目录名

$(notdir <name...>)

$(notdir <src/a.c>)

提取文件“/src/a.c”的非目录部分“a.c”

5、函数“foreach”:完成循环

6、函数“wildcard”:在非规则模式下即变量定义和函数中等同于“%”通配符,将相应对象展开

$(foreach <var>, <list>, <text>)

SRCDIRS       := dira dirb dirc 
$(foreach dir, $(SRCDIRS), $(wildcard $(dir) / *.c))

循环将SRCDIRS中的各个目录放进dir变量中,调用wildcard函数提取dir目录下所有.c文件

六、Makefile自动化变量

Makefile详解

七、Makefile示例

示例1:裸板程序

1:原始Makefile

main.bin:a.o b.o c.o
	arm-linux-gnueabihf-ld  -Txxx.lds -o main.elf a.o b.o c.o
	arm-linux-gnueabihf-objcopy -o binary -s -g main.elf main.bin
	arm-linux-gnueabihf-objdump -D main.elf > main.dis

a.o : a.c
    arm-linux-gnueabihf-gcc -c a.c -o a.o
b.o : b.c
    arm-linux-gnueabihf-gcc -c b.c -o b.o
c.o : c.s
    arm-linux-gnueabihf-gcc -c c.s -o c.o

clean:
	rm -rf *.o main.bin main.elf main.dis

2:替换为自动变量和规则模式

objs := a.o b.o c.o

main.bin:$(objs)
	arm-linux-gnueabihf-ld  -Txxx.lds  -o main.elf $^               /*(1)*/
	arm-linux-gnueabihf-objcopy -o binary -s -g main.elf $@         /*(2)*/
	arm-linux-gnueabihf-objdump -D main.elf > main.dis              

%.o : %.c
    arm-linux-gnueabihf-gcc -c $< -o $@                             /*(3)*/
%.o : %.s
    arm-linux-gnueabihf-gcc -c $< -o $@ 

clean:
	rm -rf *.o main.bin main.elf main.dis

(1)$^:a.o b.o c.o

(2)$@:main.bin

(3)$<:%.c ; $@:%.o

3:替换为变量

CROSS_COMPILE ?= arm-linux-gnueabihf-
NAME          ?= main

CC            := $(CROSS_COMPILE)gcc
LD            := $(CROSS_COMPILE)ld
OBJCOPY       := $(CROSS_COMPILE)objcopy
OBJDUMP       := $(CROSS_COMPILE)objdump

OBJS := a.o b.o c.o

$(NAME).bin = $(OBJS)
    $(LD) -Txxx.lds -o $(NAME).elf $^
    $(OBJCOPY) -o binary -s -g $(NAME).elf $@
    $(OBJDUMP) -D $(NAME).elf > $(NAME).dis

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

clean:
    rm -rf *.o $(NAME).bin $(NAME).elf $(NAME).dis

4:多文件工程

Makefile详解

CROSS_COMPILE ?= arm-linux-gnueabihf-
TARGET        ?= main

CC            := $(CROSS_COMPILE)gcc
LD            := $(CROSS_COMPILE)ld
OBJCOPY       := $(CROSS_COMPILE)objcopy
OBJDUMP       := $(CROSS_COMPILE)objdump

INCDIRS       := dira \
                 dirb \
                 dirc \

SRCDIRS       := dira dirb dirc   

INCLUDE       := $(patsubst %, -I %, $(INCDIRS))                              /*(1)*/

SFILES        := $(foreach dir, $(SRCDIRS), $(wildcard $(dir) / *.s))         
CFILES        := $(foreach dir, $(SRCDIRS), $(wildcard $(dir) / *.c))         /*(2)*/

SFILENDIR     := $(notdir $(SFILES))                                         
CFILENDIR     := $(notdir $(CFILES))                                          /*(3)*/

SOBJS         := $(patsubst %, obj/%, $(SFILENDIR:.s=.o))                     
COBJS         := $(patsubst %, obj/%, $(CFILENDIR:.c=.o))                     /*(4)*/
OBJS          := $(SOBJS) $(COBJS)                                            /*(5)*/

VPATH         := $(SRCDIRS)                                                   /*(6)*/

.PHONY: clean

$(TARGET).bin : $(OBJS)
    $(LD) -Txxx.lds -o $(TARGET).elf $^
    $(OBJCOPY) -o binary -s %(TARGET) $@
    $(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis

$(SOBJS) : obj/%.o : %.s
    $(CC) -Wall -nostdlib -c -o2 $(INCLUDE) -o $@ $<
$(COBJS) : obj/%.o : %.c
    $(CC) -Wall -nostdlib -c -o2 $(INCLUDE) -o $@ $<   

clean:
    rm -rf $(TARGET).elf $(TARGET).dis $(TARGET).bin $(COBJS) $(SOBJS)

(1):INCLUDE := -I dira -I dirb -I dirc

将字符串目录前加“-I”,Makefile语法要求头文件目录需加“-I”

(2):CFILES := dira/a.c dirb/b.c 

将SRCDIRS各个目录下的“c”文件提取出来

(3):CFILENDIR := a.c b.c

提取CFILES中的文件名,省略路径

(4):COBJS := obj/a.o obj/b.o

将原目录下各个c文件s文件编译为.o文件,并将其放置obj目录下。

(5):OBJS = obj/a.o obj/b.o obj/c.o

整合SOBJS和COBJS。

(6):指定编译时查询目录

示例2:带三方库的自动变量和规则模式(工作记录)

TOP_PATH  := $(shell pwd)
CROSS_COMPILE := $(TOP_PATH)/../../../../prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf
INCLUDE   := -I$(TOP_PATH)/../usr/include/dbus-1.0/ -I$(TOP_PATH)/../../serialport/include/ -I$(TOP_PATH)/../json/
LIBS_PATH := -L$(TOP_PATH)/../usr/lib/ -L$(TOP_PATH)/../../serialport/lib/
LIBS      := -ldbus-1 -lcserialport
CC	:= $(CROSS_COMPILE)-g++
TARGET    :=  dbus-client

SRCDIRS		:= ./ \
			   ./../json/
CFILES		:= $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.cpp))
CFILENDIR	:= $(CFILES)
COBJS		:= $(patsubst %, %, $(CFILENDIR:.cpp=.o))

.PHONY: clean

$(TARGET):$(COBJS)
	$(CC) $^ $(INCLUDE) $(LIBS_PATH) $(LIBS) -o $(TOP_PATH)/../build/$@

$(COBJS) : %.o : %.cpp
	$(CC) -c $<  $(INCLUDE)  $(LIBS_PATH) $(LIBS) -o $@

clean:
	@rm *.o	../json/*.o
	@rm $(TOP_PATH)/../build/$(TARGET)

示例3:轻量级工程范例可用来生成动态链接库so(工作记录)

CUR_DIR=.
SRC_DIR=${CUR_DIR}
INC_DIR= -I${CUR_DIR}/
LIB_DIR= -L${CUR_DIR}/ -l cid1000m -l cserialport
CROSS_COMPILE := $(CUR_DIR)/../buildroot/output/rockchip_rv1126_rv1109_ba8300_facial_gate/host/bin/arm-linux-gnueabihf
SRC = ${SRC_DIR}/demo.c

OBJ = ${SRC}

TARGET=demo
CC=$(CROSS_COMPILE)-g++

# include header
CCFLAGS += ${INC_DIR}

# lib 
CCFLAGS += ${LIB_DIR}

# so
CCFLAGS += -fPIC -shared

# pthread support
# CCFLAGS += -lpthread

${TARGET}: ${OBJ}
	${CC} ${OBJ} ${CCFLAGS} -o ${TARGET}
	@echo "Compile library done."

clean:
	@rm -f ${TARGET}
	@echo "Clean target files done."

	@echo "Clean done."

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/161651.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • (Java实现) N皇后问题[通俗易懂]

    (Java实现) N皇后问题[通俗易懂]n皇后问题是一个以国际象棋为背景的问题:在n×n的国际象棋棋盘上放置n个皇后,使得任何一个皇后都无法直接吃掉其他的皇后,即任意两个皇后都不能处于同一条横行、纵行或斜线上。蛮力法思想:解决n皇后问题的思想本质上就是蛮力法,生成所有可能的摆放情况,并判断该情况是否满足要求,我们以树结构来表示解决问题的方法。以4*4的棋盘为例,第0层的根节点为空白的棋盘,第1层为只在棋盘的第一行摆放的四种…

    2022年9月30日
    3
  • oracle11g安装图解「建议收藏」

    oracle11g安装图解「建议收藏」Oracle11g安装:**一、软件需求安装CentOS6.5的服务器一台Oracle11g安装介质:linux.x64_11gR2_database_1of2.ziplinux.x64_11gR2_database_2of2.zip命令行客户端工具xshell、crt或者putty图形界面客户端工具Xming二、系统配置检查1.内存检查SSHSecureShell的命令行窗口,执行[root@localhost~]#grepMemTotal/proc/meminfoM

    2022年9月21日
    2
  • mybatis的二级缓存_mybatis注解详解

    mybatis的二级缓存_mybatis注解详解一、创建Cache的完整过程我们从SqlSessionFactoryBuilder解析mybatis-config.xml配置文件开始:Readerreader=Resources.getResourceAsReader(“mybatis-config.xml”);S…

    2022年9月18日
    4
  • C++学习——类和对象

    C++学习——类和对象一、类和对象基本知识:1、类的访问控制有哪些?公有成员:以关键字public指明。私有成员:以关键字private指明。保护成员:以关键字protected指明。2、拷贝构造函数的作用是什么?用一个已经存在的对象初始化本类的新对象。3、友元函数和友元类的作用是什么?友元提供了不同类或对象的成员函数之间、类的成员函数与一般函数之间进行 数据共享的机制。对于一个类,可以利用关键字fri…

    2022年8月18日
    6
  • salesforce的功能_salesforce开发

    salesforce的功能_salesforce开发时刻分享,时刻感恩!124、【CustomURLButtonforCommunity】:CreatingCustomButtonCodeforPartnerCommunities&SalesforceInternal场景:需要在Community中应用URL自定义Button,并且URL不受环境影响-避免HardCode。方案1Sample:{!URL……

    2022年10月20日
    4
  • Vim详细配置_mini5配置

    Vim详细配置_mini5配置Vim配置要点一、在终端中开打.vimrc文档二、在.vimrc文档中添加配置内容1.常用设置2.自动备份3.自动补全三、保存退出四、代码高亮不显示一、在终端中开打.vimrc文档vi~/.vimrc二、在.vimrc文档中添加配置内容1.常用设置setnumber “显示行号syntaxon “语法高亮度显示setautoindent “vim使用自动对起,也就是把当前行的对起格式应用到下一行setsmartindent “依据上面的对起格式,智能的

    2022年9月29日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号