概述
#########################################################################
#
# U-boot build supports producing a object files to the separate external
# directory. Two use cases are supported:
#
# 1) Add O= to the make command line
# 'make O=/tmp/build all'
#
# 2) Set environement variable BUILD_DIR to point to the desired location
# 'export BUILD_DIR=/tmp/build'
# 'make'
#
# The second approach can also be used with a MAKEALL script
# 'export BUILD_DIR=/tmp/build'
# './MAKEALL'
#
# Command line 'O=' setting overrides BUILD_DIR environent variable.
#
# When none of the above methods is used the local build is performed and
# the object files are placed in the source directory.
#
ifdef O
ifeq ("$(origin O)", "command line")
BUILD_DIR := $(O)
endif
endif
ifneq ($(BUILD_DIR),)
saved-output := $(BUILD_DIR)
# Attempt to create a output directory.
$(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR})
# Verify if it was successful.
BUILD_DIR := $(shell cd $(BUILD_DIR) && /bin/pwd)
$(if $(BUILD_DIR),,$(error output directory "$(saved-output)" does not exist))
endif # ifneq ($(BUILD_DIR),)
OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
SRCTREE := $(CURDIR)
TOPDIR := $(SRCTREE)
LNDIR := $(OBJTREE)
export TOPDIR SRCTREE OBJTREE
MKCONFIG := $(SRCTREE)/mkconfig
export MKCONFIG
ifneq ($(OBJTREE),$(SRCTREE))
REMOTE_BUILD := 1
export REMOTE_BUILD
endif
# $(obj) and (src) are defined in config.mk but here in main Makefile
# we also need them before config.mk is included which is the case for
# some targets like unconfig, clean, clobber, distclean, etc.
ifneq ($(OBJTREE),$(SRCTREE))
obj := $(OBJTREE)/
src := $(SRCTREE)/
else
obj :=
src :=
endif
export obj src
# Make sure CDPATH settings don't interfere
unexport CDPATH
#########################################################################
注释详解:
# U-boot 的编译过程可以支持向一个自己定义的路径生成最终的目标文件
# 这里提供了两种用法:
#第一种用法:通过在终端执行命令make O=/dir(即你指定的生成的目标文件的存放目录)
'make O=/tmp/build all'
#第二种用法:通过设置环境变量来指定目标文件存放目录,如下所示:
# 'export BUILD_DIR=/tmp/build'
# 'make'
#第二种方法也可以写成一个MAKEALL脚本,然后执行MAKEALL,如下所示:
# 'export BUILD_DIR=/tmp/build'
# './MAKEALL'
#命令行'O='设置会覆盖环境变量BUILD_DIR的设置
#如果都不采用上面两种方法,那么目标文件最终要存放到源码顶层目录,也就是U-BOOT顶层目录
代码详解:
#方法1
ifdef O
ifeq ("$(origin O)", "command line")
BUILD_DIR := $(O)
endif
endif
这句话表示如果在编译命令里面加入参数 O (如make O=/dir)就把O后面的制定的值复制给变量BUILD_DIR
( BUILD_DIR表示uboot的编译路径)
$(origin VARIABLE)
函数功能:函数“origin”查询参数“VARIABLE” (一个变量名)的出处。
函数说明: “VARIABLE”是一个变量名而不是一个变量的引用。因此通常它不包含“$”(当然,计算的变量名例外)。
返回值:返回“VARIABLE”的定义方式。用字符串表示。
“undefined”--------如果<variable>从来没有定义过, origin 函数返回这个值“undefined”。
“default”------------如果<variable>是一个默认的定义,比如“CC”这个变量。
“environment”----如果<variable>是一个环境变量,并且当 Makefile 被执行时,“-e”参数没有被打开。
“file”-----------------如果<variable>这个变量被定义在 Makefile 中。
“command line”--如果<variable>这个变量是被命令行定义的。
“override”----------如果<variable>是被 override 指示符重新定义的。
“automatic”--------如果<variable>是一个命令运行中的自动化变量。
#方法2
ifneq ($(BUILD_DIR),)
saved-output := $(BUILD_DIR)
如果变量BUILD_DIR不为空,即环境变量BUILD_DIR 被定义过,那么把它的值赋给saved-output
# Attempt to create a output directory.
$(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR})
[ -d ${BUILD_DIR}] 表示这个build_dir是不是存在 ,如果没有就创建。
[ ] 就是个条件判断语句,条件表达式,简易版if -d directory意思 用于判断目录是否存在
如果[ -d ${BUILD_DIR}] 是一个目录,则条件成立,否则不成立。
||(或)语法格式如下:
command1 || command2 || command3 …
1.命令之间使用 ||
连接,实现逻辑或的功能。
2.只有在 ||
左边的命令返回假(命令返回值 $? == 1),||
右边的命令才会被执行。这和C语言中的逻辑或语法功能相同,即实现短路逻辑或操作。
3.只要有一个命令返回真(命令返回值 $? == 0),后面的命令就不会被执行。
# Verify if it was successful.
BUILD_DIR := $(shell cd $(BUILD_DIR) && /bin/pwd)
$(if $(BUILD_DIR),,$(error output directory "$(saved-output)" does not exist))
endif # ifneq ($(BUILD_DIR),)
shell中命令的意思是先进入这个目录,再调用pwd显示当前路径,在将这个路径值赋给BUILD_DIR
这里用了一个if函数,意思是如果如果$(BUILD_DIR) 非空,则什么都不执行(返回空),否则执行error output directory "$(saved-output)" does not exist函数,输出错误信息
if函数:(《跟我一起学makefile》49页-if函数)
$(if <condition>,<then-part>)
或者
$(if <condition>,<then-part>,<else-part>)
可见, if 函数可以包含“else”部分,或是不含。即 if 函数的参数可以是两个,也可以是三个。
<condition>参数是 if 的表达式,如果其返回的为非空字符串,那么这个表达式就相当于返回真,
于是, <then-part>会被计算,否则<else-part>会被计算。
OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR)) //输出目录
SRCTREE := $(CURDIR) //源码目录
TOPDIR := $(SRCTREE) //顶层目录
LNDIR := $(OBJTREE) //连接目录
export TOPDIR SRCTREE OBJTREE
$(CURDIR) 代表当前路径。
# ifneq ($(BUILD_DIR),) #意思是:如果没有定义目标文件存放目录
#Makefile中定义了源码以及生成目标文件存放的目录,目标文件存放目录BUILD_DIR可以通过make O=dir指定。如果没有指定,则设定为源码顶层目录。
#一般编译的时候不指定输出目录,则BUILD_DIR为空。其他目录变量如下:
OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR)) #如果$(BUILD_DIR)不为空,则返回$(BUILD_DIR),并赋给OBJTREE,即自己定制的目标存放目录
SRCTREE := $(CURDIR) #把当前源码所在目录 $(CURDIR) 赋给SRCTREE
TOPDIR := $(SRCTREE) #把当前源码所在目录 $(CURDIR) 赋给TOPDIR
LNDIR := $(OBJTREE) #存放生成的目录文件
如果编译时没有定义编译路径,即没有定义$(BUILD_DIR),所有的变量都是CURDIR,即当前目录,也就是uboot的顶层目录。
注:OBJTREE 就是编译出来的*.o文件夹所存放的目录的根目录,默认情况下 为当前目录,在O=xxx下,为我们设置的目录。
OBJTREE、SRCTREE
(1)OBJTREE:编译出的.o文件存放的目录的根目录。
在默认编译下,OBJTREE等于当前目录;
在O=xx编译下,OBJTREE就等于我们设置的那个输出目录。
(2)SRCTREE: 源码目录,其实就是源代码的根目录,也就是当前目录。
总结:在默认编译下,OBJTREE和SRCTREE相等;在O=xx这种编译下OBJTREE和SRCTREE不相等。Makefile中定义这两个变量,其实就是为了记录编译后的.o文件往哪里放,就是为了实现O=xx的这种编译方式的。
MKCONFIG := $(SRCTREE)/mkconfig
export MKCONFIG
ifneq ($(OBJTREE),$(SRCTREE))
REMOTE_BUILD := 1
export REMOTE_BUILD
endif
如果源码目录于输出目录不相等,则置位REMOTE_BUILD变量。
在执行编译UBOOT之前需要先执行配置文件make *_config
参考:https://blog.csdn.net/qq_30106701/article/details/96879224
smdk2410_config : unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
等同于:./mkconfig smdk2410 arm arm920t smdk2410 NULL s3c24x0
# $(obj) and (src) are defined in config.mk but here in main Makefile
# we also need them before config.mk is included which is the case for
# some targets like unconfig, clean, clobber, distclean, etc.
ifneq ($(OBJTREE),$(SRCTREE))
obj := $(OBJTREE)/
src := $(SRCTREE)/
else
obj :=
src :=
endif
export obj src
# Make sure CDPATH settings don't interfere
unexport CDPATH
如果源码目录和输出目录不相等,则obj和src都被赋予相应的值,否则都为空
最后
以上就是激动乌龟为你收集整理的makefile 原地编译和单独输出文件夹编译的全部内容,希望文章能够帮你解决makefile 原地编译和单独输出文件夹编译所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复