いでで。みごとに落とし穴にはまってしまった。その経験談。
MIPSアーキテクチャのターゲットで、goで書かれたプログラムを動かす必要が出てきたので、ちょっとハロワでテスト。
golangが比較的最近にMIPS対応が入ったというのは聞いたことがあった。ちょっと状況をググる。
Go 1.8 Release Notes - The Go Programming Language
https://golang.org/doc/go1.8
Go 1.8のMIPS32バイナリをルータ上で動かしてみた(成功編) - Qiita
https://qiita.com/hnw/items/8703a0e776f8b6a60b45
Go 1.8の32-bit MIPSサポートはFPUかカーネルによるFPUエミュレーションが必須だと書いてある。 なるほど soft float 必須か。めんどくさいな。 下手すると、SDKに手を入れないといけないし、kernelのコンディション変更は嫌がられるかも。
Floating point - LinuxMIPS
https://www.linux-mips.org/wiki/Floating_point
ここには、Linuxではデフォルトで、ハードフロートだと書かれている。
続報もあった。
Go 1.10にMIPS32 softfloat対応が来たよー - Qiita
https://qiita.com/hnw/items/ee6e3269c38d415bf8e5
とりあえず、やってみることにする。
Ubuntu環境に最新のgoをインストールする。
Getting Started - The Go Programming Language
https://golang.org/doc/install
Downloads - The Go Programming Language
https://golang.org/dl/
最新は、これのようだ。
・go1.13.1.linux-amd64.tar.gz (114MB) ・go1.13.1.src.tar.gz (21MB)
curlでダウンロードしようかと思ったら、curlは入ってなかつた。wgetは入っていたので、それでいいか。
ubuntu@mos:~$ wget https://dl.google.com/go/go1.13.1.linux-amd64.tar.gz
--2019-10-17 12:16:54-- https://dl.google.com/go/go1.13.1.linux-amd64.tar.gz
dl.google.com (dl.google.com) をDNSに問いあわせています... 172.217.161.46, 2404:6800:4004:800::200e
dl.google.com (dl.google.com)|172.217.161.46|:443 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 120040373 (114M) [application/octet-stream]
`go1.13.1.linux-amd64.tar.gz' に保存中
go1.13.1.linux-amd6 100%[===================>] 114.48M 113MB/s 時間 1.0s
2019-10-17 12:16:56 (113 MB/s) - `go1.13.1.linux-amd64.tar.gz' へ保存完了 [120040373/120040373]
そのまま展開すると「許可がありません」の嵐になるので、rootで展開。
ubuntu@mos:~$ sudo tar -C /usr/local -xzf go1.13.1.linux-amd64.tar.gz
[sudo] ubuntu のパスワード:xxxxxxxxxxxxxxxxxx
インストールできた。少し確認など。
ubuntu@mos:~$ which go
/usr/local/go/bin/go
ubuntu@mos:~$ go version
go version go1.13.1 linux/amd64
ディレクトリを掘って、ハロワを置く。
ubuntu@mos:~$ export PATH=$PATH:/usr/local/go/bin
ubuntu@mos:~$ mkdir -p $HOME/go/src/hello
ubuntu@mos:~$ vi $HOME/go/src/hello/main.go
package main
import "fmt"
func main() {
fmt.Printf("hello, world\n")
}
とりあえず、手元の環境でビルドしてみる。
ubuntu@mos:~$ cd $HOME/go/src/hello
ubuntu@mos:~/go/src/hello$ go build
できた。
ubuntu@mos:~/go/src/hello$ ls
hello main.go
ubuntu@mos:~/go/src/hello$ file hello
hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
ubuntu@mos:~/go/src/hello$ ./hello
hello, world
当たり前だが、普通に動く。
MIPSでビルドしてみる。
ubuntu@mos:~/go/src/hello$ GOOS=linux GOARCH=mips go build
ubuntu@mos:~/go/src/hello$ ls
hello main.go
ubuntu@mos:~/go/src/hello$ file hello
hello: ELF 32-bit MSB executable, MIPS, MIPS32 version 1 (SYSV), statically linked, not stripped
ubuntu@mos:~/go/src/hello$ ls -lh hello
-rwxr-xr-x 1 ubuntu ubuntu 2.0M 10月 17 12:35 hello
ハロワで2Mはデカいな...
stripってどうやるんだろ? とりあえず、stripコマンドでやってみる。
ubuntu@mos:~/go/src/hello$ cp hello hello.org
ubuntu@mos:~/go/src/hello$ strip hello
strip: 入力ファイル `hello' の形式を認識できません
だよね... アーキが違うものね。goでクロスコンパイルの時には、-ldflags '-s -w'を付けるとstripされるそうだ。
ubuntu@mos:~/go/src/hello$ GOOS=linux GOARCH=mips go build -ldflags '-s -w'
ubuntu@mos:~/go/src/hello$ ls -lh hello*
-rwxr-xr-x 1 ubuntu ubuntu 1.4M 10月 17 13:10 hello
-rwxr-xr-x 1 ubuntu ubuntu 2.0M 10月 17 12:40 hello.org
ちょっとだけ小さくなった。
ターゲットに転送して動作確認。pythonのワンライナでWebサーバーを起動して、ターゲットからwgetする。
ubuntu@mos:~/go/src/hello$ python -m SimpleHTTPServer 8080
Serving HTTP on 0.0.0.0 port 8080 ...
root@MIPSTARGET:/tmp# wget xxx.xxx.xxx.xxx:8080/hello
--12:42:30-- http://xxx.xxx.xxx.xxx:8080/hello
=> `hello'
Connecting to xxx.xxx.xxx.xxx:8080... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2,007,185 (1.9M) [application/octet-stream]
100%[====================================>] 2,007,185 1.28M/s
12:42:31 (1.28 MB/s) - `hello' saved [2007185/2007185]
実行権限を付けて実行してみる。
root@MIPSTARGET:/tmp# chmod +x hello
root@MIPSTARGET:/tmp# ./hello
./hello: line 3: syntax error: unexpected "(" (expecting ")")
あらら。
Enable mips build · Issue #3959 · syncthing/syncthing
https://github.com/syncthing/syncthing/issues/3959
エンディアンの問題かしらん。それともfpuサポートの問題かしらん。
MIPSのCPUは、リトルとビッグのどちらのエンディアンでも利用できる。歴史的には、MIPSはビッグエンディアンで構成されているシステムが多い。最近は普通のCPUではリトルエンディアンの環境が多いのだが、通信系で利用されてきた経緯から、MIPSはデフォルトがビッグエンディアンの環境が多い。この頃は、さすがにリトルエンディアンで構成されているシステムも増えてきた。 そのような経緯から、LinuxのCPUアーキテクチャでは、歴史的にビッグエンディアンはmipsで、リトルエンディアンはmipselになっている。末尾のelは、エンディアン・リトルの略。
ubuntu@mos:~/go/src/hello$ GOOS=linux GOARCH=mipsel go build
cmd/go: unsupported GOOS/GOARCH pair linux/mipsel
がーん。(それが間違いの元でした... orz)
########エンディアンの確認方法?
softfloatをオンにしてみる。
runtime: mips33 soft float point support · Issue #18162 · golang/go
https://github.com/golang/go/issues/18162
GO_GCFLAGS="-d softfloat"か-gcflags=all="-d softfloat"を指定したらいいようだ。
ubuntu@mos:~/go/src/hello$ GOOS=linux GOARCH=mips GO_GCFLAGS="-d softfloat" go build
ubuntu@mos:~/go/src/hello$ ls -lh hello*
-rwxr-xr-x 1 ubuntu ubuntu 2.0M 10月 17 12:54 hello
-rwxr-xr-x 1 ubuntu ubuntu 2.0M 10月 17 12:40 hello.org
オプション付けていないのと、サイズ同じじゃん...
ubuntu@mos:~/go/src/hello$ file hello*
hello: ELF 32-bit MSB executable, MIPS, MIPS32 version 1 (SYSV), statically linked, not stripped
hello.org: ELF 32-bit MSB executable, MIPS, MIPS32 version 1 (SYSV), statically linked, not stripped
同じじゃね?
ubuntu@mos:~/go/src/hello$ diff hello hello.org
まったく同じだってさ。ということはsoftfloatはデフォルトってことだな。
これのせいだとすると、kernelとtoolchainでsoftfloatをオンにするしかない。それはリスキーだな。他の部分の実行速度にも影響出ちゃうのじゃ。
twitterで、mipsleじゃないかと教えてもらった。
ubuntu@mos:~/go/src/hello$ GOOS=linux GOARCH=mipsle go build
ubuntu@mos:~/go/src/hello$ file hello
hello: ELF 32-bit LSB executable, MIPS, MIPS32 version 1 (SYSV), statically linked, not stripped
ubuntu@mos:~/go/src/hello$ ls -lh hello*
-rwxr-xr-x 1 ubuntu ubuntu 2.0M 10月 17 13:55 hello
-rwxr-xr-x 1 ubuntu ubuntu 2.0M 10月 17 12:40 hello.org
ubuntu@mos:~/go/src/hello$ diff hello hello.org
バイナリーファイル hello とhello.org は異なります
おお、できたものは違うそうだ。ちょっと期待できる。ターゲットに転送してテストする。
root@MIPSTARGET:/tmp# rm hello
root@MIPSTARGET:/tmp# wget xxx.xxx.xxx.xxx:8080/hello
--13:57:14-- http://xxx.xxx.xxx.xxx:8080/hello
=> `hello'
Connecting to xxx.xxx.xxx.xxx:8080... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2,007,259 (1.9M) [application/octet-stream]
100%[====================================>] 2,007,259 1.72M/s
13:57:15 (1.72 MB/s) - `hello' saved [2007259/2007259]
root@MIPSTARGET:/tmp# chmod +x hello
root@MIPSTARGET:/tmp# ./hello
[584108.516000] Algorithmics/MIPS FPU Emulator v1.5
hello, world
動くじゃん...
というか、なんでgoではmipsleなの... ARCH表記の伝統に従わないなんて...
オリジナル投稿:
golangでMIPSアーキテクチャをビルドするときの落とし穴|kinneko|pixivFANBOX
https://kinneko.fanbox.cc/posts/609704


