1、原地编译
编译代码时默认是原地编译,原地编译就是编译生成的.o文件和相应的.c文件是在同一目录的。原地编译比较简单,但是会污染源码,目录里会多出生成的.o文件,并且编译不同配置的目标文件,都要先清除之前的.o文件。
2、单独输出文件夹编译
在编译时指定输出目录,在编译的时候所有生成的.o文件或生成的其他文件全部丢到那个输出目录下去。同一份代码在编译不同配置的目标文件时,可以指定不同的输出目录,这样就可以同时有两份不同配置的目标文件,并且不会污染源代码。
3、两种编译方法的应用
在uboot和kernel都支持两种不同的编译方法,下面以u-boot为例进行讲解单独输出文件夹编译,原地编译没什么好讲的,你不做配置默认就是原地编译。
单独输出文件夹编译的使用方法:
By default the build is performed locally and the objects are saved
in the source directory. One of the two methods can be used to change
this behavior and build U-Boot to some external directory:
1. Add O= to the make command line invocations:
make O=/tmp/build distclean
make O=/tmp/build NAME_config
make O=/tmp/build all
2. Set environment variable BUILD_DIR to point to the desired location:
export BUILD_DIR=/tmp/build
make distclean
make NAME_config
make all
使用方法的说明在uboot根目录的README文件里,有两种方法去指定输出目录:第一种是通过o=输出目录,第二种是导出环境变量BUILD_DIR。
4、u-boot中主Makefile关于单独输出文件夹编译的部分脚本:
ifdef O
ifeq ("$(origin O)", "command line") #判断编译是否通过"O=xxx"指定输出目录
BUILD_DIR := $(O)
endif
endif
ifneq ($(BUILD_DIR),)
saved-output := $(BUILD_DIR)
# 判断该路径是否存在,不存则创建
$(shell [ -d ${
BUILD_DIR} ] || mkdir -p ${
BUILD_DIR})
# 将相对路径转换为绝对路径
BUILD_DIR := $(shell cd $(BUILD_DIR) && /bin/pwd)
#如果BUILD_DIR不为空则什么也不做,如果BUILD_DIR为空则输出后面的打印信息
$(if $(BUILD_DIR),,$(error output directory "$(saved-output)" does not exist))
endif # ifneq ($(BUILD_DIR),)
#如果BUILD_DIR为不为空,则OBJTREE=BUILD_DIR,否则OBJTREE=CURDIR。
#CURDIR是Makefile内嵌的变量,其值等于当前所在目录
OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
SRCTREE := $(CURDIR) #CURDIR是Makefile内嵌的变量,其值等于当前所在目录
TOPDIR := $(SRCTREE)
脚本的解析:
(1)$(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR}):该语句是 或 连接起来的两条命令,判断路径是否存在(-d ${BUILD_DIR})和创建该路径(mkdir -p ${BUILD_DIR})。如果该路径存在则不会执行后面的语句,如果不存在就创建。
(2)BUILD_DIR := $(shell cd $(BUILD_DIR) && /bin/pwd):这是通过 与 逻辑连接的两条语句,首先进入到BUILD_DIR目录,然后执行pwd目录,得到绝对路径。
(3)if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR):和C语言的?运算符是一样的逻辑,(表达式)? x : y ",表达式为真返回x;否则返回y。
5、OBJTREE、SRCTREE、TOPDIR、CURDIR
(1)OBJTREE:存放目标文件的根目录;SRCTREE:源码的根目录。如果没有指定输出目录则两个变量相等;指定了输出目录则OBJTREE和SRCTREE不相等,OBJTREE等于指定的输出目录。
(2)TOPDIR:顶层目录的路径,就是整个uboot工程所在的路径;
(3)CURDIR:当前所在目录,也就是Makefile所在的路径;
补充:一般名字中的TREE是根的意思,代表这是某某根目录。