; -*- mode: text; fill-column: 72 -*- Cross-Compiling Mini-HOWTO ========================== This Mini-HOWTO (briefly :-) describes the steps to set up a cross compiling environment for Linux/68k on a PC also running Linux. On the PC, a Slackware 3.0 setup is assumed, but most things should apply to other distributions aswell. Even though this Mini-HOWTO only talks from i[45]86-linux and m68k-linux, all things described here should apply somehow similar to other hosts and targets. But then you're on your own with the details... Beside this document, you should also read the READMEs and INSTALL files that come with gcc and the GNU binutils. 1) Get Some Software -------------------- You need the sources for gcc and the GNU binutils. Things become a lot easier if support for the target m68k-linux is already included in their configuration. But, unfortunately, the binutils still lack this support. Fortunately, there is a patch to add it. (This patch should also come into the standard distribution of the binutils soon.) gcc contains m68k-linux support since version 2.7.1, so get a current version. The patch for binutils-2.6 can be found on ftp.uni-erlangen.de or its mirrors as /pub/Linux/LOCAL/680x0/ELF/binutils-2.6-linux.diff.gz. It applies cleanly to the unpacked source. Change to the binutils directory and type $ zcat ../binutils-2.6-linux.diff.gz | patch -p1 If you want to use the cross compiler only for compiling the Linux/68k kernel on the PC, you don't need any libraries (the kernel itself isn't linked to any library!), except from some include files regarding varargs. But if you already have a cross compiler, you maybe want to use it for other programs, too. Then you need the libraries on the PC (i.e. the compile host), too. But binaries are ok in this case, you don't need the sources. On the other side, if you want to compile only "ordinary" programs and no kernels, you still need the include/linux and include/asm-m68k subdirectories of the Linux/68k kernel sources on the compile host. 2) Assumptions -------------- We assume the current Slackware 3.0 filesystems and programs: gcc (probably 2.7.0) as system default compiler (probably ELF format) and binutils (probably 2.5.2) with files as follows: /usr/bin/gcc gcc-specific stuff under /usr/lib/gcc-lib and /usr/i486-linux All files under /usr/i486-linux are links to other files at default places, i.e: /usr/i486-linux/bin/* -> /usr/bin/* /usr/i486-linux/lib/* -> /usr/lib/* /usr/i486-linux/include -> /usr/include. Because we have to compile gcc and binutils anyway, this is your chance to update the system default compiler and binutils, too. Most binutils can be built for more architectures, so we save some disk space this way and have a consistent working environment for cross and native compiling. I don't care too much about a.out programs. I am able to let precompiled binaries run, but I can't think of any reason why I had to be able to produce them. On the other hand, it isn't too hard to include this format in the setup. This would end up in another two versions of gcc and include and lib hierarchies. I don't know why I should do that, but your mileage may vary... There is one major pitfall when you upgrade from binutils-2.xx to binutils-2.6: The new linker ld needs additional links for shared libraries to find them. If you don't have them, ld will only produce statically linked files being considerably larger. I know of no easy way to create these links (perhaps someone supplies a shell script? ;-)), so you have to create them manually: $ ln -s libxx.so.yy libxx.so for every shared lib (usually located in /lib, /usr/lib, and /usr/X11R6/lib), if these links don't exist already. We want to install the compiler system-wide, so we have to give a --prefix=/usr option to every configure script we run. (The default is usually /usr/local). All user visible files for cross compiling reside in directories /usr/, /usr/m68k-linux in our case. Below this directory, there are bin/, lib/, and include/ subdirectories with the obvious meaning. They contain binaries, libraries and header files needed for cross compiling to the respective target. In all following steps, i[345]86 means i386, i486 or i586, as applicable to your PC. In general, in the procedure below the same options should be given the same arguments. Otherwise, some inconsistency could arise, preventing you from using your compiler to compile fixed versions. So keep a backup of your current setup until everything works fine! 3) Prepare the Cross Binutils ----------------------------- Unpack the binutils-2.6 source under /usr/src (or somewhere else, that doesn't matter, but we assume it in the examples) and apply the patch (if you haven't done that already): $ cd /usr/src $ tar xvzf binutils-2.6.tar.gz $ cd binutils-2.6 $ patch -p1 <../binutils-2.6.diff Now the binutils have to be configured. The easiest way here is to have the same programs for native ix86 compiling and for cross compiling. In newer versions, the binutils support multiple targets in one binary, so this is possible: $ ./configure --host=i[345]86-linux --prefix=/usr \ --enable-target=i[345]86-linux,m68k-linux --enable-shared If you also want to compile for a.out format, you can add i[345]86-linuxaout and/or m68k-linuxaout to the --enable-target list. The next step is to compile and install the binutils: $ make CFLAGS=-O3 [ ... lots of output ... ] $ make install The installing process will fail when it tries to use the newly generated ranlib. To fix this, copy libbfd.so* and libopcodes.so* from their subdirs to /usr/lib with cp -a: $ cp -a lib/libbfd.so* lib/libopcodes.so* /usr/lib Now try again and installing should work: $ make install Now make a directory /usr/m68k-linux with subdirectories bin, lib, and include. Copy or link everything except gas and gasp from /usr/i[345]86-linux/bin into the appropriate directories: $ mkdir /usr/m68k-linux $ mkdir /usr/m68k-linux/bin $ mkdir /usr/m68k-linux/lib $ mkdir /usr/m68k-linux/include $ ln /usr/i[345]86-linux/bin/* /usr/m68k-linux/bin $ rm /usr/m68k-linux/bin/gas $ rm /usr/m68k-linux/bin/gasp Unfortunately, gas cannot (yet?) deal with multiple targets :-( So you'll need separate versions for each target, i.e. i[345]86-linux, m68k-linux, and maybe others. The above make run has built gas for the Intel target. So you need another one for m68k-linux. For this, go into the gas subdir of binutils and do a $ cd gas $ ./configure --prefix=/usr --host=i[345]86-linux --target=m68k-linux $ make CFLAGS=-O3 After that finished, copy the new binaries as.new and gasp.new to /usr/m68k-linux/bin, but without the trailing .new: $ cp as.new /usr/m68k-linux/bin/as $ cp gasp.new /usr/m68k-linux/bin/gasp $ cd .. Do _not_ try make install. It will overwrite your Intel-gas! Now you have your new binutils up and running for both i[345]86-linux and m68k-linux target system. They are used in the next step when actually building the compiler. 4) Compiling a Cross Compiler ----------------------------- In this step, you'll build the cross compiler proper. Maybe you also want to build a new native gcc for your Linux/Intel system, if your existing gcc there is an older version. Now is the chance, since you already have the sources at hand :-) But to our first goal... Obviously, you have to unpack the sources first: $ cd /usr/src $ tar xvzf gcc-2.7.2.tar.gz $ cd gcc-2.7.2 Since you already have gcc running on your host system (haven't you? :-), it is sufficient to only build a stage 3 compiler. (See gcc's INSTALL file for more information on this.) (Hint: use the 'make bootstrap' command and go for lunch ;-)). Install it and don't forget the 'make distclean' before the next step. $ ./configure --prefix=/usr --with-gnu-as --with-gnu-ld \ --host=i[345]86-linux --target=m68k-linux $ make CFLAGS=-O3 $ make install If you want to compile a new native gcc, do that by omitting the --target option. Maybe it's also clever to first build the new native compiler and install it, and then go to compile the cross-compiler. It might result in slightly better/faster/... code there. (For the nasty guys: After that, go back one step and recompile the binutils, then the compiler, and then the binutils again. stage5 in the gcc Makefile ;-)) 5) Preparing the Libraries and Header Files ------------------------------------------- First, read under 2) whether you need libraries and header files at all. Abstract: You don't need libraries if you only want to cross-compile Linux/68k kernels. All you need then are the varargs headers, which are compiler specific anyways and reside under /usr/lib/gcc-lib// /include. Ok, let's assume you want to install the libraries. Most probably you also have a Linux/68k machine with a compiler setup. Then just copy all library files in /lib and /usr/lib, and all header files from /usr/include there to the appropriate directories under /usr/m68k-linux. Remember that include/asm and include/linux are just links to the kernel sources, so set them accordingly. If you don't want to compile kernels, you can put the real directories in here instead of links. If you don't have such a machine, or don't have a development environment there, or have some other reason not to use the files there, just get the binaries of the libraries from some FTP server, and unpack them where they should go. Also get the include files and treat them the same. (Real hackers would now use the cross-compiler to compile cross-libraries themselves ;-)) Note: With the cross-libs, no distinction is made between /lib and /usr/lib. All libraries go into /usr/m68k-linux/lib. Be sure that for every library there is a symlink from libxxx.so to libxxx.so.. The 2.6 version of ld needs this link to find the libraries. If these links are not present, all programs will be linked statically! Note: For a.out output format, you can omit the the *.so* shared library images. These will never be used on the host system. But these files are needed with ELF, because there are no *.sa stub libs anymore, and the linker has to determine some infos about the libs. Note 2: ld.so and/or ld-linux.so are also not needed on the host system. Put your m68k header files in /usr/m68k-linux/include. (In a later version, when m68k has been integrated into the main kernel source tree, you may be able to use the ones you have.) If you have a Linux/68k kernel source on the PC, make symlinks from /usr/m68k-linux/include/linux and /usr/m68k-linux/include/asm to the corresponding directories in the kernel source. (And keep the links up-to-date, if you update the kernel :-) If you don't have the kernel sources on the host anyway, you need to get these header files from the kernel source and copy them into /usr/m68k-linux/include/{linux,asm}. There is an ugly bug with the installed cross-compiler: The configure script can't determine which floating point format to use. As a result, /usr/lib/gcc-lib/m68k-linux/2.7.2/include/float.h contains nothing but an #error directive. Put your own one from an existing m68k-linux native compiler in here. 6) Working with the cross compiler ---------------------------------- Your cross compiler is ready to use now! Just calling 'gcc' executes the standard native compiler for the Intel system, and 'gcc -b m68k-linux' does cross compiling. Alternatively, you can call the cross compiler as /usr/m68k-linux/bin/gcc. The 'gcc -b m68k-linux' solution may have one drawback: It doesn't work right if native and cross compiler have different versions. The compiler driver 'gcc' always calls a compiler with the same version itself has. Ok, you can change this with the -V option, but it's annoying to type that with every compiler call. Another standard solution, and in my eyes the most convenient one, is to make symlinks to the cross binaries in one of the usual binaries directories (most probably /usr/bin). To avoid name conflicts with native tools, the target names is prefixed: $ ln -s /usr/m68k-linux/bin/gcc /usr/bin/m68k-linux-gcc $ ln -s /usr/m68k-linux/bin/as /usr/bin/m68k-linux-as $ ln -s /usr/m68k-linux/bin/ld /usr/bin/m68k-linux-ld $ ... After that, you can call the compiler and the tools without typing the path. If you have a good shell, this becomes even easier by using the command name completion: Just type "m6", and "8k-linux-" will be appended by the shell automagically. You only need to enter the name of the tool itself then, which you'd have to do anyway... Now you can try to build a kernel. If something doesn't work, you most probably want to look at arch/m68k/Makefile. This is the place where some paths and options are set for cross-compiling. On a P75, the whole building process takes about 2...3 hours. The only big pitfall is to make the additional link for ld-2.6. Joerg & Roman