1. 程式人生 > >簡易解inode802.1x認證實戰(6)交叉編譯

簡易解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】

(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和可執行檔案,重新生成