Okay, I think I
finally figured it out.
Getting ICU to build
as static libraries on Windows required two changes to the code. The first
is the one I outlined in my previous note: In common/utracimp.h, the definition
of utrace_level needs to be modified to not include U_EXPORT when
U_STATIC_IMPLEMENTATION is defined. The relevant section of the file
should end up looking like this:
The two lines I
added are highlighted in bold (I also added the "defined(" stuff, which I think
is just an oversight in the current version of this file).
The second change is
to common/udata.c. Line 652 in this file looks like
const DataHeader U_IMPORT U_ICUDATA_ENTRY_POINT;
shouldn't be there when you're building as static libraries (this is what was
causing the funny symbol mangling I was seeing). This should probably be
fixed with some kind of conditional compilation akin to what's going on in
utracimp.h, where you define some symbol in the makefile that controls whether
we say U_IMPORT here or not, but I didn't want to figure out what should control
that; I just commented out U_IMPORT.
These two changes,
plus a fair amount of messing around with the project files and manually
building things at the command line, will get the data, common, and i18n modules
built as static libraries. I wrote a little sanity check program that
links against these files and it builds and runs correctly.
So to summarize, I
think you follow these steps to build ICU as a static library on Windows with
1) Make the change
to utracimp.h described above (but not the change to udata.c).
Then build the source as-is (as DLLs) with MSVC, following the instructions in
the readme. This will build all the data files and allow you to run the
unit tests. You should get no test failures.
2) There will be a
file called icudt28l_dat.obj in source/data/out/build. I believe your
program can link to this directly, or you can make it into a static library by
just doing lib /out:icudata.lib idudt28l_dat.obj at the command line. You
can also hack makedata.mak as described in George's earlier email (I'm pretty
sure both methods work). The resulting library will work with both debug
and release builds and with any MSVC threading model, as far as I can
tell. [I chose sicudata.lib as the filename for the lib file just so the
names were consistent with the names they get on the Unix
3) Now go into
udata.c and make the change described above.
4) Go back into MSVC
and choose Settings from the Project menu. Choose "common" as the project
to modify. In the defines list, change "U_COMMON_IMPLEMENTATION" to
"U_STATIC_IMPLEMENTATION". It necessary, change "/MD" to whatever
trheading model you're using. Set "common" as your active project and
choose Rebuild All from the Build menu. The .c and .cpp files should all
compile, but you'll get an undefined-symbol error from the linker. This is
okay. Repeat this step for both the debug and release
5) Go into
source\common\Release and execute lib /out:sicuuc.lib
*.obj. This will create a static library for "common". Issue
the same command inside source\common\Debug. In both cases, the name I'm
using-- sicuuc.lib-- was chosen to be consistent with the Unix
6) "i18n" won't
build from within MSVC because of the link error in "common". Go into
source\i18n and build it by hand using cl. Copy the compiler options from
the Project Settings window. Change "/D U_I18N_IMPLEMENTATION" to "/D
U_STATIC_IMPLEMENTATION". You should be able to build everything by
specifying the input filename as "*.c *.cpp", rather than issuing a separate cl
command for each file.
7) You can now
assemble everything into a library with "lib /out:sicui18n.lib *.obj" in
whatever directory you sent the compiler output to. You'll have to repease
steps 6 and 7 to do both debug and release builds.
done! If (as I did) you need to support different threading models, repeat
steps 4 through 6 for the different threading models you need to
Caveat: These are
not the exact steps I followed to get everything built. My route was more
circuitous, as it involved trying different things until I fugured out what
worked. So I can't guarantee the steps I give above will work perfectly,
but it's what I think the sequence is now that I got everything
solved, and there's the wisdom I gleaned in case anyone else out there tries to
do the same thing.
Life would be so
much easier if everyone coded in Java! :-)
Analysis Systems, Inc.