20100404

My first port to the Ben NanoNote: gnugo

Since I bought the Ben NanoNote, I thought I needed to port something to it, as the biggest point with the NanoNote is developing to it, as its wiki says.

David Reyes, from Tuxbrain did a great work by porting gnuchess to the Nano and documenting it in his blog.

Of course, I want to port big things, but I'm not a great Linux guy, just average, so this tutorial makes a great starting point. I first tried to port gforth... But cross-compiling a compiler like gforth is really painful. I'll give it more tries, but it will take a really long time. For now, I'll show you how I ported gnugo to the NanoNote.

With respect to usability, the small screen in the Nano does not allow us to play a full 19x19 game (not in a way I'm aware of), but it can play 9x9 as you can see in the picture I posted.

Okey, now for the how-to for porting. For the first steps I just copied David's tutorial, as it covers everything you have to do, and is exactly the way I did it.

Setting up the developing framework

This are Debian/Ubuntu instructions to ensure that we have everything needed for cross-compilation. To install everything needed, run the following in a console
sudo apt-get install gcc g++ binutils patch bzip2 flex bison make gettext unzip libz-dev libc6 ncurses-dev subversion libxml-simple-perl gawk git-core
Now we create a folder (in our home directory, for instance) where we will keep all OpenWRT stuff and the framework from the git repository qi-hardware has set up.
mkdir openwrt
cd openwrt
git clone git://projects.qi-hardware.com/openwrt-xburst.git
cd openwrt-xburst
git fetch origin
git checkout --track -b xburst origin/xburst
make menuconfig
Now we will see a graphical menu for adding packages, and compiling a whole Linux image. It is similar to the Linux kernel configuration menu (in graphical mode). It has a lot of configuration options. Here we can select which packages to compile, which to generate as modules and so on. We have to select as Target System Ingenic Xburst, and Qi BenNanoNote as Target Profile (it may auto-select it). Now exit and save configuration changes, and run make to get a basic kernel and the toolchain.

Now, start the porting process.

Porting

Create a directory where we will keep all our porting applications:
cd ..
mkdir ports
mkdir ports/games
mkdir ports/games/gnugo
Fire your favourite text editor and create a file named Makefile in the recently created gnugo directory.

In it we have to copy the following. BEWARE! Between define and endef you have to add tabs, real tabs, not four spaces! If you don't change it, make will complain about missing separators.
# Copyright (C) 2008 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
#

include $(TOPDIR)/rules.mk
## Package name
PKG_NAME:=gnugo
## Package version we need (to match our download source)
PKG_VERSION:=3.8
## Release version (don't really needed, just for completeness)
PKG_RELEASE:=3
## Name of the file we will download, with the previous package name definitions
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
## Url with the PKG_SOURCE file
PKG_SOURCE_URL:=http://ftp.gnu.org/gnu/gnugo/
## Program to uncompress the sources
PKG_CAT:=zcat

include $(INCLUDE_DIR)/package.mk
# Definition of the package, for adding to menuconfig and creating the ipkg.
define Package/gnugo
TITLE:=Go GNU from FSF
SECTION:=games
CATEGORY:=Games
URL:=http://www.gnu.org/software/gnugo
endef
# Directory where the sources will be uncompiled and built BUILD_DIR
# is an env variable from the OpenWrt toolchain, you don't need to set
# it.
PKG_BUILD_DIR:=$(BUILD_DIR)/gnugo-$(PKG_VERSION)
# Long description of the package
define Package/gnugo/description
GNU Go is a free program that plays the game of Go. GNU Go has played thousands of games on the NNGS Go server. GNU Go is now also playing regularly on the Legend Go Server in Taiwan, on the WING server in Japan, and many volunteers run GNU Go clients on KGS. GNU Go has established itself as the leading non-commercial go program in the recent tournaments that it has taken part in.
endef
# If ./configure does not need any options, leave it as follows
define Package/gnugo/Build/Configure
$(call Build/Configure/Default)
endef
# Where will be copied the binaries and libraries after installation.
# Gnugo creates the binary executable in the interface directory.
define Package/gnugo/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/interface/gnugo $(1)/usr/sbin/
endef
# Final step for bulding the package
$(eval $(call BuildPackage,gnugo))
Now we need to tell OpenWRT we have new packages. To do so, go the trunk directory and run
cp feeds.conf.default feeds.conf
And add this line to the end of the file feeds.conf:
src-link ports route/to/your/ports/dir
and update the feeds:
./scripts/feeds update -a
./scripts/feeds install -a
Good, almost ready to go. What is the main problem for cross-compiling gnugo? Gnugo uses intermediate programs that process information and generate intermediate code, that is then compiled. And these intermediate programs can not be created by a cross-compiler: they have to be created for the host architecture.

My take on it was to download gnugo's sources, ./configure and make gnugo. Then use the generated intermediate files to generate the target files. And it worked!

Thus, now create a directory ~/testing-gnugo/ where you download gnugo's tar.gz sources, and uncompress it. Copy that directory into gnugo-3.8-mod and gnugo-3.8-old. And do the ./configure make stuff in the original gnugo-3.8. You will have some files in gnugo-3.8/patterns named mkpat, joseki, mkeyes and a few more. These are the key files!

Patching gnugo's makefile

We need to make a patch for gnugo to compile. First, create a patches directory in ports/games/gnugo/. Now, open your favourite text editor and open gnugo-3.8-mod/patterns/Makefile.in

You need to change all instances to ./joseki, ./mkpat, ./mkeyes, ./uncompress_fuseki, ./mkmcpat to use the ones in the gnugo-3.8/patterns directory you got earlier.

After you are done, go to the testing-gnugo directory and create the patch with the following instruction

diff -crB gnugo-3.8-old/ gnugo-3.8-mod/ > 001_static_definition.patch

and copy the 001_static_definition.patch to the patches directory you have just created. The number serves to order patches that have to be applied sequentally.

Go to the trunk directory, make menuconfig and go to the Games section. Select gnugo with "M" to generate a separate package, exit and save. Now
make package/gnugo/compile V=99
If everything works correctly, there won't be any errors and you can end the process with
make package/gnugo/install V=99
If there was some error, it was probably due some missing replace in the Makefile. Check what change is missing and correct it.

Now you can transfer (with the Ethernet via USB connection) the file in trunk/bin/xburst/packages, named gnugo-3.8-3-xburst.ipk to the NanoNote, where you can install by going to the directory where you have copied the ipk file and
opkg install gnugo-3.8-3-xburst.ipk
It may complain about some missing packages, but it is a Qi's distribution problem, not a fault from the freshly made package.

Related posts:
Unpacking my Ben NanoNote
Another Ben Nanonote port: pmars
Nanonote ports: Yacas, 4th (forth compiler and interpreter)
Gcal: the ultra-powerful command line GNU calendar
Written by Ruben Berenguel