Difference between revisions of "Cross-Compiling Under Linux"

From WxWiki
Jump to navigation Jump to search
m (typo: < and > in the code changed to < and >)
(20 intermediate revisions by 16 users not shown)
Line 1: Line 1:
= Cross-compiling under Linux =
+
= Building for i386 on an x86_64 machine =
 +
''Reminder:'' If when compiling from source you decide you'd like to recompile with a different set of options, or stop the build in order to change some of the options you've selected, you ''must'' first run `make distclean` (`make clean` only removes object files) in order to remove generated configuration files before you run the configure script again with your new options.  If you accidentally stop the build (by hitting ctrl-c or something) and do not wish to change any of the options, you can safely restart the build by simply typing the `make` command and it will continue right where it left off.
 +
 
 +
%debian
 +
if ./configure complains about not being able to find gtk-config, install the &#39;libgtk2.0-dev&#39; package
 +
%%
 +
 
 +
If the compile fails with the error &quot;had to relocate PCH&quot;, try adding &quot;--disable-precomp-headers&#39; to your ./configure line.
 +
 
 +
You can create windows binaries without even booting to Windows! see [[Cross-Compiling Under Linux]].
 +
 
 +
See also this page about [[Build System Management]].
 +
 
 +
You may need to build 32-bit apps on an x86_64 Linux box (Suse or RHEL WS3 which is what I have).
 +
On my box at least, the 32-bit gtk libs aren&#39;t installed, so I opted to build the plain X11 version,
 +
but the config below should work for either one.
 +
 
 +
Configure like this:
 +
  mkdir build_ia32
 +
  cd build_ia32
 +
  ../configure CC=&#39;gcc -m32&#39; CXX=&#39;g++ -m32&#39; --x-libraries=/usr/X11R6/lib ...options...
 +
  make
 +
 
 +
On RHEL WS 3, there are some missing lib symlinks in /usr/lib, e.g. no libX11.so (should be a symlink to libX11.so.X.Y).  You&#39;ll have to make those manually.  They should be pretty obvious config or build failures.
 +
 
 +
Also, the configure script tries to search in /usr/lib64 and /usr/X11R6/lib64; remove those from SEARCH_LIBS near the top of the configure script (not doing this would make it try to link with e.g. -lXinerama, which exists but only in the 64 bit world.)
 +
 
 +
= Cross-compiling under Linux for MS Windows =
  
 
* [[Install The Mingw Cross-Compiler]].
 
* [[Install The Mingw Cross-Compiler]].
 
* Compile wxWidgets
 
* Compile wxWidgets
 
** Download wxWidgets source
 
** Download wxWidgets source
** Compile with  ./configure --prefix=/usr/local/i386-mingw32 --host=i386-mingw32 --target=i386-mingw32 --with-msw ''--your_optional_switches''
+
** Compile with  ./configure --prefix=/usr/local/i586-mingw32 --host=i586-mingw32msvc --build=i686-linux ''--your_optional_switches''
 
     make
 
     make
 
     make install
 
     make install
 +
 +
Host string differs depending on mingw installations, you should check your mingw cross compiler for the exact value. Build option can also be different if you're not using Linux on x86, of course. For example, if you use mingw32 from Debian or Ubuntu packages under Linux on x86-64 architecture the command would be:
 +
./configure --prefix=/usr/local/i586-mingw32msvc --host=i586-mingw32msvc --build=x86_64-linux ''--your_optional_switches''
 +
 +
You may use 'checkinstall make install' instead of 'make install' in order to create a package and allow clean removal of the binaries.
 +
  
 
'''See also:'''
 
'''See also:'''
 
* Embedding icons in your cross-compiled binary: [[Cross-Compiling Windows Resources]]
 
* Embedding icons in your cross-compiled binary: [[Cross-Compiling Windows Resources]]
 
* Embedding other files: [[Embedding PNG Images]]
 
* Embedding other files: [[Embedding PNG Images]]
 +
* Several tips, tricks and workarounds as well as Eclipse configuration: [[wxWindows application compile (for Linux) and cross-compile (for Windows) under Linux/Eclipse/CDT]]
 
* [http://www-106.ibm.com/developerworks/linux/library/l-sc10.html?ca=dgr-lnxw02Xmingwin IBM DeveloperWorks article]
 
* [http://www-106.ibm.com/developerworks/linux/library/l-sc10.html?ca=dgr-lnxw02Xmingwin IBM DeveloperWorks article]
 
* [http://narnia.dnsalias.org/rlsavon/cross_compiling.php Cross compiling RLS AVON with MinGW on Linux] (simple instructions for installing environment, compiling wxWidgets, and compiling an certain wxWidgets application)
 
* [http://narnia.dnsalias.org/rlsavon/cross_compiling.php Cross compiling RLS AVON with MinGW on Linux] (simple instructions for installing environment, compiling wxWidgets, and compiling an certain wxWidgets application)
Line 16: Line 50:
 
'''Note:''' The SDL scripts and these directions cannot be mixed.
 
'''Note:''' The SDL scripts and these directions cannot be mixed.
 
'''Note:''' By disabling threads (with --disable-threads), you can avoid a dependency on the ming dll
 
'''Note:''' By disabling threads (with --disable-threads), you can avoid a dependency on the ming dll
 
=== Some more details for Debian folks ===
 
 
After apt-getting the three packages mingw32, mingw32-binutils and mingw32-runtime from "unstable" as well as the wxWindows source (took the "2.6.2 all ports combined", but MSW should be enough), I found out that I had to set a lot of environment variables in order for configure to use the mingw32 executables:
 
<pre>
 
export CC=i586-mingw32msvc-gcc
 
export CXX=i586-mingw32msvc-g++
 
export LD=i586-mingw32msvc-ld
 
export AR=i586-mingw32msvc-ar
 
export AS=i586-mingw32msvc-as
 
export NM=i586-mingw32msvc-nm
 
export STRIP=i586-mingw32msvc-strip
 
export RANLIB=i586-mingw32msvc-ranlib
 
export DLLTOOL=i586-mingw32msvc-dlltool
 
export OBJDUMP=i586-mingw32msvc-objdump
 
export RESCOMP=i586-mingw32msvc-windres
 
export CFLAGS=
 
</pre>
 
If you save that in a file, say, don't forget that you shouldn't ''execute'', but ''source'' it! Then
 
<pre>
 
./configure --prefix=/usr/local/i586-mingw32 --host=i586-mingw32msvc --target=i586-mingw32msvc \
 
      --with-msw [--your_optional_switches]
 
make
 
make install</pre>
 
(or <tt>sudo make install</tt>, depending what rights you have on <tt>/usr/local/i586-mingw32</tt>).
 
 
Your wxMSW libraries will be created in the directory you specified with <tt>--prefix</tt>, here it's <tt>/usr/local/i586-mingw32</tt>
 
  
 
== Example usage ==
 
== Example usage ==
  
Once installed, save the following file as winhello.c (stolen from [http://landonf.bikemonkey.org/code/win32/MinGW.20041207231336.1583.sulu.html Installing and Using the MinGW Cross-Compiler on Mac OS X]:<br>
+
Once installed, save the following file as winhello.c (stolen from [http://landonf.bikemonkey.org/code/win32/MinGW.20041207231336.1583.sulu.html Installing and Using the MinGW Cross-Compiler on Mac OS X]):<br>
  
 
<pre>
 
<pre>
Line 54: Line 61:
 
  */
 
  */
  
#include <windows.h>
+
#include &lt;windows.h&gt;
 
int main(int argc, char *argv[])
 
int main(int argc, char *argv[])
 
{
 
{
Line 64: Line 71:
 
To build the example, execute the following command:  
 
To build the example, execute the following command:  
 
<pre> $ i386-mingw32-gcc winhello.c -o winhello.exe</pre>
 
<pre> $ i386-mingw32-gcc winhello.c -o winhello.exe</pre>
and run it for example with wine   wine winhello.exe .
+
and run it, for example, with wine:  '''wine winhello.exe'''
  
 
== Contrib libraries ==
 
== Contrib libraries ==
Line 73: Line 80:
  
 
You might need these flags when compiling:
 
You might need these flags when compiling:
<pre>-Wl,--subsystem,windows -mwindows -DWINVER=0x0400 -D__WIN95__ -D__GNUWIN32__ -DSTRICT -DHAVE_W32API_H -D__WXMSW__ -D__WINDOWS__</pre>
+
<pre>-Wl,--subsystem,windows -mwindows \
 +
-DWINVER=0x0400 -D__WIN95__ -D__GNUWIN32__ \
 +
-DSTRICT -DHAVE_W32API_H -D__WXMSW__ -D__WINDOWS__</pre>
 
And these while linking:
 
And these while linking:
<pre>-lregex -lpng -ljpeg -lzlib -ltiff -lstdc++ -lgcc -lodbc32 -lwsock32 -lwinspool -lwinmm -lshell32 -lcomctl32 -lctl3d32 -lodbc32 -ladvapi32 -lodbc32 -lwsock32 -lopengl32 -lglu32 -lole32 -loleaut32 -luuid</pre>
+
<pre>-lregex -lpng -ljpeg -lzlib -ltiff -lstdc++ -lgcc -lodbc32 -lwsock32 -lwinspool -lwinmm -lshell32 \
 +
-lcomctl32 -lctl3d32 -lodbc32 -ladvapi32 -lodbc32 -lwsock32 -lopengl32 -lglu32 -lole32 -loleaut32 \
 +
-luuid</pre>
  
 
== environment variables ==
 
== environment variables ==
 +
 +
VZ: Note that this is unnecessary when using autoconf cross-compilation support.
  
 
In order to use the cross-compiler tools you need to replace the normal tools in makefiles. This is easier to do just exporting some environment variables before running ''configure''/''make'':
 
In order to use the cross-compiler tools you need to replace the normal tools in makefiles. This is easier to do just exporting some environment variables before running ''configure''/''make'':
Line 92: Line 105:
 
   export OBJDUMP=i586-mingw32msvc-objdump
 
   export OBJDUMP=i586-mingw32msvc-objdump
 
   export RESCOMP=i586-mingw32msvc-windres
 
   export RESCOMP=i586-mingw32msvc-windres
 +
  export WINDRES=i586-mingw32msvc-windres
  
 
== SDL&#39;s Script ==
 
== SDL&#39;s Script ==
Line 109: Line 123:
 
Run cross-configure.sh and cross-make.sh and you should be done. :-)
 
Run cross-configure.sh and cross-make.sh and you should be done. :-)
  
== Autoconf supports cross-compilation natively ==
+
== Note about WINE ==
 
 
If your cross-suite is i586-mingw32msvc-{gcc,g++,ld,...}, just do
 
../configure --with-msw --target=i586-mingw32msvc --host=i586-mingw32msvc --build=i386-linux and all necessary tools will be prefixed automatically.
 
  
ATTENTION: Turn off binfmt support before running configure (Debian: /etc/init.d/binfmt-support stop), which invokes wine for .exe files; otherwise configure will think it does NOT use a cross-compiler.
+
Make sure to turn off binfmt support before running configure (Debian: /etc/init.d/binfmt-support stop), which invokes wine for .exe files; otherwise configure will think it does NOT use a cross-compiler.
  
 
== Autoconf/Automake unit testing suites ==
 
== Autoconf/Automake unit testing suites ==
Line 141: Line 152:
  
 
Where dir is the path and tst is the test name (remember that EXEEXT).  That&#39;s it:  wine will return the exit code of your running binary.  You can also put a special shell or other token in there, but that exceeds the focus of this documentation.  This assumed automake-1.9 and autoconf-2.57 but I&#39;m fairly certain it works in earlier versions of both (uncertain about autoconf-2.13 style).
 
Where dir is the path and tst is the test name (remember that EXEEXT).  That&#39;s it:  wine will return the exit code of your running binary.  You can also put a special shell or other token in there, but that exceeds the focus of this documentation.  This assumed automake-1.9 and autoconf-2.57 but I&#39;m fairly certain it works in earlier versions of both (uncertain about autoconf-2.13 style).
 +
 +
 +
== Testing the created executables ==
 +
 +
To test your mingw32 installation with a sample ''not'' using wxWidgets, look above ("Example usage").
 +
 +
To test your mingw32 installation with a real wxWidgets example, take minimal.cpp from the official examples. Fortunately, I didn't have to fiddle around with the flags myself, I use <tt>wx-config</tt> for that - not the system-wide one, but the one compiled with the cross-Windows libraries below <tt>/usr/local/i586-mingw32</tt>!
 +
 +
<pre>
 +
i586-mingw32msvc-g++ -c -o minimal.o minimal.cpp \
 +
  `/usr/local/i586-mingw32/bin/wx-config --cxxflags`
 +
i586-mingw32msvc-g++ -o minimal.exe minimal.o \
 +
  `/usr/local/i586-mingw32/bin/wx-config --libs`
 +
</pre>
 +
 +
Attention, there are are '''two caveats''' here that could cost you lots of time (it did cost me lots of time, hope I'll save yours ;-)
 +
 +
* When compiling, be sure to include the <tt>-c</tt> option. <tt>-o</tt> with an <tt>.o</tt> object file isn't enough, mingw32 will try to link!
 +
* When linking, be sure to include '''first''' your object files and '''then''' the libraries (given by <tt>wx-config</tt>). When compiling, the order isn't too important, but if you exchange libraries and object files at the linking stage, you'll get lots of undefined references. The reason is that a linker processes the libraries in order of their appearance (see documentation of "-l" at http://sourceware.org/binutils/docs/ld/Options.html).
 +
 +
Finally, when executing your program with wine, qemu (works great!) or even on a real Windows box, don't forget that even if you linked everything statically, you'll also need <tt>mingwm10.dll</tt> in addition to your executable. Put in in the same directory and execute the binary from there, and everything works. I found mingwm10.dll</tt> gzipped in <tt>/usr/share/doc/mingw32-runtime/</tt>

Revision as of 18:38, 7 December 2011

Building for i386 on an x86_64 machine

Reminder: If when compiling from source you decide you'd like to recompile with a different set of options, or stop the build in order to change some of the options you've selected, you must first run `make distclean` (`make clean` only removes object files) in order to remove generated configuration files before you run the configure script again with your new options. If you accidentally stop the build (by hitting ctrl-c or something) and do not wish to change any of the options, you can safely restart the build by simply typing the `make` command and it will continue right where it left off.

%debian if ./configure complains about not being able to find gtk-config, install the 'libgtk2.0-dev' package %%

If the compile fails with the error "had to relocate PCH", try adding "--disable-precomp-headers' to your ./configure line.

You can create windows binaries without even booting to Windows! see Cross-Compiling Under Linux.

See also this page about Build System Management.

You may need to build 32-bit apps on an x86_64 Linux box (Suse or RHEL WS3 which is what I have). On my box at least, the 32-bit gtk libs aren't installed, so I opted to build the plain X11 version, but the config below should work for either one.

Configure like this:

 mkdir build_ia32
 cd build_ia32
 ../configure CC='gcc -m32' CXX='g++ -m32' --x-libraries=/usr/X11R6/lib ...options...
 make

On RHEL WS 3, there are some missing lib symlinks in /usr/lib, e.g. no libX11.so (should be a symlink to libX11.so.X.Y). You'll have to make those manually. They should be pretty obvious config or build failures.

Also, the configure script tries to search in /usr/lib64 and /usr/X11R6/lib64; remove those from SEARCH_LIBS near the top of the configure script (not doing this would make it try to link with e.g. -lXinerama, which exists but only in the 64 bit world.)

Cross-compiling under Linux for MS Windows

  • Install The Mingw Cross-Compiler.
  • Compile wxWidgets
    • Download wxWidgets source
    • Compile with ./configure --prefix=/usr/local/i586-mingw32 --host=i586-mingw32msvc --build=i686-linux --your_optional_switches
    make
    make install

Host string differs depending on mingw installations, you should check your mingw cross compiler for the exact value. Build option can also be different if you're not using Linux on x86, of course. For example, if you use mingw32 from Debian or Ubuntu packages under Linux on x86-64 architecture the command would be: ./configure --prefix=/usr/local/i586-mingw32msvc --host=i586-mingw32msvc --build=x86_64-linux --your_optional_switches

You may use 'checkinstall make install' instead of 'make install' in order to create a package and allow clean removal of the binaries.


See also:

Note: The SDL scripts and these directions cannot be mixed. Note: By disabling threads (with --disable-threads), you can avoid a dependency on the ming dll

Example usage

Once installed, save the following file as winhello.c (stolen from Installing and Using the MinGW Cross-Compiler on Mac OS X):

/*
 * Hello, World for Win32
 * gcc winhello.c -o winhello.exe
 */

#include <windows.h>
int main(int argc, char *argv[])
{
	MessageBox(NULL, "Hello, world!", "Hello, world!", MB_OK);
	return 0;
}

To build the example, execute the following command:

 $ i386-mingw32-gcc winhello.c -o winhello.exe

and run it, for example, with wine: wine winhello.exe

Contrib libraries

Couldn't compile the contrib directory with the wxMSW 2.4.2 sources, use the latest cvs.

Flags

You might need these flags when compiling:

-Wl,--subsystem,windows -mwindows \
-DWINVER=0x0400 -D__WIN95__ -D__GNUWIN32__ \
-DSTRICT -DHAVE_W32API_H -D__WXMSW__ -D__WINDOWS__

And these while linking:

-lregex -lpng -ljpeg -lzlib -ltiff -lstdc++ -lgcc -lodbc32 -lwsock32 -lwinspool -lwinmm -lshell32 \
-lcomctl32 -lctl3d32 -lodbc32 -ladvapi32 -lodbc32 -lwsock32 -lopengl32 -lglu32 -lole32 -loleaut32 \
-luuid

environment variables

VZ: Note that this is unnecessary when using autoconf cross-compilation support.

In order to use the cross-compiler tools you need to replace the normal tools in makefiles. This is easier to do just exporting some environment variables before running configure/make:

  export CC=i586-mingw32msvc-gcc
  export CXX=i586-mingw32msvc-c++
  export LD=i586-mingw32msvc-ld
  export AR=i586-mingw32msvc-ar
  export AS=i586-mingw32msvc-as
  export NM=i586-mingw32msvc-nm
  export STRIP=i586-mingw32msvc-strip
  export RANLIB=i586-mingw32msvc-ranlib
  export DLLTOOL=i586-mingw32msvc-dlltool
  export OBJDUMP=i586-mingw32msvc-objdump
  export RESCOMP=i586-mingw32msvc-windres
  export WINDRES=i586-mingw32msvc-windres

SDL's Script

See also: BuildCVS.txt in the tar of the SDL scripts

http://www.libsdl.org/extras/win32/cross/ contains scripts that automate the compiler build process described above.

Download build-cross.sh, cross-configure.sh, and cross-make.sh.

Run the script build-cross.sh.

Download the CVS version wxAll and uncompress it.

Copy cross-configure.sh and cross-make.sh to the wxWidgets-2.5.2 directory.

Run cross-configure.sh and cross-make.sh and you should be done. :-)

Note about WINE

Make sure to turn off binfmt support before running configure (Debian: /etc/init.d/binfmt-support stop), which invokes wine for .exe files; otherwise configure will think it does NOT use a cross-compiler.

Autoconf/Automake unit testing suites

(maybe this section should go somewhere else?)

It is possible to autotest your code using wine (you are using unit tests, right?). This makes it very easy to script code under Unix to build multiple platforms, then test, without intervention. This section focusses on testing console-able objects.

First familiarise yourself with building test binaries with autoconf and automake. I recommend cppunit (for C++ systems). There's plentiful documentation on cppunit's website on integrating cppunit with Makefile.am. One show-stopping step is the ability to test msw binaries in the same way (make check) one tests unix binaries.

To take advantage of wine (running your tests automatically with wine), first make sure that wine may run headless. If you have access to a graphical terminal then this isn't important (if you're Ok with having wine spout gobbledygock to a window with every run). Make sure your test-directory Makefile.am's have all TESTS tokens suffixed with $(EXEEXT):

TESTS = TestFoo$(EXEEXT)

check_PROGRAMS = TestFoo

...and so on.

Next add a configure.ac (you have upgraded to using .ac instead of .in, right?) line manipulating the macro TESTS_ENVIRONMENT:

AC_SUBST([TESTS_ENVIRONMENT], [$WINE])

In this I assume that WINE has been set with AC_CHECK_PROGS or something (even `WINE = wine'). This will have all tests run in the following format:

$(TESTS_ENVIRONMENT) $${dir}$$tst

Where dir is the path and tst is the test name (remember that EXEEXT). That's it: wine will return the exit code of your running binary. You can also put a special shell or other token in there, but that exceeds the focus of this documentation. This assumed automake-1.9 and autoconf-2.57 but I'm fairly certain it works in earlier versions of both (uncertain about autoconf-2.13 style).


Testing the created executables

To test your mingw32 installation with a sample not using wxWidgets, look above ("Example usage").

To test your mingw32 installation with a real wxWidgets example, take minimal.cpp from the official examples. Fortunately, I didn't have to fiddle around with the flags myself, I use wx-config for that - not the system-wide one, but the one compiled with the cross-Windows libraries below /usr/local/i586-mingw32!

i586-mingw32msvc-g++ -c -o minimal.o minimal.cpp \ 
  `/usr/local/i586-mingw32/bin/wx-config --cxxflags`
i586-mingw32msvc-g++ -o minimal.exe minimal.o \
  `/usr/local/i586-mingw32/bin/wx-config --libs`

Attention, there are are two caveats here that could cost you lots of time (it did cost me lots of time, hope I'll save yours ;-)

  • When compiling, be sure to include the -c option. -o with an .o object file isn't enough, mingw32 will try to link!
  • When linking, be sure to include first your object files and then the libraries (given by wx-config). When compiling, the order isn't too important, but if you exchange libraries and object files at the linking stage, you'll get lots of undefined references. The reason is that a linker processes the libraries in order of their appearance (see documentation of "-l" at http://sourceware.org/binutils/docs/ld/Options.html).

Finally, when executing your program with wine, qemu (works great!) or even on a real Windows box, don't forget that even if you linked everything statically, you'll also need mingwm10.dll in addition to your executable. Put in in the same directory and execute the binary from there, and everything works. I found mingwm10.dll gzipped in /usr/share/doc/mingw32-runtime/