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

简介: 使用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
目录
相关文章
|
5月前
|
Ubuntu Linux 开发工具
openwrt环境搭建编译demo
openwrt环境搭建编译demo
75 0
|
5月前
|
并行计算 监控 Shell
openwrt编译模块demo练习
openwrt编译模块demo练习
54 0
|
5月前
|
开发工具 git
openwrt编译
openwrt编译
75 1
|
5月前
|
Linux 开发工具 C++
Linux基础环境开发工具的使用(二):动静态库的理解,make,makefile(下)
Linux基础环境开发工具的使用(二):动静态库的理解,make,makefile
|
5月前
|
Linux 开发工具 C语言
Linux基础环境开发工具的使用(二):动静态库的理解,make,makefile(上)
Linux基础环境开发工具的使用(二):动静态库的理解,make,makefile
|
6月前
|
Go Windows
5个步骤搞定protoc环境安装
5个步骤搞定protoc环境安装
225 1
|
8月前
|
Ubuntu 编译器 网络安全
RK3568开发笔记(七):在宿主机ubuntu上搭建Qt交叉编译开发环境,编译一个Demo,目标板运行Demo测试
在之前的博文中已经搭建好了一个比较完善的ubuntu宿主机,都很完善了但是发现没有Qt交叉编译开发环境,所以还需要搭建一套Qt交叉编译开发环境。
|
11月前
|
IDE 编译器 开发工具
统信UOS系统开发笔记(四):从Qt源码编译安装之编译安装QtCreator4.11.2,并配置编译测试Demo
上一篇已经从Qt源码编译了Qt,那么Qt开发的IDE为QtCreator,本篇从源码编译安装QtCreator,并配置好构建套件,运行Demo并测试。
|
12月前
|
Ubuntu 编译器 Linux
Linux驱动开发笔记(三):基于ubuntu的helloworld驱动源码编写、makefile编写以及驱动编译加载流程测试
前面学习了驱动的基础框架,上一篇编译了gcc7.3.0,那么为了方便很好的熟悉流程,本篇,将使用ubuntu18.04,直接编译ubuntu18.04的驱动,然后做好本篇文章的相关实战测试。
|
12月前
|
C语言
tufao 编译环境配置(二)
前文提到tufao 自1.4.0 后开始引入boost.http,故本文在前文基础上配置 tufao 最新版本编译环境。如有不懂见上一章节详细配置。
110 0