简易解inode认证实战
1
2
3
4
5
6、交叉编译
经过一番折腾,我们终于写完了这一个认证过程,并且在Linux系统上运行正常。
本篇主要内容为编译&&交叉编译
Hello World编译流程:
一、假定我们有这么一个helloworld.c的文件
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("hello world");
return 0;
}
(1)我们可以用gcc来编译
gcc -c helloworld.c
命令执行后,没有错误的话,会多出一个文件helloworld.o
(2)也可以用g++来编译
g++ -c helloworld.c
同样的,多出了.o文件
(3)连接,同样用gcc或者g++都可以
gcc helloworld.o -o helloworld
或
g++ helloworld.o -o helloworld
执行完后,会有如下:helloword文件,
输入如下命令执行:
./helloworld
二、如果我们的文件是cpp文件,即C++
#include <iostream>
using namespace std;
int main()
{
cout<<"hello world"<<endl;
return 0;
}
则,编译:可用gcc或g++, 连接:一般只能用g++。
若链接用gcc,大概会报如下错误:
三、关于Makefile
我们可以使用makefile来将编译和连接的步骤连起来,相当于一个脚本
.c的Makefile
helloworld : helloworld.o
$(CC) $(LDFLAGS) helloworld.o -o helloworld
helloworld.o : helloworld.c
$(CC) $(CFLAGS) -c helloworld.c
clean :
rm *.o
.cpp的Makefile
helloworld : helloworld.o
$(CXX) $(LDFLAGS) helloworld.o -o helloworld
helloworld.o : helloworld.cpp
$(CXX) $(CFLAGS) -c helloworld.cpp
clean :
rm *.o
就是把CC改成CXX而已,
CC:指用gcc
CXX:指用g++
然后在目录下执行make,即生成.o 以及执行文件helloworld
执行make clean,则会清除.o文件
一、Debian Linux下编译&&连接
(1)先检查一下我们的代码包括了哪些文件
- main.cpp
- MD5.cpp
- MD5.h
- packethandle.cpp
- packethandle.h
(2)由上面的helloworld例子,我们可以跟着写出Makefile如下,注意到是CPP,因此用CXX:
Makefile:
main : main.o MD5.o packethandle.o
$(CXX) $(LDFLAGS) main.o MD5.o packethandle.o -lpcap -Istdc++ -o main
MD5.o : MD5.h MD5.cpp
$(CXX) $(CFLAGS) -c MD5.cpp
packethandle.o : packethandle.h packethandle.cpp
$(CXX) $(CFLAGS) -c packethandle.cpp -lpcap
main.o : main.cpp
$(CXX) $(CFLAGS) -c main.cpp -lpcap
clean :
rm *.o
(3)执行一下make,不报错的话,有如下文件
(4)测试一下文件是否可以正常运行:
ok,正常运行,那么在Debian Linux下编译连接工作就到这里。接下来就是交叉编译了
二、交叉编译
(1)先确定好固件类型、版本号,我们才能选择对应的SDK,否则编译出来的程序不能在平台上运行【很重要】
比如我有不可描述的K2路由器,则进入192.168.1.1,描述如下
可以看到,我们路由器运行pandoraBox 17.09版本
当然,我们也可以用xshell,192.168.1.1,端口22,连接后有如下,也可以看版本
(2)确定版本后,我们选择对应SDK下载【当然,也要知道你路由器的硬件配置,主要是CPU】
- 下载SDK的地址:http://download.pandorabox.com.tw:99/pandorabox/17.09/
- 我的路由是MT7620的,那么我就下载7620的SDK,注意,标明了SDK的才是,其他都是编译好的固件
- 我选了下图的来下载:
(3)将下载文件放入虚拟机,(必备啊)
- mkdir build 我新建了个文件夹来放
- tar xvJf ***.tar.xz ,解压
tar xvjf PandoraBox-SDK-ralink-mt7620_gcc-4.8-linaro_uClibc-1.0.x.Linux-x86_64.tar.xz
- 解压完后,需要在bashrc文件上加入对应环境
- 可以改/etc/bash.bashrc 或者/home/$USER/.bashrc ,$USER是你的用户名,自行替换即可
- 这里我改/home/$USER/.bashrc 文件
gedit /home/msi/.bashrc
在文件末尾,添加类似如下,至于路径,则自行根据环境修改【即不要直接复制我的,根据自己环境修改】
export PATH=$PATH:/home/msi/build/PandoraBox-SDK-ralink-mt7620_gcc-4.8-linaro_uClibc-1.0.x.Linux-x86_64/PandoraBox-SDK-ralink-mt7620_gcc-4.8-linaro_uClibc-1.0.x.Linux-x86_64/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-1.0.x/bin
export STAGING_DIR=/home/msi/build/PandoraBox-SDK-ralink-mt7620_gcc-4.8-linaro_uClibc-1.0.x.Linux-x86_64/PandoraBox-SDK-ralink-mt7620_gcc-4.8-linaro_uClibc-1.0.x.Linux-x86_64/staging_dir/
(4)检查toochains环境配置是否完成
- 在命令行中输入lip, 按TAB,看是否会自动补全
- 如下:
自动补全,则环境配置完成
(5)尝试利用mipsel-openwrt-linux-gcc,来编译连接我们刚刚的helloworld
- 在helloworld目录下,执行
mipsel-openwrt-linux-g++ -c helloworld.cpp
mipsel-openwrt-linux-g++ helloworld.o -o helloworld
如果编译链接报错,那么可能是本机缺少一些SDK运行所需的库,先检查一下,
一个关键的c库【提示什么cloog、C compiler cannot可以尝试以下来解决】:
sudo apt-get install ccache
sudo apt-get update sudo apt-get install git-core build-essential libssl-dev libncurses5-dev unzip gawk sudo apt-get install subversion mercurial
- 这个操作,实际上就是交叉编译了,我们利用的是SDK中的Pandorabox平台的编译器
- 这个过程,很像上面一开始的编译连接过程,只不过是gcc变成了lip。。。。-gcc。
- 我们尝试在Debian Linux下执行编译出来的文件,提示错误,这是正常的,因为这是openwrt环境下的可执行文件
(6) 接下来,将这个helloworld文件,从虚拟机拖到电脑上,再利用winscp工具,将它上传到路由器上,看能否执行
- winscp到处都能下,就不提供下载地址了
- 上传的步骤如下:
- 打开winscp,登录 192.168.1.1 账户 root 密码 admin,然后将helloworld拖到root目录下
- 再登录XSHELL,执行如下:
chmod +x helloworld
./helloworld
- 如果可正常输出,则表示SDK版本选择对了
- 如果提示缺失一个什么libstdc++.so.6文件,而你的路由此时不能上网,那么可以回到虚拟机,在SDK的文件下中寻找该文件,然后将libstdc++.so.6文件拖到路由器的/lib 目录即可
- 如果提示segment fault,那么很可能你的SDK版本对不上你的固件,也有可能是程序的问题,但是一般helloworld不会出现这个问题,所以helloworld的作用也在这里体现了
- 如果你的libstdc++.so.6文件是网上下载的,也有可能版本不对,貌似也会出现segment fault的问题
- 如果执行输出如下,恭喜你,可以进行下一步操作了
(7)既然成功交叉编译了hellowrold,那么我们可以用同样的套路来编译我们的认证程序
- 在程序目录下,依次执行
mipsel-openwrt-linux-g++ -c MD5.cpp
mipsel-openwrt-linux-g++ -c packethandle.cpp
mipsel-openwrt-linux-g++ -c main.cpp
- 链接obj
mipsel-openwrt-linux-g++ main.o MD5.o packethandle.o -o main
- 一般来说,会报错如下:
原因是,我们的认证程序用到了libpcap,而这个libpcap并没有在SDK的平台上,因此,我们需要给它装上这个库
a)下载libpcap-1.6.2
链接:https://pan.baidu.com/s/16RO8ByXcXclj0Cbgoe105Q 提取码:o7dl
b)解压,进入对应文件夹
c)安装,注意并非安装到本机目录,而是要安装到SDK的目录下,因此./configure时,要添加参数
./configure --host=mipsel CC=/home/msi/build/PandoraBox-SDK-ralink-mt7620_gcc-4.8-linaro_uClibc-1.0.x.Linux-x86_64/PandoraBox-SDK-ralink-mt7620_gcc-4.8-linaro_uClibc-1.0.x.Linux-x86_64/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-1.0.x/bin/mipsel-openwrt-linux-gcc --prefix=/home/msi/build/PandoraBox-SDK-ralink-mt7620_gcc-4.8-linaro_uClibc-1.0.x.Linux-x86_64/PandoraBox-SDK-ralink-mt7620_gcc-4.8-linaro_uClibc-1.0.x.Linux-x86_64/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-1.0.x/ --with-pcap=linux
--host 表示你要安装的平台,然后 CC= 填写你SDK中toolchain-mipsel,gcc的地址,
--prefix表示安装的路径,--with-pcap=linux , 【路径那些,按照你的本地环境SDK路径改就好了】
d)安装成功,继续操作
- 再次链接obj,这时要加上参数 -pcap,表示用这个库
mipsel-openwrt-linux-g++ main.o MD5.o packethandle.o -pacp -o main
这时候应该就可以链接成功了,生成如下
(8)路由器上测试我们的程序
- 同样winscp上传
- chmod +x main
- ./main
- 如果提示缺失libstdc++.so.6,按上面提到的方法处理即可【后面会有更好的方法解决】
- 如果提示缺libpcap库,这里给一个下载地址尝试安装该库:链接:https://pan.baidu.com/s/15wWwMcqzaMnpIYWD6-Ihdw 提取码:mcfd 【一般来说应该不会,貌似我们的程序静态编译了这个库?】
- 路由器opkg安装ipk文件,貌似要进行配置,请参见:https://blog.csdn.net/weixin_29465425/article/details/82668292
成功运行如下:
(9)到这里,我们的交叉编译可执行文件基本就OK了。接下来会讲利用SDK生成IPK安装包
三、利用SDK生成IPK安装包
(1)如果我们交叉编译的可执行文件可以在路由上运行,那么实际上已经成功了大半
(2)接下来,我们还是先以helloworld为例子,生成其ipk文件
- 进入程序文件夹,新建一个src文件夹,并将helloworld.cpp Makefile移入src文件夹
- 检查src文件夹内的Makefile文件
- src:Makefile: 里面都是$(CXX), 而不是直接的g++,因为生成ipk时会自动改成mipsel-openwrt-linux-g++
helloworld : helloworld.o
$(CXX) $(LDFLAGS) helloworld.o -o helloworld
helloworld.o : helloworld.cpp
$(CXX) $(CFLAGS) -c helloworld.cpp
clean :
rm *.o
(3)我们在原来Makefile【上面的Makefile已经被移到src文件夹了】的位置,重新建一个Makefile:
警告:从这里复制过去的Makefile,可执行命令前面都变成空格,请自行将空格重新替换为TAB,否则接下来你会很头疼,会提示什么missing separator
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 Buile/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))
- 关于Makefile,这里不说太多【因为个人也不太懂】
- 只讲关键的:
- PKG_NAME:= _这里填文件夹的名字_, 例:文件夹名字为helloworld,则填hellworld
- define Package/_这里同上_, 即宏定义中Package/后面跟着文件夹名字,
- 重点:define Package/helloworld/install 宏定义中,第三条 $(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/bin/ ,红字helloworld并非代表文件夹,而是代表最终输出的可执行文件的名字,如果你src中的Makefile 链接 -o main,则红字改成main
- 其他一般不会有太大改动
(4)到这里,文档编辑类基本完成,先看看目录包含什么:
(5)接下来,将整个文件夹复制到SDK目录的Package目录下
(6)在SDK目录下,执行 make menuconfig,如果提示错误,请检查依赖库是否安装(自行百度)
make menuconfig
出现如下界面:
- 可在键盘敲 "/",进入搜索模式,然后输入helloworld进行搜索,搜索结果显示在Utilities,选择它,按空格进入
- 选中helloworld,按空格,使它前面的M变成*号,表示参加build
- 保存,退出
(7)返回命令行,执行
make package/helloworld/compile
输出:
然后报错如下:
Package helloworld is missing dependencies for the following libraries:
libstdc++.so.6
说少了这个依赖库,但是实际上我们是可以在SDK包中找到这个文件的,查找结果如下:
结合实际编译执行的感受,他这个提示可能是说,他这个版本的固件本身不带这个库,实际操作上也是,编译CPP程序到刷了这个PandoraBox 17.09固件上执行,会提示缺失这个库
解决方案:
解决方案参考自:https://my.oschina.net/hevakelcj/blog/411944 ,并对其方案三(这里的方案2)作出了修正
方案(1):在 Makefile 中的 Package/helloworld/install 宏中准备所需的库文件,即可以在这个宏里,将它需要的几个库文件复制到 $(1) 对应的目录下。
即修改Makefile:
define Package/helloworld/install
$(INSTALL_DIR) $(1)/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/bin
$(INSTALL_DIR) $(1)/usr/lib
$(INSTALL_DATA) $(TOOLCHAIN_DIR)/lib/libstdc++.so.6 $(1)/usr/lib
endef
警告:从这里复制过去的Makefile,可执行命令前面都变成空格,请自行将空格重新替换为TAB,否则接下来你会很头疼,会提示什么missing separator
方案(2):在 Makefile 文件的 Package/helloworld宏中加 DEPENDS 描述
define Package/helloworld
...<略>
DEPENDS+=libstdcpp
endef
警告:从这里复制过去的Makefile,可执行命令前面都变成空格,请自行将空格重新替换为TAB,否则接下来你会很头疼,会提示什么missing separator
(8)Makefile修改完成后,重新 make package/helloworld/compile
make package/helloworld/compile
这时候应该没有报错了。
我们去bin目录看一下生成的IPK
(9)对于我们的认证程序,操作步骤基本同步骤(1)~(8),这里就不再展示了
(10)将编译完成的IPK上传的路由器root目录,进行安装
chmod +x helloworld_1_mipsel_24kec_dsp.ipk
opkg install helloworld_1_mipsel_24kec_dsp.ipk
安装完成后,直接用helloworld,即可执行
(11)如果编译过程中,make Package/inode/compile,报错如下:
Package inode is missing dependencies for the following libraries:
libc.so.6
libm.so.6
libpcap.so.0.8
建议清理 掉所有的.o和可执行文件,重新生成