使用openwrt搭建编译环境,编译一个demo

@我真的很想重视能力提升,但是总能眼里略过问题。

基于软路由openwrt,进行自己代码的模块编译,实现第一个样例代码helloworld,这里遇到过很多的问题。

1. 问题

1: 源码包和SDK包的区别?

ImageBuilder:是编译完整固件用的,我们只编译ipk软件包所以用不到,

SDK包 : SDK将与该平台无关的程序都取消掉,只留下了编译需要用的工具和平台相关的代码,也就是说SDK是基础的编译环境,我们在上面选择对应的模块进行编译就好!!! ===》含有交叉编译环境用到的toolchain
​ 用du -sh查看下大小,只占了几百M,源工程可是有好几G呢
源码包: 可以通过make menuconfig 选择对应的目标文件进行生成,可以选择生成SDK等

2:正确编写一个样例代码的流程?

1:安装基础的依赖组件包
2:单纯依赖SDK包中的编译环境,直接配置我们的模块代码(在package目录中),单独编译我们的模块就ok ===》SDK是基础的编译环境,编译哪个由我们自己选择。
3:单独编译我们的模块 make -j1 V=cs package/模块名称/compile

3: Makefile报错问题的排查!

特别注意:遇到报错,要去分析报错!!!
在这里插入图片描述

问题:关注了行号看不出问题,请一定要多理解后面报错的涵义去分析问题

4: make menuconfig中对应的选项,有什么关系?

以及默认的选项,单独执行make进行全编译的时候为什么有很多的不通过?

2. 基于ubuntu20.4的纯净环境,使用我们的sdk(openwrt-sdk-ramips-mt7621_gcc-7.4.0_musl.Linux-x86_64.tar)进行样例代码的编译:

1:安装相关的基础包

sudo apt update
sudo apt upgrade
sudo apt install make
sudo apt-get install build-essential

2:参考官网https://openwrt.org/docs/guide-developer/build-system/install-buildsystem,安装对应的需要依赖。

hlp@ubuntu:~/openwrt/openwrt-sdk-ramips-mt7621_gcc-7.4.0_musl.Linux-x86_64/package$ sudo apt install build-essential ccache ecj fastjar file g++ gawk gettext git java-propose-classpath libelf-dev libncurses5-dev libncursesw5-dev libssl-dev python python2.7-dev python3 unzip wget python3-distutils python3-setuptools rsync subversion swig time xsltproc zlib1g-dev

3:配置样例代码,并进行编译。

hlp@ubuntu:~/openwrt/openwrt-sdk-ramips-mt7621_gcc-7.4.0_musl.Linux-x86_64/package$ tree helloworld/
helloworld/
├── helloworld.c
└── Makefile

0 directories, 2 files
hlp@ubuntu:~/openwrt/openwrt-sdk-ramips-mt7621_gcc-7.4.0_musl.Linux-x86_64/package$ cd ../
hlp@ubuntu:~/openwrt/openwrt-sdk-ramips-mt7621_gcc-7.4.0_musl.Linux-x86_64$ make -j V=s package/helloworld/compile
... #这里注意会不会有错误
hlp@ubuntu:~/openwrt/openwrt-sdk-ramips-mt7621_gcc-7.4.0_musl.Linux-x86_64$ find -name *.ipk |grep hello
./bin/packages/mipsel_24kc/base/helloworld_1.0-1_mipsel_24kc.ipk
hlp@ubuntu:~/openwrt/openwrt-sdk-ramips-mt7621_gcc-7.4.0_musl.Linux-x86_64$

可以看到,在SDK包目录下package目录中写自己的样例代码,只要实现样例代码以及对应的Makefile,特别注意Makefile中tab键不能是空格

helloworld.c

#include <stdio.h>
int main()
{
	printf("\n hello world!\n");
	return 0;
}

Makefile ===>这里的不规范导致我持续处理了好久,不能用八个空格代表tab
注意:这里的makefile中有个源码路径,需要修改

include $(TOPDIR)/rules.mk

# Name, version and release number
# The name and version of your package are used to define the variable to point to the build directory of your package: $(PKG_BUILD_DIR)
PKG_NAME:=helloworld
PKG_VERSION:=1.0
PKG_RELEASE:=1

# Source settings (i.e. where to find the source codes)
# This is a custom variable, used below
SOURCE_DIR:=/home/hlp/openwrt/openwrt-sdk-ramips-mt7621_gcc-7.4.0_musl.Linux-x86_64/package/helloworld

include $(INCLUDE_DIR)/package.mk

# Package definition; instructs on how and where our package will appear in the overall configuration menu ('make menuconfig')
define Package/helloworld
  SECTION:=examples
  CATEGORY:=Examples
  TITLE:=Hello, World!
endef

# Package description; a more verbose description on what our package does
define Package/helloworld/description
  A simple "Hello, world!" -application.
endef

# Package preparation instructions; create the build directory and copy the source code. 
# The last command is necessary to ensure our preparation instructions remain compatible with the patching system.
define Build/Prepare
	mkdir -p $(PKG_BUILD_DIR)
	cp $(SOURCE_DIR)/* $(PKG_BUILD_DIR)
	$(Build/Patch)
endef

# Package build instructions; invoke the target-specific compiler to first compile the source file, and then to link the file into the final executable
define Build/Compile
	$(TARGET_CC) $(TARGET_CFLAGS) -o $(PKG_BUILD_DIR)/helloworld.o -c $(PKG_BUILD_DIR)/helloworld.c
	$(TARGET_CC) $(TARGET_LDFLAGS) -o $(PKG_BUILD_DIR)/$1 $(PKG_BUILD_DIR)/helloworld.o
endef

# Package install instructions; create a directory inside the package to hold our executable, and then copy the executable we built previously into the folder
define Package/helloworld/install
	$(INSTALL_DIR) $(1)/usr/bin
	$(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/usr/bin
endef

# This command is always the last, it uses the definitions and variables we give above in order to get the job done
$(eval $(call BuildPackage,helloworld))

我么可以参考模板进行我们项目配置,注意 CATEGORY:=Examples 这行命令把我们的模块配置在了menuconfig中,$(INSTALL_DIR) $(1)/usr/bin 是我们目标文件的生成位置。

4: 上传ipk到对应的固件环境,安装并执行:

opkg install /tmp/helloworld_1.0-1_mipsel_24kc.ipk

安装包安装完成后,直接在串口终端输入:hello_world

root@transCOMM:/tmp# opkg install helloworld_1.0-1_mipsel_24kc.ipk 
Installing helloworld (1.0-1) to root...
Configuring helloworld.
Collected errors:
 * opkg_conf_parse_file: Duplicate src declaration (openwrt_base http://downloads.openwrt.org/snapshots/packages/mipsel_24kc/base). Skipping.
 * opkg_conf_parse_file: Duplicate src declaration (openwrt_luci http://downloads.openwrt.org/snapshots/packages/mipsel_24kc/luci). Skipping.
 * opkg_conf_parse_file: Duplicate src declaration (openwrt_packages http://downloads.openwrt.org/snapshots/packages/mipsel_24kc/packages). Skipping.
root@transCOMM:/tmp# helloworld 

 hello world!
root@transCOMM:/tmp# 

3. 遗留一些疑问:

​ 1: 单独的SDK包,是基础的编译环境,用make package/XXX/compile 进行编译单独的模块,如果有默认的选项,用make直接编译,不通过?

​ 2:Makefile的使用技巧及问题排查。

​ 3:其他可以试试在别的模块写代码,配置 feeds.conf进行连接自己的模块编译,或者分层级的makefile编译。

​ 4:openwrt虚拟机,openwrt整体编译, 刷固件等可以待研究。

​ 5:openwrt安装第三方模块(openwrt官方源中下载,可以使用svn或者git方式下载包)? make package/XXX/download make package/XXX/prepare make package/XXX/compile ==>https://dev.openwrt.org/browser/packages/utils/nano (如namo的包)

​ 6:openwrt自动编译固件升级?GitHub Actions云编译OpenWrt?参考: https://gitee.com/coray/openwrt#https://pan.baidu.com/s/1RVi4nN8Y1ak9LTWzhV5bSQ

openwrt官网文档可以查看:https://openwrt.org/docs/start

openwrt相关包下载:https://downloads.openwrt.org/

4. 其他源码目录了解等:

交叉编译环境运行生成的文件是不可以在我们的环境直接运行的,需要拷贝到对应的环境上去运行。

1:构建交叉编译环境:(可以解压到opt目录下,也可以source /etc/bash.bashrc中修改环境变量)
	1:通过源码包staging_dir目录下直接有toolchain,设置环境变量,使用mipsel-openwrt-linux-gcc -v进行验证
		export PATH=$PATH:"/home/ubuntu/0407_AT/openwrt-sdk-ramips-mt7621_gcc-7.4.0_musl.Linux-x86_64/staging_dir/toolchain-mipsel_24kc_gcc-7.4.0_musl/bin"
		export STAGING_DIR='/home/ubuntu/0407_AT/openwrt-sdk-ramips-mt7621_gcc-7.4.0_musl.Linux-x86_64/staging_dir'
	2:可以使用make menuconfig 选上toolchain,会在bin/ramips/目录生成toolchain包,解压后设置环境变量即可
		Target System:你的路由器的Soc架构
		Subtarget:你的路由器Soc的型号
		Target Profile:你的路由器的型号
		Build the OpenWrt SDK:是否选择编译SDK,按需选择
		SDK可用于交叉编译
		Libraries:Linux的库
		LuCI:路由器的网页界面
		Utilities:Linux下的工具
2:openwrt代码库目录层级的含义?
	build_dir:用来解压所有的源代码和编译它们的位置
	staging_dir:用来安装所有已编译软件的位置,或者用来存放用来打包、组装固件的文件。

build_dir文件夹中有三个区域:
	build_dir/host:用来编译所有跑在主机上的程序(OpenWRT从源中编译他自己版本的sed和其它许多工具)。
			这个区域将用来编译仅跑在你主机上的程序。
	build_dir/toolchain:用来编译打包中使用到的C交叉编译器和C标准库组件。
			这个区域将用来编译仅跑在你住几上的程序(例如:C交叉编译器)以及设计的跑在目标机器上的链接库,例如uClibc, libm, pthreads等等。
	build_dir/target:用于编译目标系统的实际的包,和Linux内核。

staging_dir下也有三个区域:
	staging_dir/host:该文件夹是一个微型的Linux 根目录,有自己的目录bin/, lib/等等。
		这是主机工具安装的位置,构建系统的其余部分会将该区域的目录前缀到环境变量PATH中。
	staging_dir/toolchain:该文件夹是一个微型的Linux 根目录,有自己的目录bin/, lib/等等。
		它包含用来构建固件的C交叉编译器。
			你可以用该编译器在OpenWRT之外编译一个可以加载到固件中的简单的C程序。
				这个C编译器一般是这样:staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-uclibc-gcc。
				你可以看到CPU、C库和编码到其中的gcc的版本号;
				并且允许多目标同时在一起构建。
	staging_dir/target:包含每个目标包已安装的版本;
			根目录形式,包含bin/, lib/等等,并且将会变成实际的根目录,仅作出一些调整就会打包进固件镜像中,像root-ar71xx之类的。这里也有一些其它的文件在其中,主要生成软件包和开发软件包。
3:不同命名的安装包的含义? 以及如何使用这些安装包。
		相关的bin文件就是生成的固件,刷进自己的固件中就可以了。
4:如何选择系统对应的openwrt版本?
5:交叉编译环境编译出来的可执行文件是无法运行的,需要拷贝到开发板上?  那么,如何安装openwrt虚拟机
	使用交叉编译环境如何生成ipk文件
	make的时候 选用参数 host指定交叉编译环境的gcc
	
	查看固件对应的openwrt版本:https://openwrt.org/toh/views/toh_fwdownload

6:源码实现: bin文件是最终的刷入固件中的样式
	我们可以实现正确的二进制文件,直接进行运行?
	我们可以实现openwrt的模块(ipk),使用opkg进行安装
7:定制自己的固件:			
	有三种方法编译openwrt定制固件。 https://blog.csdn.net/wsclinux/article/details/46311893
		1. 用ImageBuilder编译,用于灵活选择package。毕竟压缩的只读文件系统squashfs比可写的JFFS能省不少地方,可以用来把玩更多的package。 https://www.right.com.cn/forum/thread-4087041-1-1.html
			tar xvJf openwrt-imagebuilder-19.07.7-ramips-mt7621.Linux-x86_64.tar.xz 
			cd openwrt-imagebuilder-19.07.7-ramips-mt7621.Linux-x86_64/
			make info
			make image PROFILE=youhua_wr1200js PACKAGES="luci luci-i18n-base-zh-cn luci-i18n-firewall-zh-cn luci-i18n-opkg-zh-cn luci-lib-ipkg ddns-scripts luci-app-ddns luci-i18n-ddns-zh-cn"
			最后在bin目录下生成对应的固件

		2. 用SDK编译,用于编译package仓库中没有的软件包,另外其中有配套的内核源码及头文件,编译缺失的内核模块也很方便。
		3. 从源码编译,因为要重新编译cross-compile toolchians,下载最内核和软件包的源码编译,导致这个过程比较耗时,用于上述两种情况搞不定的情况。
			https://qiedd.com/344.html
		
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值