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