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
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.
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
Now we need cmake to actually drive the build. Calling the its installer:
$ WINEPREFIX=~/.local/share/wineprefixes/vc2008express/ wine ~/Download/cmake-18.104.22.168-win32-x86.exe
and perhaps Python which comes as a
$ 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
cmaketo 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
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
As I have setup CPack in my
.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
(which doesn't have
vc2008express installed) to make sure it runs against a bare install without the development
$ wine pxtools-1.0.0-win32/bin/pxinfo.exe --filename=...
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
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