Date Tags wine

Every once in a while the Continuous Integration reminds me that the code I write isn't "that" portable. I develop on Linux, push to the SCM and the CI goes out and builds on several Unixes and Windows.

Fixing windows build issues through the CI takes quite a while. It is far easier to have a local windows build-environment around to do the build, testing before you push. You could make that quite efficient by installing Windows in a VM, use shared-folders, use cygwin+sshd to log into it from the command-line ...

... or you simplify it even more and just use wine.

The main reason for me to go this path:

  • I don't need a GUI (I could start the VM headless)
  • I don't want to polute windows with cygwin (I could use WinRM)
  • I don't need most of the things a full windows provides

Wine does the basics I need:

  • provide a shared folder between windows and my host
  • I can use my unix-toolset to control it
  • I can use several, separted instances

Installing vcexpress2008

First I checked the appdb about which Visual Studio express was most likely to run nicely in wine.

  • Visual Studio 2005 8
  • Visual Studio 2008 9

The easiest way to install it is using winetricks.

$ winetricks list-all | grep -i express
vc2005express            MS Visual C++ 2005 Express (Microsoft, 2005) [downloadable]
vc2008express            MS Visual C++ 2008 Express (Microsoft, 2008) [downloadable]

As it offers 2008, let's pick that:

$ winetricks vc2008express

Let it download the .NET packages, the vcexpress ISO-file, accept the EULAs, perhaps restart winetricks when it dies unexpectitly ... and you are done.

Using it

Now you have a clean WINEPREFIX in:

$ cd ~/.local/share/wineprefixes/vc2008express/

From there you have your

$ cd drive_c/
$ cd Program\ Files/

Opening a shell is:

$ WINEPREFIX=~/.local/share/wineprefixes/vc2008express/ wine cmd
Wine CMD Version 5.1.2600 (1.6-rc5)

Z:\home\jan>

You see that it mounts the unix-root directory as Z:\ with the current directory being the current directory you started wine in.

Now we need cmake to actually drive the build. Calling the its installer:

$ WINEPREFIX=~/.local/share/wineprefixes/vc2008express/ wine ~/Download/cmake-2.8.11.2-win32-x86.exe

and perhaps Python which comes as a .msi:

$ WINEPREFIX=~/.local/share/wineprefixes/vc2008express/ wine msiexec /package ~/Download/python-2.7.5.msi

Build with it

As we have a build environment setup now we can start our build. I assumed that:

  • you use cmake to create portable build-files
  • dependencies are already setup, one-per-dependency in the same base directory

All it takes is creating a little .bat file which sets up the enviroment variables and calls cmake and vcbuild. The build.bat may look like:

$ cat build.bat
rem create a clean environment
set PATH=C:\windows\system32;C:\windows;C:\windows\system32\wbem
set PKG_CONFIG_PATH=;

set CMAKE="C:\Program Files\CMake 2.8\bin\cmake.exe"
set PYTHONDIR=c:\Python26\
call "C:\Program Files\Microsoft Visual Studio 9.0\VC\vcvarsall.bat"
@echo off

set PATH=%PYTHONDIR%;%PATH%

rem directory where all the dependencies are installed
set BASEDIR=Z:/home/jan/...

set PKG_CONFIG_BASEDIR=%BASEDIR%/pkg-config-0.26-windows-x86-32bit/
set PATH=%PKG_CONFIG_BASEDIR%/bin;%PATH%

set ZLIB_BASEDIR=%BASEDIR%/zlib-1.2.5-windows-x86-32bit/
set PATH=%ZLIB_BASEDIR%/bin;%PATH%

set LIBINTL_BASEDIR=%BASEDIR%/gettext-0.17-libintl-windows-x86-32bit/
set PATH=%LIBINTL_BASEDIR%/bin/;%PATH%

set LIBFFI_BASEDIR=%BASEDIR%/libffi-3.0.12-windows-x86-32bit/
set PKG_CONFIG_PATH=%LIBFFI_BASEDIR%/lib/pkgconfig;%PKG_CONFIG_PATH%
set PATH=%LIBFFI_BASEDIR%/bin/;%PATH%

set GLIB_BASEDIR=%BASEDIR%/glib-2.36.3-windows-x86-32bit
set PKG_CONFIG_PATH=%GLIB_BASEDIR%/lib/pkgconfig;%PKG_CONFIG_PATH%
set PATH=%GLIB_BASEDIR%/bin;%PATH%

set GI_BASEDIR=%BASEDIR%/gobject-introspection-1.36.0-windows-x86-32bit/
set PKG_CONFIG_PATH=%GI_BASEDIR%/lib/pkgconfig;%PKG_CONFIG_PATH%
set PATH=%GI_BASEDIR%/bin;%PATH%

md pxtools-build-win32 
cd pxtools-build-win32
%CMAKE% ^
        -DCPACK_GENERATOR=ZIP ^
        -G "Visual Studio 9 2008" ^
        z:/home/jan/.../pxtools

vcbuild pxtools.sln "Release|Win32"
vcbuild PACKAGE.vcproj "Release|Win32"

All you need now is:

$ WINEPREFIX=~/.local/share/wineprefixes/vc2008express/ wine cmd < build.bat | tee build.txt

Running it

As I have setup CPack in my CMakeLists.txt the PACKAGE.vcprog generates a .zip of the finished build.

$ unzip pxtools-build-win32/pxtools-1.0.0-win32.zip

Running your built app is a good time to use another, clean WINEPREFIX (which doesn't have vc2008express installed) to make sure it runs against a bare install without the development DLLs around:

$ wine pxtools-1.0.0-win32/bin/pxinfo.exe --filename=...

Debugging it

One of the most common problems on windows for me is missing to place all the DLL it needs in into the library search path which usually is the directory of the started binary or PATH.

For example if I run g-ir-scanner I may get a python exception that in the end says:

ImportError: DLL load failed: Module not found.

Now you would have to start the Dependency Walker and try to find what is missing, or you just check the output of wine:

err:module:import_dll Library zlib1.dll (which is needed by L"Z:...\\bin\\gio-2-vs9.dll") not found
err:module:import_dll Library gio-2-vs9.dll (which is needed by L"Z:...\\lib\\gobject-introspection\\giscanner\\_giscanner.pyd") not found

Solution: Add the directory where zlib1.dll is located to the PATH of the build.bat, done.


Comments

Enable javascript to load comments.