OpenWrt SDK 编写交叉编译Makefile的简单方法

如果你在浏览github的时候发现一个很好的Linux c语言程序,在桌面平台编译一下发现很好用,这时你想把它移植到OpenWrt平台上放到路由器上使用,那么要是能把它编译成ipk文件直接安装到路由器上就好了。下面就以redsocks2这款软件为例来介绍使用Ubuntu交叉编译redsocks2 ipk安装包的Makefile写法

选择Redsocks2作为例子的原因是redsocks这个程序只需运行一行make就可以开始执行编译,没有复杂的编译时配置,并且编译完成之后会生成一个名为redsocks2的可执行文件,把这个文件拷贝出来到磁盘的其他地方都可以运行。也就是说,redsocks2是一个编译起来非常容易的程序。编译完成只需获得一个可执行文件就可以开始用了。

下面先在Ubuntu16.04系统上观察它的编译过程

首先我们从github上克隆redsocks2的源码

git clone https://github.com/semigodking/redsocks.git

克隆结束之后安装一个依赖库libevent2,不然编译的时候会报错“fatal error: event2/event.h: 没有那个文件或目录”

sudo apt-get install libevent-dev

然后观察一下现在的redsocks2目录

OpenWrt SDK 编写交叉编译Makefile的简单方法_第1张图片

然后执行make,gcc就开始编译了,编译完成后再观察这个目录,就会发现多出一个redsocks2的可执行文件,我们就可以把这个可执行文件拷贝出来然后运行使用了

OpenWrt SDK 编写交叉编译Makefile的简单方法_第2张图片

在Ubuntu上很简单的就编译完成了redsocks2,那么在OpenWrt的SDK上如何编译成ipk呢

首先先下载OpenWrt的SDK,这里也WNDR4300路由器为例

下载完毕之后使用

tar xjf OpenWrt-SDK-ar71xx-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2.tar.bz2
解压这个tar包,之后进入SDK的主目录,在package目录下新建一个名为redsocks2的目录,然后开始新建一个Makefile文件,内容如下

include $(TOPDIR)/rules.mk


PKG_NAME:=redsocks2
PKG_VERSION:=0.66
PKG_RELEASE:=1

PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/semigodking/redsocks.git
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_SOURCE_VERSION:=bc2706a331c04a76df428748da97a7d4b5fa1754
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
PKG_MAINTAINER:=semigodking  
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)/$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION)

include $(INCLUDE_DIR)/package.mk

define Package/redsocks2
	SECTION:=net
	CATEGORY:=Network
	TITLE:=Redirect any TCP connection to a SOCKS or HTTPS proxy server
	URL:=https://github.com/semigodking/redsocks
	DEPENDS:=+libevent2 +libopenssl
endef

define Package/redsocks2/description
This is a modified version of original redsocks. \
The name is changed to be REDSOCKS2 since this release to distinguish with original redsocks. \
This variant is useful for anti-GFW (Great Fire Wall).
endef

define Package/redsocks2/conffiles
/etc/config/redsocks2
endef

define Package/redsocks2/install
	$(INSTALL_DIR) $(1)/usr/bin
	$(INSTALL_BIN) $(PKG_BUILD_DIR)/redsocks2 $(1)/usr/bin
	$(INSTALL_DIR) $(1)/etc/redsocks2
	$(INSTALL_DATA) ./files/redsocks2.template $(1)/etc/redsocks2/config.template
endef

$(eval $(call BuildPackage,redsocks2))

下面简单的解释一下

第一行 include $(TOPDIR)/rules.mk 是固定写法,不论是luci还是可执行文件的Makefile,第一行都是它

PKG_NAME:=redsocks2
PKG_VERSION:=0.66
PKG_RELEASE:=1

这三行代表你打包出的ipk的软件名,版本,PKG_RELEASE是发布号,一般是1,2,3等。其中PKG_NAME用于给其他的软件包安装时检查依赖用,PKG_VERSION在升级ipk的时候有用,比如你要用一个旧版ipk替换新版ipk,默认是不可以的,而新版替换旧版就没什么问题

PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/semigodking/redsocks.git
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_SOURCE_VERSION:=bc2706a331c04a76df428748da97a7d4b5fa1754
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz

上面这几行标识出源代码应该从哪里下载,

PKG_SOURCE_PROTO指出是git还是svn,

PKG_SOURCE_URL指出git仓库下载的地址。

PKG_SOURCE_SUBDIR指出git应该将源代码克隆到什么位置。

PKG_SOURCE_VERSION指出应该克隆哪个版本,由commit号决定,有了它你就可以直接编译最新版的ipk安装包或者编译旧版本的安装包,非常实用

PKG_SOURCE 这个我也不是很清楚是做什么的


PKG_MAINTAINER:=semigodking 
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)/$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION)

PKG_MAINTAINER 后面写作者的邮箱,比较随意,不影响编译

PKG_BUILD_DIR代表编译目录,也就是在哪里编译源码,目录内容和我上面Ubuntu截图的那个目录是一样的,这里写错了会无法编译,报错找不到目录。同理编译完成后生成的可执行文件也要到这个目录里面去找


include $(INCLUDE_DIR)/package.mk 这一行是固定写法

define Package/redsocks2
    SECTION:=net
    CATEGORY:=Network
    TITLE:=Redirect any TCP connection to a SOCKS or HTTPS proxy server
    URL:=https://github.com/semigodking/redsocks
    DEPENDS:=+libevent2 +libopenssl
endef

上面这些是定义应该编译什么ipk包,可以写好几个define,由于这个的redsocks2之编译openssl一个版本所以就写了一个,如果想要编译polarSSL版本需要再写一个define

上面的redsocks2就是显示在make menuconfig中的包名

SECTION指的是在make menuconfig中该ipk包应该被放在哪个父目录下

TITLE是make menuconfig中的标题说明

URL指的是URL说明

DEPENDS这一行比较关键,这个规定了编译时的依赖库,同时也表明出安装时的依赖库,如果这里依赖库填写少了,比如缺少+libevent2这个库,那么编译时就会报出缺少event.o这个文件,编译就会失败,同时如果在向openwrt安装redsocks的ipk时,如果没有安装libevent2.ipk,那么redsocks2的ipk也不会安装成功,提示缺少依赖库libevnet2。

注:如果在安装过程中,实现使用了opkg update并联网安装redsocks2的ipk,openwrt会自动联网其所需要的依赖库。使用ImageBuilder打包固件时也会如此。


define Package/redsocks2/description
This is a modified version of original redsocks. \
The name is changed to be REDSOCKS2 since this release to distinguish with original redsocks. \
This variant is useful for anti-GFW (Great Fire Wall).
endef

这一段指出了在make menuconfig时候显示的软件描述信息,不影响编译


define Package/redsocks2/conffiles
/etc/config/redsocks2
endef

指出了该软件包的配置文件位置,作用不大,不影响编译


define Package/redsocks2/install
    $(INSTALL_DIR) $(1)/usr/bin
    $(INSTALL_BIN) $(PKG_BUILD_DIR)/redsocks2 $(1)/usr/bin
    $(INSTALL_DIR) $(1)/etc/redsocks2
    $(INSTALL_DATA) ./files/redsocks2.template $(1)/etc/redsocks2/config.template
endef

这一段非常重要,它详细的列出了梅雨个编译后生成的文件的安装位置,比如上一段前两行标识将编译路下的redsocks2文件安装到/uer/bin目录下

后两行表示将files(提前放在package/redsocks目录下)目录下的redsocks2.template文件(该文件为你自己写的随便一个文件)安装到/etc/redsocks2目录下并改名为config.template

同时,原版redsocks目录下的文件也可以在这里规定安装到哪去,比如下面两句

$(INSTALL_DIR) $(1)/etc/
$(INSTALL_DATA) $(PKG_BUILD_DIR)/redsocks.conf.example $(1)/etc/redsocks2.conf.example

就是把编译目录下的redsocks.conf.example文件(该文件是github上原作者自己制作的文件,和上面那个不一样)安装到/etc/目录下


最后一行$(eval $(call BuildPackage,redsocks2))是固定写法

有了这个Makefile文件之后,我们就不需要把github上的源码克隆到本地,因为SDK在执行Makefile文件的时候会自动帮我们去完成这写操作。需要我们做的就是将该Makefile放到/package/redsocks2目录下,然后在SDK目录执行make menuconfig,选择redsocks2为M模式,然后执行

OpenWrt SDK 编写交叉编译Makefile的简单方法_第3张图片

OpenWrt SDK 编写交叉编译Makefile的简单方法_第4张图片

make package/redsocks2/compile V=99

就可以在SDK目录/bin/ar71xx下面获得一个ipk包了


这里有一个我写好的现成可以直接用的目前最新版redsocks2 ipk编译文件,有需要的可以直接用SDK编译:https://github.com/AlexZhuo/openwrt-redsocks2


除了使用Makefile打包ipk之外,也可以用SDK直接交叉编译出OpenWrt所使用的程序,方法略麻烦,是redsocks2作者提供的方法。这个需要根据CPU的不同设置不同的环境变量,找来找去也听麻烦的,比如ar71xx可以用如下方法配置环境变量然后编译

export PATH=$PATH:/home/alex/Downloads/OpenWrt-SDK-15.05.1-ar71xx-nand_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/
export STAGING_DIR=/home/alex/Downloads/OpenWrt-SDK-15.05.1-ar71xx-nand_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/
export CFLAGS="-I/home/alex/Downloads/OpenWrt-SDK-15.05.1-ar71xx-nand_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/target-mips_34kc_uClibc-0.9.33.2/usr/include/ -L/home/alex/Downloads/OpenWrt-SDK-15.05.1-ar71xx-nand_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/target-mips_34kc_uClibc-0.9.33.2/usr/lib/"

make CC=mipsel-openwrt-linux-gcc LD=mipsel-openwrt-linux-ld


同理,如果想要编译ramips CPU的话只需要修改上面环境变量的目录即可


export PATH=$PATH:/home/alex/OP_SDK/OpenWrt-SDK-15.05.1-ramips-rt305x_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/bin/
export STAGING_DIR=/store/build/openwrt/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/
export CFLAGS="-I/home/alex/OP_SDK/OpenWrt-SDK-15.05.1-ramips-rt305x_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/usr/include/ -L/home/alex/OP_SDK/OpenWrt-SDK-15.05.1-ramips-rt305x_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/usr/lib/"

make CC=mipsel-openwrt-linux-uclibc-gcc LD=mipsel-openwrt-linux-uclibc-ld

使用这种方法我们只能编译出一个redsocks2的可执行文件,可以通过scp上传到路由器上使用,但是没有了ipk的安装过程,系统也就不认为你安装了一个名字叫redsocks2的组件,如果由其他依赖包依赖redsocks2的话,还是会报错。所以ipk安装的方式更好一些

你可能感兴趣的:(OpenWrt SDK 编写交叉编译Makefile的简单方法)