Thursday, May 14, 2015

gccgo gcc5.1.0 Cross compile for Sparc solaris 10 on Fedora20 X86_64

gcc5.1.0 Cross compile for Sparc solaris 10

The purpose of this procedure is to demonstrate the cross compilation of gcc5.1.0 on a Fedora 20 X86_64 host for Sparc Solaris 10. When I say cross compiling it means you will build the program on your host machine (linux X86_64) that will run on a Solaris Sparc X86_64 machine. This was mainly done to have latest version of the golang (1.4.2 at the time) compiler gccgo. The process is outlined below:

Setup the following enviornment variables:
export PREFIX=/opt/cross/
export SYSROOT=/opt/cross/sysroot/
export TARGET=sparc-sun-solaris2.10

PREFIX: we will install all the pre-requisites and gcc cross compiler into this directory

SYSROOT:  We will put all the required files from the target machine for which we are building gcc. This is the directory, the cross compiler will look into for header files and libraries. It acts as the root of the system we will compile the programs for.

TARGET: Is the architecture/platform we are targeting I mean the target on which the executables we will produce from cross compiling will execute. You can obtain the target from: gcc -dumpmachine

Create the required directories:
$ sudo mkdir $PREFIX
$ sudo mkdir $SYSROOT
$ sudo mkdir {$SYSROOT/usr,$SYSROOT/lib,$SYSROOT/usr/sfw,$SYSROOT/usr/local}

Step 1: Copy header and library files from the target machine:

$ sudo cd $SYSROOT
$ sudo rsync -a root@solaris_sparc_machine:/lib/ $SYSROOT/lib/
$ sudo rsync -a root@solaris_sparc_machine:/usr/lib $SYSROOT/usr/
$ sudo rsync -a root@solaris_sparc_machine:/usr/include $SYSROOT/usr/
$ sudo rsync -a root@solaris_sparc_machine:/usr/platform $SYSROOT/usr/
$ sudo rsync -a root@solaris_sparc_machine:/usr/local/lib $SYSROOT/usr/local/
$ sudo rsync -a root@solaris_sparc_machine:/usr/local/include $SYSROOT/usr/local/
$ sudo rsync -a root@solaris_sparc_machine:/usr/sfw/lib $SYSROOT/usr/sfw/
$ sudo rsync -a root@solaris_sparc_machine:/usr/sfw/include $SYSROOT/usr/sfw/

Step2: configure and install binutils from source

binutils is a collection of tools and utilities for creating and managing binary programs, object files, libraries etc. for instance, assembler, linker, ar (archive management tool)

Download the latest binutils from http://ftp.gnu.org/gnu/binutils/
untar  binutils:
$ tar -zxf binutils-2.25.tar.gz

build and install binutils:
$ mkdir build-binutils
$ cd build-binutils
$ sudo ../binutils-2.25/configure  -target=$TARGET --prefix=$PREFIX -with-sysroot=$SYSROOT -v
$ sudo make -j4
$ sudo make install

We are building binutils in a separate directory as it will not affect the untared directory if any errors are encountered during building. It will be easy to wipe build-binutils directory and start again.

Step3: Build and Install gcc5.1.0:

Download gcc from http://mirrors.concertpass.com/gcc/releases/
$ tar -zxf gcc-5.1.0.tar.gz

build and install gcc:
$ mkdir gcc-build
$ cd gcc-build
$ sudo ../gcc-5.1.0/configure --target=$TARGET --with-gnu-as --with-gnu-ld  --prefix=$PREFIX --with-sysroot=$SYSROOT --disable-libgcj --enable-languages=c,c++,go -v
$ sudo make -j6
$ sudo make install

Now you should have the gccgo compiler: $PREFIX/bin/sparc-sun-solaris2.10-gccgo  and other compilers, c & c++ under $PREFIX/bin

Create symlink gccgo:
$ cd $PREFIX/bin
$ ln -s /sparc-sun-solaris2.10-gccgo  gccgo

How to cross compile golang program for sparc solaris 10:
Assuming you have already got the gccgo cross compiler installed as described above. If you have already got the golang installed on your linux box the process is easy just pass the --compiler option to go binary during build and use --gccgoflags option to pass options to the gccgo compiler.

Add the $PREFIX/bin to your PATH:
$ export PATH=$PREFIX/bin:$PATH

Statically linking libgo using go:
$ go build --compiler gccgo --gccgoflags "-v -static-libgo -Wl,-dy -lnsl -lsocket -lrt" hello.go

Statically linking libgo using gccgo:
$ gccgo  -m64 -v -static-libgo -o hello hello.go -Wl,-dy -lnsl -lsocket -lrt

Note: for gcc-6.1 use:
$ go build --compiler gccgo --gccgoflags "-v -static-libgo -Wl,-dy -lnsl -lsocket -lrt -lsendfile" hello.go
$ gccgo  -m64 -v -static-libgo -o hello hello.go -Wl,-dy -lnsl -lsocket -lrt -lsendfile

copy the executable hello to your solaris machine and run it. It should work.

For dynamic linking using go:
$ go build --compiler gccgo  hello.go

For dynamic linking using gccgo:
$ gccgo -v  -o hello hello.go

To run the dynamically linked executable mount/copy the $PREFIX on your Solaris machine and set the LD_LIBRARY_PATH to include  $PREFIX/lib and $PREFIX/lib64. run $ ldd  hello to see all the dynamic libraries are found.

5 comments:

  1. Can this way be used to get a sparc binaries?

    ReplyDelete
    Replies
    1. You can compile a go program to work on a Sparc machine. If you want to build go on a sparc machine the process is same.

      Delete
  2. Hello,
    Could you please put somewhere the result of the compilation of gcc 5.1 for Spark solaris ? That would save me a lot of pain :)

    ReplyDelete
  3. Thanks for the nice post. I have followed your steps and started compiling binaries for SPARC. However, I noticed that the generated binaries leak memory in a very bad way. I am afraid, the issue I am facing makes the generated binaries unusable.

    ReplyDelete
  4. Hello, i followed your post. However i am struggling with this error. Any suggestions

    [george@tnpgeorge01 src]$ go build --compiler gccgo --gccgoflags "-v -static-libgo -Wl,-dy -lnsl -lsocket -lrt -lsendfile" hello.go
    package main
    imports fmt
    imports errors
    imports runtime
    imports runtime/internal/sys: cannot find package "runtime/internal/sys" in any of:
    /home/george/gcc-5.1.0/libgo/go/src/runtime/internal/sys (from $GOROOT)
    /opt/cross/bin/src/runtime/internal/sys (from $GOPATH)

    ReplyDelete