Difference between revisions of "User:Iceiceice/Cross-compiling"

From The Battle for Wesnoth Wiki
m (Make a boost config file (tell it what compiler you want to use))
Line 158: Line 158:
  
 
That's all there is to it. Good luck.
 
That's all there is to it. Good luck.
 +
 +
== WINE ==
 +
 +
To get wine to run I did the following. You must make sure you are using a 32 bit environment.
 +
 +
  env WINEPREFIX=~/prefix32 WINEARCH=win32 wine cmd
 +
 +
All the online instructions say that you need to update wine's path, using regedit, to point to your dll's. I couldn't actually get this to work, so I ended up putting symlinks in my prefix 32 C:\windows\system32 directory:
 +
 +
  ~/prefix32/drive_c/windows/system32 $ ln -s ~/w-deps/bin
 +
  ~/prefix32/drive_c/windows/system32 $ ln -s /usr/lib/gcc/i686-w64-mingw32/4.9-win32/
 +
 +
If I got errors like this:
 +
 +
  $ env WINEPREFIX=~/prefix32 WINEARCH=win32 wine wesnoth
 +
  err:module:import_dll Library libpangoft2-1.0-0.dll (which is needed by L"C:\\windows\\system32\\libpangocairo-1.0-0.dll") not found
 +
  err:module:import_dll Library libpangocairo-1.0-0.dll (which is needed by L"Z:\\home\\chris\\wesnoth-src\\clone\\wesnoth\\wesnoth.exe") not found
 +
  err:module:LdrInitializeThunk Main exe initialization for L"Z:\\home\\chris\\wesnoth-src\\clone\\wesnoth\\wesnoth.exe" failed, status c0000135
 +
 +
I fixed it by adding a symlink to ~/w-deps/bin/libpangoft2-1.0-0.dll in the folder prefix32/drive_c/windows/system32.
 +
 +
And so on and so forth... Eventually it worked.

Revision as of 15:44, 24 October 2014

Here are some instructions I created the first time I managed to cross compile wesnoth. It's as much a "post-mortem" as a guide, I leave it here in case I ever want to do it again later, or if it might help someone.

These instructions refer to using mingw to cross-compile wesnoth 1.13.0-dev on Linux Mint Qiana 17 , targeted at windows.

Last tested at commit: 1385ab3791088d7c9bfa3bc439fcf49b23563535

Get mingw

It might seem as simple as "sudo apt-get install mingw32", but after you do this, you need to make sure that you have a 32 bit compiler which is good enough to compile wesnoth. This required some trial and error, the version I got automatically from the distribution was only gcc 4.2, as you can see:

  $ i586-mingw32msvc-g++ -v
 Using built-in specs.
 Target: i586-mingw32msvc
 Configured with: /build/buildd/mingw32-4.2.1.dfsg/build_dir/src/gcc-4.2.1-2-dfsg/configure -v --prefix=/usr --target=i586-mingw32msvc --enable-languages=c,c++ --enable-threads --enable-sjlj-exceptions --disable-multilib --enable-version-specific-runtime-libs
 Thread model: win32
 gcc version 4.2.1-sjlj (mingw32-2)


Furthermore it was broken, and had some bugs about ::swprintf not defined, which caused boost iostreams to break... google this for some stories of pain. [1] [2] [3]


Therefore to get a more recent version of mingw I added a package from utopic universe :

 $ sudo add-apt-repository -y "deb http://archive.ubuntu.com/ubuntu/ utopic main universe"

And I install

 $ sudo apt-get install g++-mingw-w64-i686

(Launchpad page: http://packages.ubuntu.com/utopic/g++-mingw-w64-x86-64) Now I get this instead

 $ i686-w64-mingw32-g++ -v
 Using built-in specs.
 COLLECT_GCC=i686-w64-mingw32-g++
 COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-w64-mingw32/4.9-win32/lto-wrapper
 Target: i686-w64-mingw32
 Configured with: ../../src/configure --build=x86_64-linux-gnu --prefix=/usr --includedir='/usr/include' --mandir='/usr/share/man' --infodir='/usr/share/info' --sysconfdir=/etc --localstatedir=/var --libexecdir='/usr/lib/gcc-mingw-w64' --disable-maintainer-mode --disable-dependency-tracking --prefix=/usr --enable-shared --enable-static --disable-multilib --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --libdir=/usr/lib --enable-libstdcxx-time=yes --with-tune=generic --enable-version-specific-runtime-libs --enable-fully-dynamic-string --enable-libgomp --enable-languages=c,c++,fortran,objc,obj-c++ --enable-lto --with-plugin-ld --enable-threads=win32 --program-suffix=-win32 --program-prefix=i686-w64-mingw32- --target=i686-w64-mingw32 --with-as=/usr/bin/i686-w64-mingw32-as --with-ld=/usr/bin/i686-w64-mingw32-ld
 Thread model: win32
 gcc version 4.9.1 (GCC)

With gcc 4.9, now we are in business.

Download loonycyborg's wesnoth deps collection

http://sourceforge.net/projects/wesnoth/files/SDK/wesnoth-deps-1.11.zip/download

I'm going to assume henceforth that you extract this to the folder "~/w-deps", and that inside is "include", "bin" etc. directories.

Download boost

I wanted to test our stated boost dependencies, so I actually make a folder "~/old-boost/" where I hold several versions of boost. You can find any old version of boost at source forge, e.g.

[4] [5] [6]

etc.

Download one of these and extract it to ~/old-boost/, or take from w-deps folder.

I'm going to assume that you picked boost 1.52.0, so your boost directory is ~/old_boost/boost_1_52_0/.

Make a boost config file (tell it what compiler you want to use)

In your home directory, make a text file called user_config.jam.

Here's some sample contents:

 $ cat user-config.jam 
 using gcc ;
 using gcc : 4.6 : g++-4.6 ;
 using gcc : w64mingw32 : i586-mingw32msvc-g++ ;
 using gcc : w64mingw64 : x86_64-w64-mingw32-g++ ;


When boost has a file like this, it means that e.g. "toolset=gcc-4.6" will cause it to use the compiler g++-4.6, and "toolset=gcc-w64mingw32" will cause it to use the compiler i586-mingw32msvc-g++.

Make a line like this:

 using gcc : w64mingw32 : i686-w64-mingw32-g++ ;

To register our new compiler.

(And make sure its the only w64mingw32 line of course.)

Compile boost

Navigate to your boost directory, ~/old_boost/boost_1_52_0/

First, run the "bootstrap" program,

 ./bootstrap.sh

You don't need to give it any arguments, it doesn't really matter what it builds with. It is just building the boost jam program which will actually orchestrate the boost build.

Now, run boost jam (called "b2"). I recommend to put the actual command in shell script, for ease of use in case you have to modify it (and so you don't forget it...)

I used the following recipe:

 $ cat recipe
 #!/bin/bash
./b2 toolset=gcc-w64mingw32 -d+2 -a --reconfigure --debug-configuration --with-iostreams --with-locale --with-regex --with-filesystem --with-system --with-program_options target-os=windows variant=release threading=multi threadapi=win32    link=static runtime-link=static -j 2 -sBZIP2_BINARY=libbz2 -sBZIP2_INCLUDE=/home/chris/w-deps/include -sBZIP2_LIBPATH=/home/chris/w-deps/bin -sZLIB_BINARY=zlib -sZLIB_INCLUDE=/home/chris/w-deps/include -sZLIB_LIBPATH=/home/chris/w-deps/bin


Now run the recipe (don't forget to "chmod +x" it):

 $ ./recipe

If you would like to suppress the warnings, you can use cxxflags="-w" as an additional argument.

You should get this at the end:

 The Boost C++ Libraries were successfully built!
 
 The following directory should be added to compiler include paths:
 
     /home/chris/old_boost/boost_1_52_0
 
 The following directory should be added to linker library paths:
 
     /home/chris/old_boost/boost_1_52_0/stage/lib


If you did not, check that all of your paths are matching correctly, that you actually have a libbz2.a and zlib.a in your ~/w-deps/bin, (and that they *match* the associated headers... if in doubt, try downloading again, or even compile the c libraries yourself, it doesn't matter what compiler you use for c libraries). Check that the compiler name is correct. You could use cxxflags to try to get additional diagnostics. The -d+2 command causes boost to output much additional diagnostics as well.

Compile wesnoth

Now, you need to craft an scons command that will properly tell it to cross compile, to use the cross compiling compiler, and point it to your fresh boost compile, and all the deps. I prefer to in this case as well store the recipe in a shell script:

 $ cat build_mingw_boost_1_52.sh 
 #!/bin/bash
 rm .scons-option-cache
 scons default_targets=wesnoth build=release extra_flags_config="-DBOOST_THREAD_USE_LIB -Wno-unused-local-typedefs" prefix=~/w-deps boostdir=~/old_boost/boost_1_52_0 boostlibdir=~/old_boost/boost_1_52_0/stage/lib gettextdir=~/w-deps gtkdir=~/w-deps  host=i686-w64-mingw32

Some discussion

rm .scons-option-cache
So that stale settings can't screw up my build and confuse me
default_targets=wesnoth
This could also be wesnoth, wesnothd, campaignd. I think it can't include "test" atm because we didn't compile the boost unit testing system.
build=release
Unless you want to make a debug build
extra_flags_config
Add -Wno-unused-local-typedefs or your log will be unreadable with pointless warnings.
Add -DBOOST_THREAD_USE_LIB because loonycyborg said so
prefix=~/w-deps
This is pretty handy, this will cause scons to add ~/w-deps/include to be included as a cxx flag, and also to add ~/w-deps/bin to be linked. So it saves you some typing.
boostdir=~/old_boost/boost_1_52_0
Or corresponding, whereever the root is for the boost that you want to use.
boostlibdir=~/old_boost/boost_1_52_0/stage/lib
Wherever the boost libraries ended up for you.
gettextdir=~/w-deps
gtkdir=~/w-deps
These point scons to find compiled versions of these, and not your system version (which will not be binary compatible in case of C++ libs).
Note that I don't add sdldir=~/w-deps, because it shouldn't be necessary as SDL is a c lib, so my system version is fine. But if you get a problem finding or linking SDL, then add that in also.
host=i686-w64-mingw32
This is where we select the compiler, actually. scons will prepend the "host" followed by -, followed by g++, if no cxxtool argument is given. (I'm not sure how "host" and "cxxtool" arguments interact.) So this selection results in the compiler, i686-w64-mingw32-g++, as desired.

That's all there is to it. Good luck.

WINE

To get wine to run I did the following. You must make sure you are using a 32 bit environment.

 env WINEPREFIX=~/prefix32 WINEARCH=win32 wine cmd

All the online instructions say that you need to update wine's path, using regedit, to point to your dll's. I couldn't actually get this to work, so I ended up putting symlinks in my prefix 32 C:\windows\system32 directory:

 ~/prefix32/drive_c/windows/system32 $ ln -s ~/w-deps/bin
 ~/prefix32/drive_c/windows/system32 $ ln -s /usr/lib/gcc/i686-w64-mingw32/4.9-win32/

If I got errors like this:

 $ env WINEPREFIX=~/prefix32 WINEARCH=win32 wine wesnoth
 err:module:import_dll Library libpangoft2-1.0-0.dll (which is needed by L"C:\\windows\\system32\\libpangocairo-1.0-0.dll") not found
 err:module:import_dll Library libpangocairo-1.0-0.dll (which is needed by L"Z:\\home\\chris\\wesnoth-src\\clone\\wesnoth\\wesnoth.exe") not found
 err:module:LdrInitializeThunk Main exe initialization for L"Z:\\home\\chris\\wesnoth-src\\clone\\wesnoth\\wesnoth.exe" failed, status c0000135

I fixed it by adding a symlink to ~/w-deps/bin/libpangoft2-1.0-0.dll in the folder prefix32/drive_c/windows/system32.

And so on and so forth... Eventually it worked.