いでで。みごとに落とし穴にはまってしまった。その経験談。

 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