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

Posted 代二毛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Makefile的两种编译方法——原地编译和单独输出文件夹编译相关的知识,希望对你有一定的参考价值。

原地编译

编译代码时默认是原地编译,原地编译就是编译生成的.o文件和相应的.c文件是在同一目录的。原地编译比较简单,但是会污染源码,目录里会多出生成的.o文件,并且编译不同配置的目标文件,都要先清除之前的.o文件。

单独输出文件夹编译

在编译时指定输出目录,在编译的时候所有生成的.o文件或生成的其他文件全部丢到那个输出目录下去。同一份代码在编译不同配置的目标文件时,可以指定不同的输出目录,这样就可以同时有两份不同配置的目标文件,并且不会污染源代码。

两种编译方法的应用

在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。

u-boot中主Makefile关于单独输出文件夹编译的部分脚本:

ifdef O
ifeq ("$(origin O)", "command line") #判断编译是是否通过"O=xxx"指定输出目录
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) #CURDIR是Makefile内嵌的变量,其值等于当前所在目录

上面的脚本会判断编译时是否指定输出目录,OBJTREE是存放目标文件的根目录,SRCTREE是源码的根目录,如果没有指定输出目录则两个变量相等;指定了输出目录则OBJTREE和SRCTREE不相等,OBJTREE等于指定的输出目录。

以上是关于Makefile的两种编译方法——原地编译和单独输出文件夹编译的主要内容,如果未能解决你的问题,请参考以下文章

u-boot全面分析

跨平台C++开源代码的两种常用编译方式

c/c++中extern关键字详解

如何在linux下写makefile

直接调用对象方法的两种方式

Android 系统开发-提高编译速度的两种方式