簡易解inode802.1x認證實戰(6)交叉編譯
簡易解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和可執行檔案,重新生成