ddddfang's Blog.

makefile2

字数统计: 1.5k阅读时长: 7 min
2019/01/29 Share

DEMO 1

configurate脚本,就是一段bash脚本

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
32
33
34
35
36
37
38
39
# linux系统除了提供位置参数还提供内置参数,内置参数如下: 
# $0 ----脚本名称
# $# ----传递给程序的总的参数数目  
# $? ----上一个代码或者shell程序在shell中退出的情况,如果正常退出则返回0,反之为非0值。   
# $* ----传递给程序的所有参数组成的字符串。(尽量使用$@并将其用双引号括起来)   
# $@----以"参数1" "参数2" ... 形式保存所有参数(传递给脚本/函数的所有参数)
# $n ----表示第几个参数,$1 表示第一个参数,$2 表示第二个参数 ... $0 ----表示当前程序的名称
# $$ ----本程序的(进程ID号)PID   
# $! ----上一个命令的PID

if [ "$1" = "x86" ];then
echo "copy config.x86 to config";
cp config.x86 config;
elif [ "$1" = "arm" ];then
echo "copy config.arm to config"
cp config.arm config;
else
echo "Invalid param, usage: [./configure arm ...] or [./configure x86 ...]"
exit 1
fi

#这是把多余的后面的那几个参数打印一下
if [ "$#" -gt 1 ];then

i=0
arglist=

for arg in "$@"
do
if [ $i -ne 0 ];then
arglist=$arglist" "$arg
fi
((i++))
done

echo "arglist:"$arglist

sed -i "/^PUBLIC_FLAGS.*$/ s/$/$arglist/" config
fi

config.arm文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ARCH=arm
CROSS_COMPILE := arm-none-linux-gnueabi-

#这里指定了不使用优化,这样就可以使用gdb调试了!
PUBLIC_FLAGS:=-g -O0 -Wall -L$(ROOT_DIR)/libs/arm_linux -DARM_LINUX

#这是使用优化的gcc public flags,这样声称的binary/.so比较小,但不能gdb调试
#PUBLIC_FLAGS := -O2 -L$(ROOT_DIR)/libs/arm_linux -DARM_LINUX -fno-strict-aliasing -ffunction-sections -fdata-sections

CC := $(CROSS_COMPILE)gcc
G++ := $(CROSS_COMPILE)g++
AR := $(CROSS_COMPILE)ar
LD := $(CROSS_COMPILE)ld

export CC G++ AR LD

顶层目录makefile,下面这个include如果执行出错会终止,除非前面加上一个 -

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
32
33
34
35
36
37
38
39
40
include config

ROOT_DIR = $(shell pwd)
OUT_DIR = $(shell pwd)/build

export ROOT_DIR
export OUT_DIR

#用@告诉makefile后面是一个shell命令,同时命令不回显
#make执行时从第一个伪目标开始执行,这里即all
all: clean
@if [ ! -d $(OUT_DIR) ]; then mkdir $(OUT_DIR);fi
@$(MAKE) -j4 -C udrv
@$(MAKE) -j4 -C app
@echo "***********************************************"
@echo "** Build Finished **"
@echo "***********************************************"

modules:
@if [ ! -d $(OUT_DIR) ]; then mkdir $(OUT_DIR);fi
@$(MAKE) -C kdrv
@echo "***********************************************"
@echo "** Build Modules Finished **"
@echo "***********************************************"

modules_clean:
@$(MAKE) -C kdrv clean
@echo "***********************************************"
@echo "** Clean Modules Finished **"
@echo "***********************************************"

#命令前面有个 - 表示出错也不停止
.PHONY: clean
clean:
@$(MAKE) -j4 -C udrv clean
@$(MAKE) -j4 -C app clean
-rm -rf $(OUT_DIR)
@echo "***********************************************"
@echo "** Clean Finished **"
@echo "***********************************************"

udrv目录下的makefile

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
# ?=表示如果外面传进来(此前已经被定义)就用外面的,
# 否则就用等号后面的
# :=表示等号左边的值类似一个拷贝,有人再改变它也和本次使用无关
# =表示等号左边的值类似一个全局变量
ROOT_DIR ?= $(shell pwd)/../
OUT_DIR ?= $(ROOT_DIR)/build
include $(ROOT_DIR)/config

export ROOT_DIR
export OUT_DIR

all: clean
@if [ ! -d $(OUT_DIR) ]; then mkdir $(OUT_DIR);fi
$(MAKE) -j4 -C util
$(MAKE) -j4 -C ufrontend
$(MAKE) -j4 -C udemux
$(MAKE) -j4 -C si
$(MAKE) -j4 -C avm

clean:
-rm -rf $(OUT_DIR)
$(MAKE) clean -C util
$(MAKE) clean -C ufrontend
$(MAKE) clean -C udemux
$(MAKE) clean -C si
$(MAKE) clean -C avm

avm目录下的makefile(avm下面的子目录就不再设makefile了)

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
32
33
34
35
36
37
38
39
40
41
42
43
44
# Build configurations

ROOT_DIR ?= $(shell pwd)/../../
OUT_DIR ?= $(ROOT_DIR)/build
include $(ROOT_DIR)/config

export ROOT_DIR
export OUT_DIR

######################################################
# Module library (or Module binary)

MODULE_LIBRARY = libzxdtv.so
MODULE_OBJS += $(patsubst %.c,%.o ,$(wildcard codec/audio_dec/*.c codec/video_dec/*.c input/ts_dmx/*.c input/pvr_src/*.c))
MODULE_OBJS += $(patsubst %.c,%.o ,$(wildcard output/av_sync/*.c output/audio_out/*.c output/video_out/*.c player/av_player/*.c))

######################################################
# Header files

MODULE_INCLUDE += -I./output/av_sync -I./output/audio_out -I./output/video_out -I./player/av_player
MODULE_INCLUDE += -I../udemux/include
MODULE_INCLUDE += -I./ffmpeg

######################################################
# Module flags

#如果要生成binary而不是.so,LDFLAGS空着就好了
LDFLAGS += --shared -fPIC
LIB_FLAGS += -L$(OUT_DIR) -lzxutil -lpthread
LIB_FLAGS += -L./ffmpeg/arm-linux-lib/ -lavcodec -lavformat -lavutil -lswresample
######################################################
# Common dependency process

.PHONY:all clean

%.o: %.c
$(CC) $(LDFLAGS) $(PUBLIC_FLAGS) $(MODULE_INCLUDE) -c $< -o $@

all : clean $(MODULE_OBJS)
$(CC) $(MODULE_OBJS) $(PUBLIC_FLAGS) $(LDFLAGS) $(LIB_FLAGS) -o $(OUT_DIR)/$(MODULE_LIBRARY)

clean:
-rm -f $(LIBS_DIR)/$(MODULE_LIBRARY)
-rm -f $(MODULE_OBJS)

DEMO 2

小型程序makefile典例~~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
MODULE_BIN = maxHeapTest
MODULE_OBJS += $(patsubst %.c,%.o ,$(wildcard ./*.c))
CC = gcc
OUT_DIR = .
PUBLIC_FLAGS:=-g -O0 -Wall
LDFLAGS = -lm -lz -lpthread
MODULE_INCLUDE = -I.

.PHONY:all clean

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

all : clean $(MODULE_OBJS)
$(CC) $(MODULE_OBJS) $(PUBLIC_FLAGS) $(LDFLAGS) -o $(OUT_DIR)/$(MODULE_BIN)

clean:
-rm -f $(OUT_DIR)/$(MODULE_BIN)
-rm -f $(MODULE_OBJS)

DEMO 3

嵌入式makefile demo,以下为顶级makefile

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
CROSS   =  arm-none-linux-gnueabi-
CFLAGS := -nostdinc -nostdlib -fno-builtin -Wall -O2

INCLUDE = -I$(shell pwd)/include -I$(shell pwd)/start
ROOTDIR = $(shell pwd)/

SUBDIRS = start ucos ff9a device lib app avrnet
SUBOBJS := $(foreach n, $(SUBDIRS), obj/lib$(n).a)

export CROSS INCLUDE CFLAGS ROOTDIR

#objs := start.o init.o boot.o
#模式匹配当前目录下所有.c 文件,wildcard为一个预定义的宏
C_sources_files = $(wildcard *.c)
S_sources_files = $(wildcard *.S)
#模式匹配,由当前目录下所有.c文件得到对应的.o文件
C_objs = $(patsubst %.c,%.o,$(C_sources_files))
S_objs = $(patsubst %.S,%.o,$(S_sources_files))

bootloader.bin: $(S_objs) $(C_objs) $(SUBOBJS)
#原来的那句,ld命令默认不会给你连接gcc库的
#${CROSS}ld -Tboot.lds -o bootloader.elf $^
#连接阶段加入libgcc.a库,否则除法没法用啊
${CROSS}ld -Bstatic -Tboot.lds -L /usr/local/arm-linux-gcc4.4.3/lib/gcc/arm-none-linux-gnueabi/4.4.3 \
-L /usr/local/arm-linux-gcc4.4.3/arm-none-linux-gnueabi/sys-root/usr/lib \
-o bootloader.elf $^ --start-group -lgcc -lgcc_eh -lgcov -lc --end-group
${CROSS}objcopy -O binary -S bootloader.elf $@
${CROSS}objdump -D -m arm bootloader.elf > bootloader.dis
mv *.o *.bin *.elf *.dis ./obj

%.o:%.c
${CROSS}gcc $(CFLAGS) $(INCLUDE) -c -o $@ $<

%.o:%.S
${CROSS}gcc $(CFLAGS) $(INCLUDE) -c -o $@ $<

$(SUBOBJS) : $(SUBDIRS)

.PHONY: $(SUBDIRS)
$(SUBDIRS):
make -C $@

.PHONY:clean
clean:
for dir in $(SUBDIRS); do \
make -C $$dir clean; \
done
rm -f *.elf *.o *.bin *.dis
rm -f ./obj/*.elf ./obj/*.bin ./obj/*.dis ./obj/*.o ./obj/*.a

一下为子级makefile, 生成.a静态库

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
CURDIR = $(shell pwd)

#就为了得到lib<目录名>.a,累死我了..这样TARGET便具有自适应能力了
#<目录名>是当前父目录的名字和shell pwd不一样
TARGET = $(addsuffix .a,$(subst $(ROOTDIR),lib,$(CURDIR)))

#objs := start.o init.o main.o led.o key.o adc.o Nand.o timer.o uart.o
#模式匹配当前目录下所有.c 文件,wildcard为一个预定义的宏
C_sources_files = $(wildcard *.c)
S_sources_files = $(wildcard *.S)

#模式匹配,由当前目录下所有.c文件得到对应的.o文件
C_objs = $(patsubst %.c,%.o,$(C_sources_files))
S_objs = $(patsubst %.S,%.o,$(S_sources_files))

$(TARGET):$(S_objs) $(C_objs)
${CROSS}ar -r -o $@ $^
mv *.o *.a ../obj

%.o:%.c
${CROSS}gcc $(CFLAGS) $(INCLUDE) -c -o $@ $<
%.o:%.S
${CROSS}gcc $(CFLAGS) $(INCLUDE) -c -o $@ $<

.PHONY:clean
clean:
rm -f *.elf *.o *.bin *.dis *.a

boot.lds链接脚本

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
SECTIONS
{
. = 0x33f80000;
.text :
{
./obj/start.o (.text)
./obj/init.o (.text)
*(.text)
}
. = ALIGN(4);
.rodata :
{
*(.rodata*)
}
. = ALIGN(4);
.data :
{
*(.data)
}
. = ALIGN(4);
__bss_start = .;
.bss :
{
*(.bss)
*(COMMON)
}
__bss_end = .;
}

在 .c 中可以这么使用链接脚本中的变量

1
2
3
4
5
6
7
8
void __clear_bss(void)
{
extern int __bss_start, __bss_end;
int *p = &__bss_start;

for (; p < &__bss_end; p++)
*p = 0;
}

在 .S 中可以这么使用链接脚本中的变量

1
ldr r2, =__bss_start

CATALOG
  1. 1. DEMO 1
  2. 2. DEMO 2
  3. 3. DEMO 3