makefile 原地编译和单独输出文件夹编译

#########################################################################
#
# 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都被赋予相应的值,否则都为空

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值