Building OpenEXR libraries for Windows x64
May 25th, 2010 by BramzLiAR supports the OpenEXR file format for several months now, but I only had it working on 32-bit windows. I was still missing the binaries for the 64-bit build, as you need to build the library yourself. For 64-bit Windows that turns out to be one tricky affair:
- Only Visual Studio solution files are available so that rules out nmake.
- DLL creation involves an custom build tailored for x86.
- The Visual C++ Express editions are x86 only anyway, so you have to work around that as well.
- And surprisingly, it seems that no-one has ever bothered so before because there’s hardly anything to be found on the web.
After several hours of hairpulling, I’ve finally managed to set up a working x64 build. To document it for future reference, and for other people on the same adventure, here are the magic build steps:
Setting up the build tree
The OpenEXR build is rather picky on the build tree layout. While the absolute location is free for choice, you need to add an extra layer for things to play out nicely. On my machine, I’ve put everything in C:\libs-x64\openexr-1.6.1
, but that could be just any other location.
- Download ilmbase-1.0.1.tar.gz and openexr-1.6.1.tar.gz.
- Create
C:\libs-x64\openexr-1.6.1\openexr
.This extra layer is necessary to make sure the goodies are gathered in
C:\libs-x64\openexr-1.6.1\Deploy
. Otherwise, they would end up inC:\libs-x64\Deploy
. - Extract
ilmbase-1.0.1.tar.gz
to
C:\libs-x64\openexr-1.6.1\openexr\ilmbase-1.0.1
- Extract
openexr-1.6.1.tar.gz
to
C:\libs-x64\openexr-1.6.1\openexr\openexr-1.6.1
Using VC Express for x64 builds
For Windows, OpenEXR comes with Visual Studio project files only. So you must use Visual C++ for building. If you’re using the VC Express edition, that’s a problem because it only has a x86 compiler on board. And you can’t directly use the x64 compiler of the Windows SDK, as that requires nmake makefiles, which you don’t have. But you can do it indirectly …
- Open a Windows SDK CMD shell. This sets all the required environment variables to use the x64 compiler.
"%VCINSTALLDIR%\..\Common7\IDE\VCExpress" /useenv
or whatever the location to vcexpress.exe is.The
/useenv
switch is important to tell the IDE not to use the default compiler, but to assume the environment is already setup ready to go. This is exactly why we run this within the Windows SDK shell.- Open a solution and make sure you target the x64 platform.
You won’t be able to setup a new x64 configuration, but you can just open the Win32 configuration, go to the advanced linker options and specify
MachineX64 (/MACHINEX64)
as target machine. - Build …
Building IlmBase
IlmBase contains the createDLL project that builds a tool for the custom build steps. You need to tweak its sources to correctly skip names starting with an underscore. Because createDLL assumes the x86 __cdecl
calling convention which decorates names with an extra underscore, it actually only skips names that start with at least two underscores. But the x64 calling convention does not decorate them as such, so names starting with a single underscore slip through the net.
- Start VC Express, open
ilmbase-1.0.1\vc\vc8\IlmBase\IlmBase.sln
and convert if necessary. - Set the target machine to
MachineX64
(see above) - Open
createDLL.cpp
to make the following code changes:- Replace
/MACHINE:X86
by/MACHINE:X64
(line 683) - Replace the following (three occurrences!)
// symbol starts with two underbars, skip it
else if (buf[0] == ‘_’ && buf[1] == ‘_’) {by
// symbol starts with underbar, skip it
else if (buf[0] == ‘_’) {
- Replace
- Build …
If you get errors like
fatal error LNK1112: module machine type 'X86' conflicts with target machine type 'x64'
, you should have started VCExpress with the /useenv switch from the Windows SDK CMD shell, as described above.
Building zlib:
OpenEXR has a dependency on zlib. So if you don’t have done so yet, now is the time to build it …
- Download zlib125.zip and extract to
C:\libs-x64\zlib-1.2.5
- Open a Windows SDK CMD shell
cd /D C:\libs-x64\zlib-1.2.5
set Include=C:\libs-x64\zlib-1.2.5;%Include%
nmake -f win32/Makefile.msc AS=ml64 LOC="-DASMV -DASMINF" OBJA="inffasx64.obj gvmat64.obj inffas8664.obj"
Building OpenEXR
OpenEXR expects the zlib headers and libraries to be in the Deploy directory as well, so that’s where we’re going to put them.
- Copy
zlib.h
andzconf.h
fromC:\libs-x64\zlib-1.2.5
toDeploy\include
- Copy
zdll.lib
to bothDeploy\lib\Debug
andDeploy\lib\Release
- Copy
zlib1.dll
to bothDeploy\bin\Debug
andDeploy\bin\Release
- Start VCExpress and open
openexr-1.6.1\vc\vc8\OpenEXR\OpenEXR.sln
- Set the target machine to
MachineX64
(see above) - Build …
That’s it. By now you should have a Deploy directory filled with OpenEXR headers and libraries, ready to be used in your x64 build of, for example, LiAR =)
Happy Towel Day!
January 31st, 2011 at 4:53 pm
Hi there ! Thanks for this post !
I’m using Visual Studio Express on Visual Studio 2010, and when i try compiling it i’ve got the following error for all dll:
TRACKER : error TRK0002: Failed to execute command: “”C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\Bin\amd64\CL.exe” “@C:\Documents and Settings\Administrator\Local Settings\Temp\b521257dd13848deb2932172c4435339.rsp””. The handle is invalid.
I’ve googling a bit but without success…. did you face this issue ?
January 31st, 2011 at 8:29 pm
Hi David,
No, I haven’t seen that message before. I didn’t try it with Visual C++ 2010 Express to be honest. I’ve used the 2008 edition. From what I’ve googled, it appears to be a wider issue with VC++ 2010 on x64 windows …
Bram
March 1st, 2011 at 3:14 am
Bram,
You rock! Thanks for the timesaving tips, worked a treat for me…
March 9th, 2011 at 9:32 am
Hi Bruce,
Thanks, I’m glad it helped …
April 7th, 2011 at 3:10 pm
Hi!
Your post helped me to figure out where did that Deploy folder go.. I was a bit confused before. So thanks for that!
I still have one persistent issue that you might be familiar with.. When I try to compile openExr (with the previous steps done) it throws ùe the following error :
fatal error LNK1181: cannot open input file ‘..\win32\release\ilmimf.lib’
It seems normal that it cannot open it since it doesn’t seem to exist at all… Do you know how I could fix that ?
Thanks !
April 9th, 2011 at 6:14 pm
Hi Johanna,
IlmImf should be part of the openexr build itself. What version of OpenEXR are you trying to build?
Bram
April 11th, 2011 at 9:22 am
I’m trying to build the 1.6.1 version which is apparently the last stable version. I also tried the 1.7.0, with no more luck.
Are you saying that I don’t need to build IlmImf separately ? Because in the readme files, it still says to do it this way.
Jo
April 11th, 2011 at 1:24 pm
OK, so apparently there was some trouble with the 64bits version. I’ve been given a pre-compiled version (I don’t know from who though, sorry..) so no more trouble.
Anyway, thanks for your interest !
April 13th, 2011 at 1:19 am
Hey!
I am working with Johanna,
the prebuild lib isn’t working so we need to rebuild ourselves.
All the fix for x64 are succesfull for the libs, except the zlib linking on ImfImf :
1>CreateDLL found 3140 symbols
1>Exporting DLL
1> Creating library ..\Win32\Release\IlmImf.lib and object ..\Win32\Release\IlmImf.exp
1>ImfPxr24Compressor.obj : error LNK2019: unresolved external symbol compress referenced in function “private: int __cdecl Imf::Pxr24Compressor::compress(char const *,int,class Imath::Box<class Imath::Vec2 >,char const * &)” (?compress@Pxr24Compressor@Imf@@AEAAHPEBDHV?$Box@V?$Vec2@H@Imath@@@Imath@@AEAPEBD@Z)
1>ImfZipCompressor.obj : error LNK2001: unresolved external symbol compress
1>ImfPxr24Compressor.obj : error LNK2019: unresolved external symbol uncompress referenced in function “private: int __cdecl Imf::Pxr24Compressor::uncompress(char const *,int,class Imath::Box<class Imath::Vec2 >,char const * &)” (?uncompress@Pxr24Compressor@Imf@@AEAAHPEBDHV?$Box@V?$Vec2@H@Imath@@@Imath@@AEAPEBD@Z)
1>ImfZipCompressor.obj : error LNK2001: unresolved external symbol uncompress
1>..\Win32\Release\IlmImf.dll : fatal error LNK1120: 2 unresolved externals
1>createDLL: linking failure. Linker: link.exe, status: 1120
1>Project : error PRJ0019: A tool returned an error code from “Performing Post-Build Event…”
I tried linking against
* recompiled zlib-1.2.5 following your instructions with nmake / platform sdk
* precompiled zlib zlib125dll\dllx64\zlibwapi.lib
* libzlib_dll.lib from Hebbut.net
The linker doesn’t like any of those…It looks like createDll is still the problem ?
In createDLL_out.txt there is no zlib.lib, although I added it to the linker inputs in VC :
Input Libraries:
Half.lib
Iex.lib
IlmThread.lib
MSVCRT.lib
kernel32.lib
msvcprt.lib
createDLL: linking failure. Linker: link.exe, status: 1120
Thank you!
best regards
Julien
April 13th, 2011 at 1:52 am
I found the solution, i had to link ImfImf against zdll.lib…
thanks!
Julien
April 15th, 2011 at 7:38 am
Hi Julien,
I’m glad it works alright now! So IllImf doesn’t link against zlib by default? Or, does it looks for an import library by another name? I’ll see to update the instructions …
Happy coding!
Bram
June 9th, 2011 at 5:23 am
well,
great! thanks very much for this survey, it saved me for sure one whole day or even longer. i got openEXR win64 compiled in 1 hour only thanks to you. in fact i complied the 1.7.0 version on visual studio 2010 which works quite the same way as described here. the only issue is the one mentioned by julien – one has to replace the linkage of “zlibwapi.lib” against “zdll.lib” in the IlmImf project setup. of course one has to compile zlib as described above. and there is no need to fix the solution-files for 64 bit anymore; one only needs to convert them to visual studio 2010 and switch the configuration and build targets (which are already well defined) to “release/x64”.
works fine.
cheers
pm
November 16th, 2011 at 8:41 pm
Hi pm,
I didn’t see your comment until now, but thanks! I’m glad it helped. I’ll try out the 1.7.0 version myself, taking this zlib thing into account, and update the instructions accordingly.
Thanks,
Bram
December 20th, 2011 at 7:56 pm
[…] Building OpenEXR (Hugin SDK) Building OpenEXR x64 (Liar’s blog) Compiling zlib This entry was posted in C++, Coding, Computer Vision by Michael. Bookmark the […]
January 14th, 2013 at 5:51 pm
I have the same LNK problems and I did the same thing you guys suggested but it doesn’t seem to change anything. I am close to pulling out my hair as I have WASTED two days on this problem. Please someone help!!!
January 17th, 2013 at 10:13 pm
OK, for the 1.7.0 version, what I ended up doing is to write CMakeLists for it. Here‘s a zip with the required files if you know what you’re doing. I should eventually write an update on this. Hope it helps!
January 17th, 2013 at 10:18 pm
Dozie, in OpenEXR, there should be a line somewhere like:
#define ZLIB_WINAPI
Try to comment it out. If it doesn’t work, put it back and tell us the exact linker problems.
September 12th, 2013 at 5:47 am
Hi all,
I comment out that line, but it still get linker error like this:
ImfHeader.obj : error LNK2019: unresolved external symbol “public: static char const * __cdecl Imf::TypedAttribute<class std::vector<class std::basic_string<char,struct std::char_traits,class std::allocator >,class std::allocator<class std::basic_string<char,struct std::char_traits,class std::allocator > > > >::staticTypeName(void)” (?staticTypeName@?$TypedAttribute@V?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@std@@@Imf@@SAPBDXZ) referenced in function “public: static void __cdecl Imf::TypedAttribute<class std::vector<class std::basic_string<char,struct std::char_traits,class std::allocator >,class std::allocator<class std::basic_string<char,struct std::char_traits,class std::allocator > > > >::registerAttributeType(void)” (?registerAttributeType@?$TypedAttribute@V?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@std@@@Imf@@SAXXZ)
1>ImfStandardAttributes.obj : error LNK2001: unresolved external symbol “public: static char const * __cdecl Imf::TypedAttribute<class std::vector<class std::basic_string<char,struct std::char_traits,class std::allocator >,class std::allocator<class std::basic_string<char,struct std::char_traits,class std::allocator > > > >::staticTypeName(void)” (?staticTypeName@?$TypedAttribute@V?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@std@@@Imf@@SAPBDXZ)
1>ImfHeader.obj : error LNK2001: unresolved external symbol “public: virtual void __thiscall Imf::TypedAttribute<class std::vector<class std::basic_string<char,struct std::char_traits,class std::allocator >,class std::allocator<class std::basic_string<char,struct std::char_traits,class std::allocator > > > >::writeValueTo(class Imf::OStream &,int)const ” (?writeValueTo@?$TypedAttribute@V?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@std@@@Imf@@UBEXAAVOStream@2@H@Z)
1>ImfStandardAttributes.obj : error LNK2001: unresolved external symbol “public: virtual void __thiscall Imf::TypedAttribute<class std::vector<class std::basic_string<char,struct std::char_traits,class std::allocator >,class std::allocator<class std::basic_string<char,struct std::char_traits,class std::allocator > > > >::writeValueTo(class Imf::OStream &,int)const ” (?writeValueTo@?$TypedAttribute@V?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@std@@@Imf@@UBEXAAVOStream@2@H@Z)
1>ImfHeader.obj : error LNK2001: unresolved external symbol “public: virtual void __thiscall Imf::TypedAttribute<class std::vector<class std::basic_string<char,struct std::char_traits,class std::allocator >,class std::allocator<class std::basic_string<char,struct std::char_traits,class std::allocator > > > >::readValueFrom(class Imf::IStream &,int,int)” (?readValueFrom@?$TypedAttribute@V?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@std@@@Imf@@UAEXAAVIStream@2@HH@Z)
1>ImfStandardAttributes.obj : error LNK2001: unresolved external symbol “public: virtual void __thiscall Imf::TypedAttribute<class std::vector<class std::basic_string<char,struct std::char_traits,class std::allocator >,class std::allocator<class std::basic_string<char,struct std::char_traits,class std::allocator > > > >::readValueFrom(class Imf::IStream &,int,int)” (?readValueFrom@?$TypedAttribute@V?$vector@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@std@@@Imf@@UAEXAAVIStream@2@HH@Z)
1>..\Release/IlmImf.dll : fatal error LNK1120: 3 unresolved externals
Please help me.
Thanks,