Preface
Gc (Go's most widely-used compiler) isn't available for GOOS=linux && GOARCH=sparc
(Gentoo SPARC) for now; what makes matters worse is that Gccgo (sys-devel/gcc[go]
)
is not working on Gentoo (it hangs in early initialization). Debian Ports comes to
the rescue, as although no Gc as well, their Gccgo (at least gccgo-6
; gccgo-7
panics
in early stages) is working. Yet Debian's SPARC port is on architecture sparc64
, which
means it'll run on a Gentoo kernel (UltraSPARC T2 requires a 64bit kernel), yet the
executables it creates won't run outside without some tricks. (Gentoo SPARC has 32bit userland)
EDIT: as of Feb 2, 2018, gccgo-7
works as well. It seems like they've fixed it. Kudos for
Debian team!
Set up Debian Ports environment
Install debootstrap:
emerge --ask --verbose dev-util/debootstrap
Make the debian root and create the chroot with debootstrap
:
mkdir -p /var/debian/
debootstrap --arch=sparc64 --variant=buildd --verbose sid /var/debian/ https://deb.debian.org/debian-ports
Download the required keychain package. Chroot into the new debian environemnt, install keychain, and install required packages:
cd /var/debian/root
wget http://deb.debian.org/debian-ports/pool/main/d/debian-ports-archive-keyring/debian-ports-archive-keyring_2018.01.05_all.deb
chroot /var/debian /bin/su
chsh -s /bin/bash
dpkg -i /root/debian-ports-archive-keyring_2018.01.05_all.deb
apt update
apt install gccgo-6
Symlink the required go tools, make the GOPATH, and set it upon entering the chroot:
for a in go{,fmt}; do ln -sf /usr/bin/$a-6 /usr/bin/$a; done
mkdir -p /root/go
echo "export GOPATH=/root/go" >> /root/.bashrc
Exit the chroot, enter it once again, and verify that everything's working:
exit
chroot /var/debian /bin/su
go env
Test the toolchain via a simple Hello, world!
:
cd
cat > helloworld.go << EOF
package main
import "fmt"
func main() {
fmt.Println("Hello, world!")
}
EOF
go run helloworld.go
go build helloworld.go
./helloworld
Set up Gentoo to use the executables from Debian chroot
Now that we can produce executables, we need to set up the Gentoo system to be able to use the executables from Debian chroot. Debian has 64bit libc:
root@hikari:~# ldd helloworld
libgo.so.9 => /usr/lib/sparc64-linux-gnu/libgo.so.9 (0xffff800100230000)
libm.so.6 => /lib/sparc64-linux-gnu/libm.so.6 (0xffff8001015ac000)
libgcc_s.so.1 => /lib/sparc64-linux-gnu/libgcc_s.so.1 (0xffff800101794000)
libc.so.6 => /lib/sparc64-linux-gnu/libc.so.6 (0xffff8001018a8000)
libpthread.so.0 => /lib/sparc64-linux-gnu/libpthread.so.0 (0xffff800101b18000)
/lib64/ld-linux.so.2 (0xffff800100000000)
And for gccgo-7
:
root@hikari:~# ldd helloworld
libgo.so.11 => /usr/lib/sparc64-linux-gnu/libgo.so.11 (0xffff800100230000)
libm.so.6 => /lib/sparc64-linux-gnu/libm.so.6 (0xffff800101b60000)
libgcc_s.so.1 => /lib/sparc64-linux-gnu/libgcc_s.so.1 (0xffff800101d44000)
libc.so.6 => /lib/sparc64-linux-gnu/libc.so.6 (0xffff800101e58000)
libz.so.1 => /lib/sparc64-linux-gnu/libz.so.1 (0xffff8001020c0000)
libpthread.so.0 => /lib/sparc64-linux-gnu/libpthread.so.0 (0xffff8001021dc000)
/lib64/ld-linux.so.2 (0xffff800100000000)
We need to copy those to the Gentoo host's /lib64
and add it to ld
's search paths.
mkdir -p /lib64
for a in /usr/lib/sparc64-linux-gnu/libgo.so.{9,11} /lib/sparc64-linux-gnu/{libm.so.6,libgcc_s.so.1,libc.so.6,libz.so.1,libpthread.so.0}; do cp -Lv /var/debian$a /lib64/$(basename $a); done
cp -v /var/debian/lib/sparc64-linux-gnu/ld-2.26.so /lib64/ld-linux.so.2
cp -Pv /var/debian/lib/sparc64-linux-gnu/libnss* /lib64 # needed for proper user / dns support
sed -i -e 's|/lib:/usr/lib|/lib:/lib64:/usr/lib|' /etc/env.d/00basic
env-update
Note: if you upgrade the debian chroot, watch closely if libc
and friends have been updated.
If so, remember to copy the libraries over to avoid possible breakage.
We can now check if the executable works outside the chroot:
cd /var/debian/root
ldd helloworld
./helloworld
If any libraries are missing, we need to copy it over (to /lib64
) and re-generate
ld.so.cache
with env-update
. From this point we're able to compile the Go source code in
the Debian chroot, and copy it over for use.
Extra setup for ease of use
Copying the executable outside the chroot outside every time is exhausting. The following setup will ease the process of compiling source and using the executable.
Set up fstab entries for the debian chroot, so that it will be ready for use right after
boot. Failing to mount system psuedo-filesystems (especially /proc
) will result in
mysterious errors with libbacktrace
.
# debian chroot mounts
/dev /var/debian/dev none defaults,rbind,rslave 0 0
/sys /var/debian/dev none defaults,rbind,rslave 0 0
/proc /var/debian/proc none defaults,rbind,rslave 0 0
# mount to expose the executables built to the system outside
/var/debian/root/go/bin /usr/local/go/bin none defaults,bind 0 0
The last entry exposes ${GOPATH}/bin
inside the debian chroot to the system
outside, so that we can add /usr/local/go/bin
to PATH
, and easily use them
outside (as we have set up appropriate libc
outside).
Add the /usr/local/go/bin
to PATH
:
echo "PATH=\"/usr/local/go/bin\"\nROOTPATH=\"/usr/local/go/bin\"" | sudo tee /etc/env.d/40debian-golang
env-update
And add the following alias to your shell config (.bashrc
or .zshrc
):
alias gobuild='sudo chroot /var/debian /bin/bash --login'
We can now issue gobuild
from Gentoo, go into the Debian chroot, issue
go get path/to/your/great/package
to install your binary, and then you can access them outside the chroot as well,
thanks to the bind mount and the PATH
settings.
Credits
The method to resolve the incompatiable libc libraries comes from lilydjwg, while the suggestion of installing the keychain package instead of importing raw keys comes from zhsj. Thanks.
Comment