Back to home

Golang cross compile in the Mac OSX

Background

需要改写一个系统信息采集程序,系统比较老:REHL 5 。最新的Golang Stable版本1.3.1 已经去掉了CentOS/REHL5 的支持,但是使用的类库又不兼容之前的 1.2.1。好在 Golang 提供强大的跨平台编译功能,就没有琢磨在目标机器上如何编译的问题。

Cross Compile

Golang 本身提供多平台编译支持,已有用户对齐进行封装,让整个使用更加方便。

$ git clone git://github.com/davecheney/golang-crosscompile.git
$ source golang-crosscompile/crosscompile.bash

现在你就拥有了多平台的go指令。

go-crosscompile-build-all
go-crosscompile-build darwin/386
go-crosscompile-build darwin/amd64
go-crosscompile-build freebsd/386
go-crosscompile-build freebsd/amd64
go-crosscompile-build linux/386
go-crosscompile-build linux/amd64
go-crosscompile-build linux/arm
go-crosscompile-build windows/386
go-crosscompile-build windows/amd64

在编译时,只需要将go替换为对应平台指令即可

go-linux-arm build

上面的指令就会将项目编译到arm平台。首次编译时会安装对应平台的Golang,安装完成之后就能用其编译。

Multi-platform Golang development in Mac OSX

项目中获取系统信息的类库不支持darwin系统,所以只能在目标环境上测试(CentOS5)。

在Vagrant中配置好项目信息后


  config.vm.synced_folder "../agent/go", "/opt/agent",
    group: "monitor", owner: "monitor"


  config.vm.define "default", primary: true do |config|
      config.vm.hostname = "dev"
      config.vm.network "forwarded_port", guest: 8080, host: 8080
      config.vm.network :private_network, ip: "10.0.0.100"
  end

由于编译型语言的特质,没有办法很好的AutoReload,那么我们开发最大的工作量可能不是Coding,而是Reloading。所以我们需要让这些自动化起来。

AutoReloading with Golang

一开始瞄准的是Golang实现的一个工具叫做 gin,在测试了他奇怪的编译路径和执行路径不一致之后(最后使用软连接解决),发现这种方案限制了执行环境。所以只能手工实现。

通常我们都会用 inotify 捕获文件系统事件,然后重新编译后的程序。

inotifywait -mq -e modify,delete,create,attrib /opt/agent/src/agent | while read line; do DO_RESTART_JOB; done

但是通过 synced_folder 同步的文件无法被inotify捕获修改事件,并没有按照预期的触发。这是因为Vagrant的虚机提供者VirtualBox的SharedFolder实现相关

那么只能走轮询了:

$ SUM=`md5sum ./agent`; while true; do sleep 1; if [[ "$SUM" != "`md5sum ./agent`" ]]; then pkill -f agent; bash -c "nohup /opt/agent/src/agent &"; SUM=`md5sum ./agent`; echo "restarted"; fi; done

Conclusion

工具链真折腾,总是要花很多时间熟悉。

Reference