cross-compiling

The process of compiling some code for a different architecture and/or operating system than the compiler is running on.

Example:


(de). Following an advice by Peter Dalgaard at c.l.t I found it quite easy and painless to cross-compile tcl8.4b1 and tk8.4b1 on linux for w32.

The first step is Xmingwin installation.

cd into the win directory of the tcl8.4b1 source distribution.

Create a config.site and put this into it:

  CC=mingw32-gcc
  AR=mingw32-ar
  RANLIB=mingw32-ranlib
  RC=mingw32-windres

Run

  CONFIG_SITE=config.site ./configure

This runs without any problem for me.

Do

  make

It's a real 'noisy' compile. The vast majority of the output are repeated

  warning: passing arg 2 of `iswctype' with different width due to prototype

plus some warnings about redefinition of CHAR, SHORT and LONG and warnings about "initializing from incompatible pointer type".

At least for me make completes without error and produces a tclsh84.exe, some *.dlls and .a files.

Copy the .exe, *.dlls and *.a over to a MS box (I've used a w2k box).

Don't forget to copy the 8.4b1 tcl and tk script libraries to an appropriate place on your MS box. Without them, you get a error message at tclsh and wish start up about

  "Can't find a usable init.tcl in the following directories ..."

This error msg is very helpful, because it lists the directories, that are scanned for the library files. Choose one of them an put the script library in it.

Ready. Both tclsh84 and wish84 are working (at least for me). I sourced tkcon into the wish84 and it work smooth, without any problem.

Up to know, I haven't a clear result about loading binary extensions. I was able to load a VC++ 6.0 compiled tdom07.dll and the extension worked. On the other side, loading a tktable.dll (2.5) crashed the wish84.exe immediately.

It seems, that the cross-compiled tclsh84.exe works fairly reliable. At least, it runs the tcl bench suite without any problem:

   TCL_INTERP: 1:8.4b1 2:8.4b1
   STARTED 2002-07-20 23:42:00 (runbench.tcl v1.14)
   Benchmark 1:8.4b1 /local/devel/mwing-tcl/tclsh84.exe
   00:08:03 elapsed
   Benchmark 2:8.4b1 /Programme/Tcl/bin/tclsh84.exe
   00:07:15 elapsed

Both tclsh84.exe in this tclbench run are compiled using an identical source tree (tcl8.4b1-src.tar.gz).

The first tclsh84 (1) was cross-compiled on a linux box, with mingw32 cross-compiler based on gcc-2.95.3 and version 1.3 of the mingw-runtime and w32api, as described above and then copied to the test box, which runs w2k.

The second tclsh84 (2) was compiled on the test box with a VC++ 6.0 Enterprise Edition (i.e. optimization available).

It's an almost undoubted fact (at least outside gcc zealot circles) that VC++ generates more efficient executables than the gcc w32 versions. (Yes, gcc is optimized for portability, I know. Gcc is really great in that, also undoubted.) Therefore I expected the VC compiled tclsh to be faster.

I'm a bit pleasant surprised, that the VC compiled executable is 'only' around 10 percent faster over all, than the gcc cross-compiled executable. Seems, a cross-compiled tclsh84.exe should be fast enough for most applications.

MS notes: I suppose you can speed up the cross-compiled tclsh about 7% by choosing the compilation flags "-O2 -fomit-frame-pointer" instead of "-O". This is a fearless extrapolation from the measurements in Optimized compilation of tcl.

de: Yes, I could see a small speed up of the cross compiled tclsh, with the flags "-O2 -fomit-frame-pointer" but not 7 percent. It's around 3-4 percent. The tcl bench method of speed measurement (using wall clock, not process time) clearly has some random noise (running the tclbench suite several times with the same executables will give slightly different results). But after a few runs of the tclbench suite it seems to be a somewhat clear result, that the effect of the "-O2 -fomit-frame-pointer" doesn't makes that big of a difference for the cross-compiled tclsh, as you found it for the compilation on linux.

UKo 2003-03-04: Has anyone tried to use the new gcc-3.2? I've heard it is much better in code generation than its predecessors.de See MinGW versus VC++ 6.0.


Victor Wagner, among the Tcl'ers most experienced in cross-generation--for his MS-DOS port of Tcl, for example--makes the helpful point that, "if your both build and target platforms are Linux on different architectures, you might have some success using qemu to run test programs. QEMU is able to run PPC linux binaries on i386 and vice versa."


I don't see any useful advice here on cross-compiling to change architecture (that is, Linux->Linux, say from ix86 to PPC), which is what I need to do. I've cross-built lots of other packages. For example, I build Net-SNMP with something like:

  ./configure --target=powerpc-linux \
              --host=powerpc-linux \
              --build=i386-pc-linux \
              --with-cc=powerpc-linux-gcc \
              --with-ar=powerpc-linux-ar \
              ...

but the configure script I find in tcl/tcl8.4.9/unix doesn't seem to have any options for cc, ar, etc. This page has details of building on Linux for Wintel but nothing that seems to help me with Linux-to-Linux.

I've got it working, sort of. This is what I did:

  • Got the standard Tcl source distribution
  • In tcl/unix, did
  ./configure
  • Manually edited the Makefile. Here's the diff:
  --- Makefile  Fri May  6 08:48:33 2005
  +++ Makefile.ppc      Fri May  6 08:48:05 2005
  @@ -27,10 +27,10 @@
   # to the "configure" script.  The *dir vars are standard configure
   # substitutions that are based off prefix and exec_prefix.

  -prefix                       = /usr/local
  -exec_prefix          = /usr/local
  +prefix                       = /ppc/usr/local
  +exec_prefix          = ${prefix}
   bindir                       = ${exec_prefix}/bin
  -libdir                       = /usr/local/lib
  +libdir                       = /ppc/usr/local/lib
   includedir           = ${prefix}/include
   mandir                       = ${prefix}/man

  @@ -192,7 +192,7 @@
   # these definitions by hand.

   STLIB_LD             = ${AR} cr
  -SHLIB_LD             = gcc -pipe -shared
  +SHLIB_LD             = powerpc-linux-gcc -pipe -shared
   SHLIB_CFLAGS         = -fPIC
   SHLIB_LD_FLAGS               = 
   SHLIB_LD_LIBS                = ${LIBS}
  @@ -241,8 +241,8 @@
   COMPAT_OBJS          = 

   AC_FLAGS             =  -DPEEK_XCLOSEIM=1 -D_LARGEFILE64_SOURCE=1 -DTCL_WIDE_INT_TYPE=long\ long -DHAVE_STRUCT_STAT64=1 -DHAVE_OPEN64=1 -DHAVE_LSEEK64=1 -DHAVE_TYPE_OFF64_T=1 -DHAVE_GETCWD=1 -DHAVE_OPENDIR=1 -DHAVE_STRSTR=1 -DHAVE_STRTOL=1 -DHAVE_STRTOLL=1 -DHAVE_STRTOULL=1 -DHAVE_TMPNAM=1 -DHAVE_WAITPID=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_SYS_PARAM_H=1 -DUSE_TERMIOS=1 -DHAVE_SYS_TIME_H=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_TM_ZONE=1 -DHAVE_GMTIME_R=1 -DHAVE_LOCALTIME_R=1 -DHAVE_TM_GMTOFF=1 -DHAVE_TIMEZONE_VAR=1 -DHAVE_ST_BLKSIZE=1 -DSTDC_HEADERS=1 -DHAVE_SIGNED_CHAR=1 -DHAVE_LANGINFO=1 -DHAVE_SYS_IOCTL_H=1 
  -AR                   = ar
  -RANLIB                       = ranlib
  +AR                   = powerpc-linux-ar
  +RANLIB                       = powerpc-linux-ranlib
   SRC_DIR                      = .
   TOP_DIR                      = ./..
   GENERIC_DIR          = $(TOP_DIR)/generic
  @@ -255,7 +255,7 @@
   # Must be absolute to so the corresponding tcltest's tcl_library is absolute.
   TCL_BUILDTIME_LIBRARY        = /home/chrisn/tcl/tcl8.4.9/library

  -CC                   = gcc -pipe
  +CC                   = powerpc-linux-gcc -pipe
   #CC                  = purify -best-effort gcc -pipe -DPURIFY

   # Flags to be passed to installManPage to control whether the manpages
  • Did
  make
  make install
  • On my target system, I had to do ldconfig so tclsh8.4 would find shared libraries

Then tclsh8.4 works! It really does seem that there ought to be a way to tell configure to use cross-building tools. Maybe there is an I'm not sufficiently well versed in configure to figure it out. Is it something about CONFIG_SITE as vaguely referenced at the top of this page? I've seen the

   var=value command

syntax before but I think it's shell-specific and I have no idea what shell is being used there. -- CLN 2005-05-06


Crosscompile TCL 8.4.14 on i686 for powerpc:

 tar xzvf tcl8.4.14-src.tar.gz
 cd tcl8.4.14/unix
 export LDFLAGS="-L /opt/powerpc-unknown-linux-gnu/powerpc-unknown-linux-gnu/lib"
 export CPPFLAGS="-I /opt/powerpc-unknown-linux-gnu/powerpc-unknown-linux-gnu/include"
 export CFLAGS="-I /opt/powerpc-unknown-linux-gnu/powerpc-unknown-linux-gnu/include"
 export CC=powerpc-unknown-linux-gnu-gcc
 export ac_cv_func_strtod=yes
 export tcl_cv_strtod_buggy=1
 ./configure --build i686-linux --host powerpc-unknown-linux-gnu
 make

George Peter Staplin Dec 14, 2007 - Here's how I built Tcl with MinGW in Ubuntu Linux (using the default Ubuntu packages):

 $ cat gps_env.sh 
 export CC=i586-mingw32msvc-gcc
 export AR=i586-mingw32msvc-ar
 export RANLIB=i586-mingw32msvc-ranlib
 export RC=i586-mingw32msvc-windres
 ./configure --target=i586-mingw32msvc --host=i486-linux-gnu

 $ sh gps_env.sh
 $ make

Hint: use the output from yourgcc -dumpmachine for the --host and --target.


Cross-compiling Tcl packages