这篇文章主要为大家展示了“OpenWRT中包的Makefile内容是什么”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“OpenWRT中包的Makefile内容是什么”这篇文章吧。
包里的 Makefile 内容如下:
include $(TOPDIR)/rules.mk PKG_NAME:=helloworld PKG_RELEASE:=1 PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) include $(INCLUDE_DIR)/package.mk define Package/helloworld SECTION:=utils CATEGORY:=Utilities TITLE:=Helloworld -- prints a snarky message endef define Package/helloworld/description It's my first package demo. endef define Build/Prepare echo "Here is Package/Prepare" mkdir -p $(PKG_BUILD_DIR) $(CP) ./src/* $(PKG_BUILD_DIR)/ endef define Package/helloworld/install echo "Here is Package/install" $(INSTALL_DIR) $(1)/bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/bin/ endef $(eval $(call BuildPackage,helloworld))
大概我们可以将简代为如下的结构:
include $(TOPDIR)/rules.mk # 这里定义一系列的 PKG_XX include $(INCLUDE_DIR)/package.mk # 定义各种 Package, Build 宏 $(eval $(call BuildPackage,包名))
下面,我们来一一拆解。
首先,include $(TOPDIR)/rules.mk,也就是将 SDK/rules.mk 文件中的内容导入进来。
TOPDIR就是SDK的路径。
在 SDK/rules.mk 文件中,定义了许多变量。
我们可以看出,在Makefile中,赋值是用 := ,而不是等号。
比如上面的 BUILD_DIR, INCLUDE_DIR 等,都在这里定义。还有:
还有关于 TARGET_CC, TARGET_CXX 等非常有用的变量定义。
还有 TAR, FIND, INSTALL_BIN, INSTALL_DIR, INSTALL_DATA等等非常重要的变量定义。
官网上指定有如下变量需要设置:
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">
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
跟上面的 include $(TOPDIR)/rules.mk 是一样的。就是把这个文件包含进来。
INCLUDE_DIR这个变量在 rules.mk 里已经定义了:
那就是 SDK/include/package.mk 文件了,打开看看。
主要有以下几个功能:
如果某个变量我们没有在上一部分里定义,那里在这个文件里,它就会被指定为默认值,比如:
上面的用 ?= 来表示给未定义的变量赋默认值。比如,如果没有指定 PKG_MD5SUM,那么就默认为 unknow。
根据上部分用户自定义的 PKG_XXXX 变量推导出更多相关的变量。
比如:
虽然我没有看过相关的手册,根据多年的从业经验也能看出上面的意思来。
#如果定义了宏,就... ifdef 宏名 ... endif #如果宏相等 ifeq (宏1,宏2) ... endif strip $宏名 #将宏对应的值去除前后的空白字符 VAR += xxxx #在变量 VAR 后面追加 xxxx
我猜大概就是这样,如果不对请指正。
再比如如下:
就这样,它为我们提供了大量有价值的变量。
在 Makefile 中,宏的定义格式是:
define XXX/xxxx <宏的实体...> endef
package.mk会把大部分需要的宏都定义好。理想情况下,用户只需要定义好了 PKG_XXX 之后,不需要再自定义宏,默认的宏就可以满足需求。
比如Build/Prepare/Default的定义:
Build/Prepare宏是在编译前进行的,是准备工作。
可以看出,它分了两种情况:
A,定义了 USE_GIT_TREE,则按git的方式定义。
B,定义了 USB_SOURCE_DIR,则按源码在本地的方案定义。
最重要的一个宏是 BuildPackage。它会在 Makefile 的最后一行被引用。它的实现也就是在 package.mk 文件里。如下为其源码:
define BuildPackage $(Build/IncludeOverlay) $(eval $(Package/Default)) #定义在package-defaults.mk文件里 $(eval $(Package/$(1))) #调用用户自定义的 Package/<包名> 宏 ifdef DESCRIPTION $$(error DESCRIPTION:= is obsolete, use Package/PKG_NAME/description) endif #检查有没有定义 Package/<包名>/description宏,如果没有定义,则以TITLE默认定义一个 ifndef Package/$(1)/description define Package/$(1)/description $(TITLE) endef endif BUILD_PACKAGES += $(1) $(STAMP_PREPARED): $$(if $(QUILT)$(DUMP),,$(call find_library_dependencies,$(DEPENDS))) #检查 TITLE, CATEGORY, SECTION, VERSION 是否定义,如果没有定义则报错 $(foreach FIELD, TITLE CATEGORY SECTION VERSION, ifeq ($($(FIELD)),) $$(error Package/$(1) is missing the $(FIELD) field) endif ) #如果有定义DUMP,那就引入Dumpinfo/Package宏的内部。 #如果没有,那么就引用 Packaget/<包名>/targets里面的每一个target,如果没有定义Packaget/<包名>/targets宏,那么将PKG_TARGETS里的每个target取出来, #如果也没有定义PKG_TARGETS,那就默认ipkg作为target。将每一个target,引用 BuildTarget/$(target)。 $(if $(DUMP), \ $(Dumpinfo/Package), \ $(foreach target, \ $(if $(Package/$(1)/targets),$(Package/$(1)/targets), \ $(if $(PKG_TARGETS),$(PKG_TARGETS), ipkg) \ ), $(BuildTarget/$(target)) \ ) \ ) $(if $(PKG_HOST_ONLY)$(DUMP),,$(call Build/DefaultTargets,$(1))) endef
总结一下语法:
$() 表示要执行的一条语句
$(if 条件, 成立执行, 失败执行) if条件分支
$(foreach 变量, 成员列表, 执行体) 成员遍历语句
可以看出,语句是可以嵌套使用的。
$(N) 表示第N个参数
我定要为我们的package定义特定的宏:
Package/<包名> #包的参数
在 Package/<包名> 宏中定义与包相关的信息。
如Package/helloworld宏:
define Package/helloworld SECTION:=utils CATEGORY:=Utilities TITLE:=Helloworld -- prints a snarky message endef
除了上面所列的 SECTION,CATEGORY,TITLE变量外,还可以定义:
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.
其它的宏可以选择性地定义,通常没必要自己重写。但有些情况,package.mk中默认的宏不能满足我们的需求。这时,我们就需要自己重定义宏。
比如,我们在为helloworld写Makefile时,我们要求在编译之前,将 SDK/package/helloworld/src/ 路径下的文件复制到 PKG_BUILD_DIR 所指定的目录下。
于是我们重新定义Build/Prepare宏:
define Build/Prepare mkdir -p $(PKG_BUILD_DIR) $(CP) ./src/* $(PKG_BUILD_DIR)/ endef
如此以来,在我们 make V=s 时,make工具会在编译之前执行 Build/Prepare 宏里的命令。
再比如,我们要指定包的安装方法:
define Package/helloworld/install $(INSTALL_DIR) $(1)/bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/bin/ endef
上面的这个宏就是指定了包的安装过程。其中 INSTALL_DIR 定义在 rules.mk 文件里。
INSTALL_DIR = install -d -m0755
INSTALL_BIN = install -m0755
$(1)为第一个参数是./configure时的--prefix参数,通常为""
展开之后就是:
define Package/helloworld/install install -d -m0755 /bin install -m0755 $(PKG_BUILD_DIR)/helloworld /bin/ endef
它的意思就一目了然了。
除了上面所列举的这两个宏外,在官网上也说明了其它可选的宏:
由该包安装的配置文件的列表,一行一个文件。
对包描述的纯文本
A set of commands to unpack and patch the sources. You may safely leave this undefined.
You can leave this undefined if the source doesn't use configure or has a normal config script, otherwise you can put your own commands here or use "$(call Build/Configure/Default,)">
How to compile the source; in most cases you should leave this undefined, because then the default is used, which calls make. If you want to pass special arguments to make, use e.g. "$(call Build/Compile/Default,FOO=bar)
How to install the compiled source. The default is to call make install. Again, to pass special arguments or targets, use $(call Build/Install/Default,install install-foo) Note that you need put all the needed make arguments here. If you just need to add something to the "install" argument, don't forget the 'install' itself.
For things needed to compile packages against it (static libs, header files), but that are of no use on the target device.
A set of commands to copy files into the ipkg which is represented by the $(1) directory. As source you can use relative paths which will install from the unpacked and compiled source, or $(PKG_INSTALL_DIR) which is where the files in the Build/Install step above end up.
The actual text of the script which is to be executed before installation. Dont forget to include the #!/bin/sh. If you need to abort installation have the script return false.
The actual text of the script which is to be executed after installation. Dont forget to include the #!/bin/sh.
The actual text of the script which is to be executed before removal. Dont forget to include the #!/bin/sh. If you need to abort removal have the script return false.
The actual text of the script which is to be executed after removal. Dont forget to include the #!/bin/sh.
之所以有些宏是以"Package/"开头,有的又以"Build/",是因为在一个Makefile里生成多个包。OpenWrt默认认为一个Makefile里定义一个包,但我们也可以根据需要将其拆分成多个。所以说,如果我们只希望编译一次,那么只要有一系列的"Build/"的宏定义就可以了。但是,我们也可以通过添加多个"Package/"宏定义,并调用 BuildPackage,来创建多个包。
在Makefile的最后一行是:
$(eval $(call BuildPackage,helloworld))
最重要的 BuildPackage定义在 package.mk 文件里。见上面 BuildPackage 宏定义。
以上是“OpenWRT中包的Makefile内容是什么”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。