Linux Cross Compilation
Contents |
[edit] Linux Cross Compilation
[edit] Introduction
This is an example how to cross compile the MySQL server, mainly from one Linux architecture to another. I.e. you build on one Linux system and produce binaries to be run on another Linux system with a different CPU.
The description is about 5.1, but will most likely also work for other versions.
[edit] Disclaimer
These notes might be incomplete and even create a server that is not functioning as it should. Always run the regression test to make sure the produced server is working properly.
[edit] Building a Cross Compiler
There are many ways to create a cross compiler, one being to use the crosstool package.
I used CrossTools (http://kegel.com/crosstool/) to create a cross gcc, and also build glibc for the target. Not sure if I did the optimal build, as this tool support various different kind of embedded targets.
What I did was to edit "crosstool-0.43/demo-powerpc-750.sh" to put things where I wanted them, and I also changed to use gcc 4.1.1. I also created a patch file to avoid a compile problem, "crosstool-0.43/patches/glibc-2.3.6/glibc-2.3.6-csu-makefile.patch", with the content
--- glibc-2.3.6/csu/Makefile.ORIG 2007-12-30 17:00:57.000000000 +0100
+++ glibc-2.3.6/csu/Makefile 2007-12-30 17:01:20.000000000 +0100
@@ -241,7 +241,7 @@
esac; \
files="$(all-Banner-files)"; \
if test -n "$$files"; then \
- echo "\"Available extensions:\\n\""; \
+ echo "\"Available extensions:\\\\n\""; \
sed -e '/^#/d' -e 's/^space:*/ /' \
-e 's/^\(.*\)$$/\"\1\\n\"/' $$files; \
fi) > $@T
This built fine, now I added to PATH the, in my case, directory
% cross_bin=/cross/compiler/path/gcc-4.1.1-glibc-2.3.6/powerpc-750-linux-gnu/bin % PATH=$PATH:$cross_bin % export PATH
[edit] Build the libncurses library
We need libncurses, I downloaded "ncurses-5.2.tar.gz", unpack, and do (with my paths replaced)
% cd ncurses-5.2 % host=powerpc-750-linux-gnu % prefix=/cross/compiler/path/gcc-4.1.1-glibc-2.3.6/powerpc-750-linux-gnu/powerpc-750-linux-gnu/usr
% CC=$host-gcc ./configure $host --target=$host --with-shared --prefix=$prefix \
--without-cxx-binding --without-progs
% make HOSTCC=gcc % make install
[edit] Edit the MySQL sources
Remove the following lines from "configure.in" (not used anyway)
# System characteristics case $SYSTEM_TYPE in *netware*) ;; *) AC_SYS_RESTARTABLE_SYSCALLS ;; esac
Also apply this bug fix in "sql/Makefile.am" (not 100% sure yet this is ok)
-BUILT_MAINT_SRC = sql_yacc.cc sql_yacc.h -BUILT_SOURCES = $(BUILT_MAINT_SRC) lex_hash.h link_sources +BUILT_MAINT_SRC = sql_yacc.cc sql_yacc.h lex_hash.h +BUILT_SOURCES = $(BUILT_MAINT_SRC) link_sources
[edit] Create a new source package
Independently if you are doing this from a BitKeeper repository or distributed sources, you want to create a new source package that contains some pregenerated files. This way the cross compilation is simplified, no executables that are part of the build itself have to be compiled, what they would generate is already in the package (no BUILD_CC or CC_FOR_BUILD support needed).
You run this to create the new source TAR
% BUILD/compile-dist % make dist
[edit] Set the environment
In my example, the environment would look like
% cross_bin=/cross/compiler/path/gcc-4.1.1-glibc-2.3.6/powerpc-750-linux-gnu/bin % host=powerpc-750-linux-gnu % CC=$host-gcc % CXX=$host-gcc % AR=$host-ar % RANLIB=$host-ranlib % CFLAGS="-O1 -fno-omit-frame-pointer" % CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti -O1 -fno-omit-frame-pointer" % PATH=/bin:/usr/bin:$cross_bin % export CC CXX AR RANLIB CFLAGS CXXFLAGS PATH
[edit] Unpack and configure
Unpack the newly created source TAR, and configure (just an example)
./configure \ --build=x86_64-unknown-linux-gnu \ --host=sparc-unknown-linux-gnu \ --prefix=/usr/local/mysql \ --disable-assembler \ --with-extra-charsets=complex \ --enable-thread-safe-client \ --with-big-tables \ --with-readline \ --with-mysqld-ldflags=-static \ --with-client-ldflags=-static \ --enable-local-infile
[edit] Edit settings
You need to tell the build what stack direction the target system uses
STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses
Edit "include/config.h", set a "1" or "-1" value to the line
#define STACK_DIRECTION
You can find out the stack direction on the target host, by compiling this code snippet using the cross compiler, and run it on the target host examining the exit code, if -1 or 1
#include <stdlib.h> \
int find_stack_direction ()
{
static char *addr = 0;
auto char dummy;
if (addr == 0)
{
addr = &dummy;
return find_stack_direction ();
}
else
return (&dummy > addr) ? 1 : -1;
}
int main ()
{
exit (find_stack_direction() < 0);
}
Note that if the target is 64 bits, you need to edit some more values
in "include/config.h" about pointer size, size of type "long" etc.
[edit] Build and pack
Build (with the same PATH setting)
% make_opts="pkgincludedir=/usr/local/mysql/include" % make_opts="$make_opts pkgdatadir=/usr/local/mysql/share" % make_opts="$make_opts pkgsuppdir=/usr/local/mysql/support-files" % make_opts="$make_opts mandir=/usr/local/mysql/man" % make_opts="$make_opts infodir=/usr/local/mysql/info" % make -j 4 $make_opts % scripts/make_binary_distribution
[edit] Random notes
I have been thinking about the building of libncurses, maybe it is better to copy the headers and libraries from the target system? It is an option at least, even the glibc even if that would be very messy to do. If building libncurses and linking with the shared one, I think maybe it is better to build with --prefix=/usr and use
% make install DESTDIR=<cross prefix>
to make sure the right rpath is compiled into the shared lib, else a "ldd mysql" on the target will show the cross path on the build host I think. Not a big deal maybe, but "wrong",