一个应用程序的形成是少不了一下几个步骤的。
1. 预处理 #检查语法错误、包含头文件、展开#if、#define等宏定义
2. 编译 #把.c文件转换为汇编文件.s
3. 汇编 #把.s汇编转换为机器码.o
4. 链接 #和库文件等组合在一起
只有经过了上面几个步骤才能形成一个可执行的应用程序
用gcc -o test test.c这个命令就可以将上面的四个步骤全部完成。加上编译指令-v可以看到详细的编译过程。
介绍一下Makefile中常用的函数。
wildcard
用法是:
$(wildcard PATTERN...)
在Makefile中,它被展开为已经存在的、使用空格分开的、匹配此模式的所有文件列表。如果不存在任何符合此模式的文件,函数会忽略模式字符并返回空。
一般我们可以使用“$(wildcard *.c)”来获取工作目录下的所有的.c文件列表。
foreach
$(foreach VAR,LIST,TEXT)
函数功能:
如果需要(存在变量或者函数的引 用) ,首先展开变量“VAR”和“LIST”的引用;
而表达式“TEXT”中的变量 引用不展开。执行时把“LIST”中使用空格分割的单词依次取出赋值给变量 “VAR” ,然后执行“TEXT”表达式。
重复直到“LIST”的最后一个单词(为 空时结束) 。
“TEXT”中的变量或者函数引用在执行时才被展开,因此如果在 “TEXT”中存在对“VAR”的引用,那么“VAR”的值在每一次展开式将会到 的不同的值。
patsubst
格式:$(patsubst <pattern>,<replacement>,<text> )
名称:模式字符串替换函数——patsubst。
功能:查找<text>中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式<pattern>,如果匹配的话,则以<replacement>替换。这里,<pattern>可以包括通配符“%”,表示任意长度的字串。如果<replacement>中也包含“%”,那么,<replacement>中的这个“%”将是<pattern>中的那个“%”所代表的字串。(可以用“”来转义,以“\%”来表示真实含义的“%”字符)
返回:函数返回被替换过后的字符串。
filter
$(filter PATTERN…,TEXT)
函数名称:过滤函数—filter。
函数功能:过滤掉字串“TEXT”中所有不符合模式“PATTERN”的单词,保留所 有符合此模式的单词。可以使用多个模式。模式中一般需要包含模式字 符“%”。存在多个模式时,模式表达式之间使用空格分割。
返回值:空格分割的“TEXT”字串中所有符合模式“PATTERN”的字串。
函数说明:“filter”函数可以用来去除一个变量中的某些字符串.
在编译的时候加上-Wp,-MD即可自动生成依赖文件。
如果需要编译子目录下的源文件则在Makefile中加上obj-y += 子目录的名称
在子目录的makef中写上obj-y += 子目录中的源文件.o
示例:
# # Makefile topdir # CROSS_COMPILE := arm-linux- #指定交叉工具链 AS := $(CROSS_COMPILE)as LD := $(CROSS_COMPILE)ld CC := $(CROSS_COMPILE)gcc CPP := $(CC) -E AR := $(CROSS_COMPILE)ar NM := $(CROSS_COMPILE)nm STRIP := $(CROSS_COMPILE)strip OBJCOPY := $(CROSS_COMPILE)objcopy OBJDUMP := $(CROSS_COMPILE)objdump export AS LD CC CPP AR NM #导出变量 用于子目录中的Makefile export STRIP OBJDUMP OBJCOPY CFLAGS := -Wall -o2 CFLAGS += -I $(shell pwd)/include LDFLAGS := -lm -lfreetype #编译选项 export CFLAGS LDFLAGS TOPDIR := $(shell pwd) export TOPDIR TARGET := show_file #生成的目标文件 obj-y += main.o #当前目录下的源文件 obj-y += sub/ #当前目录下的子目录 all: make -C ./ -f $(TOPDIR)/Makefile.build $(CC) $(LDFLAGS) -o $(TARGET) built-in.o #编译为目标文件 clean: rm -f $(shell find -name "*.o") rm -f $(TARGET) distclean: rm -f $(shell find -name "*.o") rm -f $(shell find -name "*.d") rm -f $(shell find -name "*~") rm -f $(TARGET)
# # Makefile.build # PHONY := __build __build: obj-y := subdir-y := include Makefile #包含本目录下的Makefile __subdir-y := $(patsubst %/, %, $(filter %/,$(obj-y))) subdir-y += $(__subdir-y) subdir_objs := $(foreach f,$(subdir-y),$(f)/built-in.o) cur_objs := $(filter-out %/, $(obj-y)) dep_files := $(foreach f,$(cur_objs),.$(f).d) dep_files := $(wildcard $(dep_files)) ifneq ($(dep_files),) include $(dep_files) endif PHONY += $(subdir-y) __build:$(subdir-y) built-in.o $(subdir-y) : make -C $@ -f $(TOPDIR)/Makefile.build built-in.o : $(cur_objs) $(subdir_objs) $(LD) -r -o $@ $^ %.o : %.c $(CC) $(CFLAGS) -Wp,-MD,.$@.d -c -o $@ $< .PHONY : $(PHONY)
# # Makefile subdir #
obj-y := test1.o
下面的一个是编译当前目录下所有的.c文件 不包含子目录
# # Makefile topdir # # TARGET := show_file #生成的目标文件 CROSS_COMPILE := /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi- AS := $(CROSS_COMPILE)as LD := $(CROSS_COMPILE)ld CC := $(CROSS_COMPILE)gcc CPP := $(CC) -E AR := $(CROSS_COMPILE)ar NM := $(CROSS_COMPILE)nm STRIP := $(CROSS_COMPILE)strip OBJCOPY := $(CROSS_COMPILE)objcopy OBJDUMP := $(CROSS_COMPILE)objdump export AS LD CC CPP AR NM export STRIP OBJDUMP OBJCOPY CFLAGS := -Wall -o2 CFLAGS += -I $(shell pwd)/include LDFLAGS := -lm -lfreetype export CFLAGS LDFLAGS cur_file = $(wildcard *.c) cur_objs := $(cur_file:.c=.o) all: $(cur_objs) $(CC) $(CFLAGS) -o $(TARGET) $^ clean: rm -f $(shell find -name "*.o") rm -f $(TARGET) distclean: rm -f $(shell find -name "*.o") rm -f $(shell find -name "*~") rm -f $(TARGET)
sd