Saturday, 29 August 2015

Building icu statically for linkage to Qt

It's bad enough having to link to all the Qt dll's without having to distribute its various dependencies as well - OpenSSL and  ICU chiefly among them. Then if you write a dll that plugs into someone else's exe you need to watch out that you could be trying to load a different version of a dependency dll that's used elsewhere in the exe.

So using static libs of the dependencies to link when you build Qt should help a lot. OpenSSL has some nice well-maintained static windows binaries (https://www.openssl.org/related/binaries.html), but icu does not.

There is this: http://www.npcglib.org/~stathis/blog/precompiled-icu/

But it uses static runtimes. So if you want a static build with dynamic (MD) runtimes, you're out of luck.

Building with Visual Studio

The Visual Studio solution all_in_one.sln that comes with ICU only builds dynamic libs. So you can modify the projects in the solution to link statically. Make sure that the output debug libraries have a suffix 'd' to their filenames, because they'll be built in the same directory as the release libraries.

Building with make

The recipe to build static ICU with MSVC is:

cd "%WORKSPACE%\source\"
set PATH=C:\cygwin\bin;%PATH%
call "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" x86
dos2unix -f *
dos2unix -f configure
dos2unix -f mkinstalldirs

bash runConfigureICU Cygwin/MSVC -prefix=/cygdrive/d/Jarvis/icu_static/dist -enable-static -disable-shared
dos2unix -f install-sh

make && make install


Dos2unix prevents errors of the form '\r unknown command' in the make script.

Path order is crucial. If you call vcvarsall.bat before adding cygwin\bin to the path, you'll get something like:

icupkg: unable to open input file
/cygdrive/d/icu/win32-x86/data/out/build/icudt55l\coll\root.res"

But if you add cygwin/bin after %PATH%, you'll get something like:

link.exe is not a valid executable.

So only the above order works.

Output

You'll get these files in lib (for Win32) or lib64 (for x64):

icudt.lib icuin.lib
icuio.lib
icule.lib
iculx.lib
icutest.lib
icutu.lib
icuuc.lib
testplug.lib

and for debug:
icudtd.lib icuind.lib
icuiod.lib
iculed.lib
iculxd.lib icutestd.lib
icutud.lib
icuucd.lib testplugd.lib

When you come to build Qt, set an ICU environment variable to the parent icu directory, and in the Qt make command add the options:

-icu -I "%ICU%\include" -L "%ICU%\%LIB_OR_LIB64%"

where LIB_OR_LIB64 is "lib" or "lib64" depending on the platform.