Makefile的两种编译方法——原地编译和单独输出文件夹编译

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是根的意思,代表这是某某根目录。

猜你喜欢

转载自blog.csdn.net/weixin_42031299/article/details/120694050