Makefile的介绍与使用(二)

  Makefile的介绍与使用(一)中,我简单总结了一下关于子目录下的Makefile的一些运用,而这次的Makefile的介绍与使用(二)中,就对Makefil顶层目录进行一个剖析,简单分析一下Makefile的构造。

就拿最近做的hello目录下的Makefile为示例

include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
 
PKG_NAME:=hello
PKG_VERSION=1
PKG_RELEASE:=1.0
 
PKG_BUILD_DIR := $(KERNEL_BUILD_DIR)/$(PKG_NAME)
 
include $(INCLUDE_DIR)/package.mk
 
define Package/hello
    SECTION:=utils
    CATEGORY:=hello
    TITLE:=hello
endef
 
define Build/Prepare
    mkdir -p $(PKG_BUILD_DIR)
    $(CP) ./src/* $(PKG_BUILD_DIR)
endef
 
define Build/Compile
    $(MAKE) -C $(PKG_BUILD_DIR) 
        $(TARGET_CONFIGURE_OPTS) 
        CFLAGS="$(TARGET_CFLAGS)" 
        CPPFLAGS="$(TARGET_CPPFLAGS)" 
        LDFLAGS="$(TARGET_LDFLAGS)"
endef
 
define Package/hello/install
    $(INSTALL_DIR) $(1)/bin
    $(INSTALL_BIN) $(PKG_BUILD_DIR)/hello $(1)/bin/
endef
 
$(eval $(call BuildPackage,hello))

首先是include部分

include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
include $(INCLUDE_DIR)/package.mk

这一小段,是声明调用。例如第二行include $(INCLUDE_DIR)/kernel.mk 说明,要调用目录include下的kerne.mk文件。而第一行的意思是调用OpenWRT根目录下的reles.mk文件。

接着是自定义PKG_xxxxx变量

PKG_NAME —— 通过menuconfig和ipkg可以看到的包的名称

PKG_VERSION —— 正下载的上游版本号

PKG_RELEASE —— 此包所生成的文件的版本

PKG_BUILD_DIR —— 此包编译的地址

官方说明如下:

PKG_NAME - The name of the package, as seen via menuconfig and ipkg

PKG_VERSION - The upstream version number that we're downloading

PKG_RELEASE - The version of this package Makefile

PKG_LICENSE - The license(s) the package is available under, SPDX form.

PKG_LICENSE_FILE- file containing the license text

PKG_BUILD_DIR - Where to compile the package

PKG_SOURCE - The filename of the original sources

PKG_SOURCE_URL- Where to download the sources from (directory)

PKG_MD5SUM - A checksum to validate the download

PKG_CAT - How to decompress the sources (zcat, bzcat, unzip)

PKG_BUILD_DEPENDS - Packages that need to be built before this package, but are not required at runtime. Uses the same syntax as DEPENDS below.

PKG_INSTALL - Setting it to "1" will call the package's original "make install" with prefix set to PKG_INSTALL_DIR

PKG_INSTALL_DIR - Where "make install" copies the compiled files

PKG_FIXUP - ???

PKG_SOURCE_PROTO - the protocol to use for fetching the sources (git, svn)

PKG_REV - the svn revision to use, must be specified if proto is "svn"

PKG_SOURCE_SUBDIR - must be specified if proto is "svn" or "git", e.g. "PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)"

PKG_SOURCE_VERSION - must be specified if proto is "git", the commit hash to check out

PKG_CONFIG_DEPENDS - specifies which config options depend on this package being selected

接着分析各个define……endef

define Package/hello
    SECTION:=utils
    CATEGORY:=hello
    TITLE:=hello
endef

panckage hello应是这样——package/$(PKG_NAME)对应的是上面的PKG_NAME,即这个包的名称;其中的函数的意义为:

SECTION - 包的种类

CATEGORY - 显示在menuconfig的哪个目录下

TITLE - 简单的介绍

DESCRIPTION - (deprecated) 对包详细的介绍

URL - 源码所在的网络路径

MAINTAINER - (required for new packages) 维护者是谁(出错了联系谁)

DEPENDS - (optional) 需要依事的包,See below for the syntax.

USERID - (optional) a username:groupname pair to create at package installation time.

define Build/Prepare
    mkdir -p $(PKG_BUILD_DIR)
    $(CP) ./src/* $(PKG_BUILD_DIR)
endef

一般情况下,调用的.mk文件里都有所需要使用的宏。但是也有例外,例如这个 Build/Prepare 就是需要我们自己重新定义的宏。

在这里,我们make V=s时,make工具会在编译之前执行 Build/Prepare 宏里的命令。

这里面的要求是创建一个目录在Build_dir目录中,而后将Build_dir目录下所有的东西复制进其中的src目录里。也可以说成是编译前所要做的准备。

define Package/hello/install
    $(INSTALL_DIR) $(1)/bin
    $(INSTALL_BIN) $(PKG_BUILD_DIR)/hello $(1)/bin/
endef

这一段和上面一段是一样的,都是自定义宏。作用是声明所生成的包的安装路径在/bin目录下。即指定了包的安装过程。

define Build/Compile
    $(MAKE) -C $(PKG_BUILD_DIR) 
        $(TARGET_CONFIGURE_OPTS) 
        CFLAGS="$(TARGET_CFLAGS)" 
        CPPFLAGS="$(TARGET_CPPFLAGS)" 
        LDFLAGS="$(TARGET_LDFLAGS)"
endef

这一段Build/Compile说明这一段程序是编译包。不做多述。

最后一行代码$(eval $(call BuildPackage,hello)作用于package.mk中,使之生效。(非常重要)