golang和rust嵌入式開發初探

本文簡單的介紹了golang和rust語言在openwrt系統、mips架構下的交叉編譯。

環境

主機 系統 內核 架構
host主機 Centos 7.2 linux 3.10.0-327 x86_64
target主機 openwrt 14.07 linux 3.10.14 mipsel

我們要在host主機上編譯target主機上運行的二進制程序。由於我們團隊有現有的路由寶產品,所以使用現有openwrt環境、並在真機路由器上做測試。如果想親自動手實驗,可以考慮使用QEMU等虛擬機軟件模擬相應環境。

工具鏈

獲取openwrt工具鏈有兩種方式:

  1. 可以直接使用openwrt的官網自行下載相應平臺的SDK。文檔
  2. 使用源碼自己編譯,新文檔舊文檔

文檔介紹的比較詳細,以下簡單列出一些步驟和問題。

  1. 進入源碼目錄,make menuconfig配置相應平臺和其他選項等。
  • make menuconfig終端可能顯示亂碼。解決:export TERM=screen
  1. make -j8
  • 可以使用-j8 選項加快編譯速度。
  • make時會下載依賴源碼包,由於衆所周知的網絡原因,可能有些包無法下載。
    解決:可以使用make V=s 打印編譯詳細信息,查看卡在哪個下載,根據url自行想辦法,然後把下載到到包放到dl目錄。
  1. 編譯完成後會在staging_dir目錄下生產工具鏈。

驗證工具鏈

第1步. 設置STAGING_DIR環境變量爲上面工具鏈目錄。

$ export STAGING_DIR=staging_dir目錄

第2步. 寫一個hello world程序hello.c。

#include <stdio.h>

int main() {
    printf("Hello, c!\n");
}

第3步. 使用工具鏈編譯該文件。

$ $STAGING_DIR/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mipsel-openwrt-linux-gcc -o hello-c hello.c
$ ls -l
-rwxr-xr-x 1 wanglei01 users    5933 Jan 31 11:09 hello-c

第4步. 把hello-c弄到路由上,測試。

[root@Youku-router]./hello-c
Hello, c!

rust交叉編譯

第1步. 安裝rust。curl https://sh.rustup.rs -sSf | sh
第2步. 創建rust項目,編寫main.rs文件,並配置一些優化選項。

$ cargo new --bin hello-rust
$ cd hello-rust

$ ls -al
-rw-r--r-- 1 wanglei01 users  205 Jan 31 11:20 Cargo.toml
drwxr-xr-x 2 wanglei01 users 4096 Jan 31 11:37 src

$ cat src/main.rs 
fn main() {
    println!("Hello, rust!");
}

$ cat Cargo.toml
[package]
name = "hello-rust"
version = "0.1.0"
authors = ["you"]

[dependencies]

[profile.release]
lto = true
panic = "abort"

第3步. rust交叉編譯需要一些nightly特性,所以需要安裝nightly版本,並設置當前目錄編譯工具。

$ rustup install nightly
$ rustup override set nightly

第4步. 安裝rust源碼,供交叉編譯rust std。

$ rustup component add rust-src

第5步. 安裝xargo工具,該工具方便rust進行交叉編譯。

cargo install xargo

第6步. 進行一些交叉編譯的配置。以下直接列出配置項:

$ cat .cargo/config
[build]
target = "mipsel-unknown-linux-uclibc"

[target.mipsel-unknown-linux-uclibc]
linker = "$STAGING_DIR/bin/mipsel-openwrt-linux-gcc"

$ cat Xargo.toml
[target.mips-unknown-linux-uclibc.dependencies.std]
features = []

第7步. 編譯。

$ xargo build --release
$ tree -L 4
.
├── Cargo.lock
├── Cargo.toml
├── src
│   └── main.rs
├── target
│   ├── mipsel-unknown-linux-uclibc
│   │   ├── debug
│   │   └── release
│   │       ├── hello-rust  可執行文件
└── Xargo.toml

第8步. 放到路由寶上驗證。

[root@Youku-router]./hello-rust
Hello, rust!

golang交叉編譯

相比與rust,golang的交叉編譯就簡單多了。
golang 在1.8版本以後,可以直接使用gc Go編譯MIPS(LE)架構的linux二進制程序。所以我們可以直接安裝host主機的go,而不用c交叉工具鏈。如果要使用gccgo編譯,或是使用cgo的話是需要的。gc與gccgo區別

安裝golang

安裝golang有兩種方式:

  1. 可以直接去 官網 下載適合你係統的二進制包。
  2. 源碼安裝
    這裏安裝的go二進制爲host主機的。

編譯golang

package main
import "fmt"

func main() {
    fmt.Println("hello golang!")
}
  • 使用-ldflags '-w -s’編譯選項,去掉一些符號信息,減少二進制體積。具體可以查看go tool link -h
$ GOOS=linux GOARCH=mipsle go build -o hello-go-symbol
$ GOOS=linux GOARCH=mipsle go build -o hello-go -ldflags '-w -s'

$ ls -l
-rwxr-xr-x 1 wanglei01 users 1384448 Jan 31 10:58 hello-go
-rwxr-xr-x 1 wanglei01 users 1956182 Jan 31 11:02 hello-go-symbol

運行

把它弄到路由上跑一下。

[root@router]./hello-go
hello golang!

總結

我們只是簡單的佈置了開發環境,只是寫了一個簡單的hello world程序,沒有使用第三方庫,也沒有動態連接其他動態庫。

  1. 開發環境golang是非常的簡單的,應該也是因爲go強大的運行時庫,不需要依賴第三方的原因。
  2. 也正是因爲golang運行時庫的優勢,也造成了他的劣勢,二進制體積過大。

下面列出經過strip後的文件列表:

-rwxr-xr-x 1 wanglei01 users    5931 Jan 31 20:04 hello-c
-rwxr-xr-x 1 wanglei01 users    3580 Jan 31 11:09 hello-c-strip

-rwxr-xr-x 1 wanglei01 users 1956182 Jan 31 11:02 hello-go-symbol
-rwxr-xr-x 1 wanglei01 users 1384448 Jan 31 10:58 hello-go
-rwxr-xr-x 1 wanglei01 users 1385068 Jan 31 11:11 hello-go-strip

-rwxr-xr-x 1 wanglei01 users  149824 Jan 31 11:06 hello-rust
-rwxr-xr-x 1 wanglei01 users  111084 Jan 31 11:11 hello-rust-strip

-rwxr-xr-x 1 wanglei01 users   79440 Jan 31 20:40 hello-rust-release
-rwxr-xr-x 1 wanglei01 users   79440 Jan 31 20:41 hello-rust-release-strip
  • 不知爲何,golagn strip後反而變大了。。。
  • rust-release是經過優化後的。參考
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章