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 中可以这么使用链接脚本中的变量