cross compiling gccgo for MIPS

1,775 views
Skip to first unread message

Damjan Georgievski

unread,
Jul 9, 2013, 6:04:52 AM7/9/13
to golan...@googlegroups.com
I'd like to see how Go programs would work on the OpenWRT platform, so I've compiled a cross-compiling gcc 4.8.1 with Go enabled [1]. So now I have cross-mipsel-linux-gnu-binutils 2.23.2-1 and cross-mipsel-linux-gnu-gcc 4.8.1-1 installed.

But when I try to compile a hello world go program [2], it fails with:

$ mipsel-linux-gnu-gccgo hello.go
hello.go:3:11: error: import file 'fmt' not found
 import "fmt"
           ^
hello.go:6:5: error: reference to undefined name 'fmt'
     fmt.Println("Hello, World")
     ^

Beeing a newbie, it seems to me that I also need to compile and install the libgo library (.gox and .a files?) for the MIPS architecture. None such files are present in the package I built.

So how do I do that? Would I also need a libc for libgo?
OpenWRT uses ulibc though.


[1] https://aur.archlinux.org/packages/cross-mipsel-linux-gnu-gcc/
[2] https://en.wikipedia.org/wiki/Go_%28programming_language%29#Hello_world

Ian Lance Taylor

unread,
Jul 13, 2013, 8:18:54 PM7/13/13
to Damjan Georgievski, golan...@googlegroups.com
On Tue, Jul 9, 2013 at 3:04 AM, Damjan Georgievski <gda...@gmail.com> wrote:
> I'd like to see how Go programs would work on the OpenWRT platform, so I've
> compiled a cross-compiling gcc 4.8.1 with Go enabled [1]. So now I have
> cross-mipsel-linux-gnu-binutils 2.23.2-1 and cross-mipsel-linux-gnu-gcc
> 4.8.1-1 installed.
>
> But when I try to compile a hello world go program [2], it fails with:
>
> $ mipsel-linux-gnu-gccgo hello.go
> hello.go:3:11: error: import file 'fmt' not found
> import "fmt"
> ^
> hello.go:6:5: error: reference to undefined name 'fmt'
> fmt.Println("Hello, World")
> ^
>
> Beeing a newbie, it seems to me that I also need to compile and install the
> libgo library (.gox and .a files?) for the MIPS architecture. None such
> files are present in the package I built.
>
> So how do I do that? Would I also need a libc for libgo?
> OpenWRT uses ulibc though.

Yes, you do need libgo in order to use gccgo. When you build gccgo in
the normal way, it will also build libgo. I'm not sure how you were
able to build gccgo without libgo.

Yes, libgo requires libc. I don't know whether it will work with
uClibc, though I don't know of any fundamental reason why it would
not.

Ian

minux

unread,
Jul 14, 2013, 1:12:52 PM7/14/13
to Ian Lance Taylor, Damjan Georgievski, golan...@googlegroups.com
last time i tried, uclibc lacked getcontext.
but other than that, gccgo works well with uclibc.

Damjan Georgievski

unread,
Jul 15, 2013, 4:51:16 AM7/15/13
to golan...@googlegroups.com, Damjan Georgievski

> So how do I do that? Would I also need a libc for libgo?
> OpenWRT uses ulibc though.

Yes, you do need libgo in order to use gccgo.  When you build gccgo in
the normal way, it will also build libgo.  I'm not sure how you were
able to build gccgo without libgo.

Yes, libgo requires libc.

Probably because I still didn't compile ulibc (I couldn't with out gcc) .
So I guess first I need gcc-mips, then ulibc-mips, and last gccgo+libgo



On Sunday, July 14, 2013 7:12:52 PM UTC+2, minux wrote:
last time i tried, uclibc lacked getcontext.
but other than that, gccgo works well with uclibc.

What does that mean? Do I need to patch something, or is it just a loss of some functionality?


--
damjan

Ian Lance Taylor

unread,
Jul 15, 2013, 12:25:36 PM7/15/13
to Damjan Georgievski, golan...@googlegroups.com
On Mon, Jul 15, 2013 at 1:51 AM, Damjan Georgievski <gda...@gmail.com> wrote:
>>
>> last time i tried, uclibc lacked getcontext.
>> but other than that, gccgo works well with uclibc.
>
>
> What does that mean? Do I need to patch something, or is it just a loss of
> some functionality?

The current implementation of libgo requires
getcontext/setcontext/makecontext. Without them you can't do
anything. Fortunately those functions, while processor dependent, are
small and easy to write--just look at the glibc versions for help.

At some point I would like libgo to include specific
processor-specific implementations of just the functionality it needs,
and only fall back to getcontext et. al. when there is no
processor-specific implementation in libgo. That is because
getcontext and setcontext do operations that libgo does not need,
namely save and restore signal masks. But I have not implemented
anything along those lines yet.

Ian

Damjan Georgievski

unread,
Jul 15, 2013, 12:33:19 PM7/15/13
to golan...@googlegroups.com

Thanks for the explanation. I was looking for something trivial, I'm sure I can't do the necessary work to implement this.
I'll keep watching for this in the future.

ste...@farestam.com

unread,
Oct 3, 2013, 4:49:33 AM10/3/13
to golan...@googlegroups.com

Hi Damjan,

Did you ever get this working? I'm trying to set up the toolchain myself and am seeing exactly the same error as you do.

Thanks,
Stefan

mathia...@gmail.com

unread,
Nov 1, 2013, 12:49:03 PM11/1/13
to golan...@googlegroups.com, ste...@farestam.com
For anyone finding this thread and running into this problem but with glibc instead, I was successful with glibc 2.15 and gcc 4.8.1 using crosstool-ng (though there was no shortage of other problems to solve on the way, besides this one). I was however unsuccessful on earlier attempts with an older glibc (don't remember the exact version) that seemed to lack {get,set,make}context, so that might be your problem.

I get a couple of different warnings when linking my Go applications that I haven't had time to hunt down yet, but the small test apps I've tried so far seem to run fine.

Best regards,
Mathias

ste...@farestam.com

unread,
Nov 15, 2013, 9:38:12 AM11/15/13
to golan...@googlegroups.com, ste...@farestam.com
And I solved this by downloading the openwrt toolchain (svn co svn://svn.openwrt.org/openwrt/trunk/) and then configuring it to use eglibc 2.17 and gcc 4.8.0. The toolchain takes some time to build, but the end result works fine. Only issue is that it produces dynnamically linked executables, so the only option (that I could find) to have them execute in a mips router was to create a custom chroot context and then execute using chroot. There's some headache involved in figuring out which libraries to copy and some further configuration work to make DNS resolution work, but the resulting code seems to work just fine.

Elie Zedeck RANDRIAMIANDRIRAY

unread,
Jan 27, 2014, 2:19:24 AM1/27/14
to golan...@googlegroups.com, ste...@farestam.com
I used crosstool-ng with the following settings, and it was pretty successful:
  • eglibc 2.18 - This will provide the make/get/setcontext() functions that is required for the goroutine's context switching
    • uClibc can also be used, but will require porting of these functions from glibc or elibc. eglibc is light-weight and is compatible with the full glibc, very handy in context where space is of utmost important (like in routers)
  • GCC 4.8.x Linaro - with Go (gccgo) enabled of course
Note that my router is using uClibc, which doesn't have the make/get/setcontext(), so I built the program with the eglibc statically linked with the generated binary.

If I remember correctly, I used the -static-libc flag to the cross-compiler:
# mips-gccgo -msoft-float test.go -o test -static-libc

The negative side, is that the generated binary is so big you'll have to use an external root if your flash space is very small (4MB) like mine; or may be, you could compress the binary to fit in the flash, and at runtime, extract it to /tmp/ and run from there.
Reply all
Reply to author
Forward
0 new messages