Project

General

Profile

Windows libraries

Added by Mateusz P. almost 8 years ago

Hello everyone,

I am working on Qt, multi-platform project and would like to use exiv2.
Under Mac OS I have managed to build and link everything properly.
Following manual and discussions I have analysed and used:
http://dev.exiv2.org/projects/exiv2/wiki/How_do_I_build_Exiv2_on_the_XYZ_platform
Now I started to do the job on Windows and encountered problems.
The goal is to link against exiv2 libs within the larger project.
The system settings are:
Windows 7 (64 bit)
QtCreator which uses precompiled Qt libraries (precompiled for larger project, however all simple examples are build-able and compile-able).
QMAKESPEC uses Visual Studio 2008; thus the flag is: -spec win32-msvc2008 in build steps
jom.exe is used for 'make' process.

To obtain the goal I used two approaches build the Exiv2 library :
1) http://clanmills.com/exiv2/mingw.shtml
2) http://dev.exiv2.org/boards/3/topics/1259

For both I have checked simple Qt + Exiv2 test app and for both build methods the build fails on linking stage...
The return error from QtCreator:
error: LNK2019: unresolved external symbol "public: static class std::auto_ptr<class Exiv2::Image> __cdecl Exiv2::ImageFactory::open(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?open@ImageFactory@Exiv2@SA?AV?$auto_ptr@VImage@Exiv2@std@ABV?$basic_string@DU?$char_traits@D@std@V?$allocator@D@2@4@Z) referenced in function "private: void __thiscall TestWindow::on_pushButton_clicked(void)" (?on_pushButton_clicked@TestWindow@AAEXXZ)

However when I used another QtSDK and MinGW as a QMAKESPEC then project links and runs flawlessly.
Therefore I suspect the problem caused by different usage of compilers - MinGW for building Exi2 and visual studio (win32-msvc2008) compiler for building test app. Since I can't change the QMAKESPEC flag I search for some workarround.

The commercial licence would be used for the project so I search for the way to distribute the project properly.
1. The static library exiv2.lib for Windows (32 and 64) would be the easiest way.
2. Dynamic .dlls exiv2.dll and required dependancies are also a convienient solution.

How can I produce any of them for this specific configuration ?
Should I build exiv2 Visual Studio projects so they do it for me? I tried a simple way to open .sln solution and 'build' but I just go a bunch of errors.

I'm not sure how to proceed with this idea.
Any clues?


Replies (11)

RE: Windows libraries - Added by Robin Mills almost 8 years ago

Hi

However when I used another QtSDK and MinGW as a QMAKESPEC then project links and runs flawlessly. __

If it links and runs, what's your problem?

You cannot mix compilers and libraries. If you're building your application with MingW, you'll have to link libraries built with MinGW. If you're building your application with Visual Studio (MSVC), you'll have to link libraries built with the same version of Visual Studio. You have a choice of build environments for MSVC. As you are building 32 and 64 bit libraries, I recommend you use msvc64. I've never built 64 bit libraries on MinGW.

The reason you cannot mix compilers is because the name mangling scheme is compiler specific and not defined by the C++ standard.

You can inspect the entry points on a libraries using the utility dumpbin.exe (MSVC) and nm (GCC). The utilities c+filt (for GCC) and udname (for MSVC) will convert the strange names to something human readable. I'm on the Mac at the moment:

$ for i in $(nm -g src/.libs/libexiv2.a | grep " U " | grep -i exiv | grep ImageFactory | sed -e "s/ U //g" | sort -u) ; do echo $i ; done
__ZN5Exiv212ImageFactory4openEPKhl
__ZN5Exiv212ImageFactory6createEi
$ for i in $(nm -g src/.libs/libexiv2.a | grep " U " | grep -i exiv | grep ImageFactory | sed -e "s/ U //g" | sort -u) ; do c++filt $i ; done
Exiv2::ImageFactory::open(unsigned char const*, long)
Exiv2::ImageFactory::create(int)
$ 

If you run something similar using dumpbin.exe and udname.exe on MSVC, you'll discover that the mangled names are different. Those different names result in the linker failures you've reported. The solution is to use the same compiler to build your application and the libraries.

Robin

RE: Windows libraries - Added by Mateusz P. almost 8 years ago

thank you for quick response, Robin.

That is exactly what I supposed to, my mistake is that I used two different compilers.
I meant, I can build my example when I use the same, here MinGW compilers.

However the goal application uses Visual Studio setting in QMAKESPEC, -spec win32-msvc2008.(Entire project uses Qt Creator).
The tutorials, discussions explains nicely how to build the library with MinGW.

Forgive me my lack of exeprience and my dump-looking question.
How, on the other hand, can I build exiv2 with Visual Studio?
Is it so, that I shall open Visual Studio solution and proceed with ReadMe.txt file located in exiv-0.23/msvc64?
From what I understood this solution should build all the desired libraries static/dynamic, 32- and 64- bit mode.

RE: Windows libraries - Added by Robin Mills almost 8 years ago

You can build exiv2 with Visual Studio in two ways:
  1. In <exiv2dir>/msvc you'll find projects to build 32 bit libraries
  2. In <exiv2dir>/msvc64 you'll find projects to build 32 and 64 bit libraries.

Both msvc and msvc64 will build static and dynamic libraries in debug and release mode.

You can use Qt with Visual Studio in two ways:

  1. With QtCreator and defining the tool chain to build with Visual Studio 2008
  2. With Visual Studio with the Visual Studio Qt Plugin installed into Visual Studio

Qt offer SDKs and downloads which are platform specific because of the library name mangling/linking issue explained above.

I like Visual Studio a lot. However when working in Qt, I prefer to work in QtCreator because using the same set of tools everywhere is easier on my old brain! It's your choice - 2 roads to success.

Robin

RE: Windows libraries - Added by Mateusz P. almost 8 years ago

Thank you, Robin!
Your answer clarify everything what was unclear to me. Your posts are very informative, not only this one :)

RE: Windows libraries - Added by Mateusz P. almost 8 years ago

I gave a try to procedure explained in ReadMe.txt.
Unfortunately have problems with build...
I have created a C:/gnu directory and placed 3 locations:
C:/gnu/exiv2-0.23
C:/gnu/expat-2.1.0
C:/gnu/zlib-1.2.7

I open C:/gnu/exiv2-0.23/msvc64/exiv.sln. I use Visual Studio 2008 in that purpose, and perfoms as it is stated in this point of ReadMe.txt :

1.3 Open exiv2\msvc64\exiv2.sln (here the conversion wizard does the job without errors )
Projects are zlib, expat, xmpsdk, exiv2lib, exiv2
Build/Batch build... Select All, Build
- 5 projects (zlib, expat, xmpsdk, exiv2lib, exiv2)
x 2 Platforms (x64|Win32)
x 4 Configurations (Debug|Release|DebugDLL|ReleaseDLL) = 5x2x4 = 40 builds.
The build process begins and the following errors occur:

Error 1 fatal error C1083: Cannot open source file: '..\..\..\expat-2.0.1\lib\xmlparse.c': No such file or directory c1 expat
Error 2 fatal error C1083: Cannot open source file: '..\..\..\expat-2.0.1\lib\xmltok_ns.c': No such file or directory c1 expat
Error 3 fatal error C1083: Cannot open source file: '..\..\..\expat-2.0.1\lib\xmltok_impl.c': No such file or directory c1 expat
Error 4 fatal error C1083: Cannot open source file: '..\..\..\expat-2.0.1\lib\xmltok.c': No such file or directory c1 expat
Error 5 fatal error C1083: Cannot open source file: '..\..\..\expat-2.0.1\lib\xmlrole.c': No such file or directory c1 expat
Error 6 fatal error LNK1181: cannot open input file '..\expat\Win32\Release\libexpat.lib' exiv2 exiv2

I do not know if the Windows build issues are discussed here in forum or should I ask you, Robin, via e-mail.
Perhaps I miss some kind of setting here. I've tried to set manually in project properties the Additional Include Directories where I changed the location of expat libraries to C:/gnu/expat-2.1.0/lib. Although it did not help, the errors returned were the same as above.
Any clue I would appreciate.

RE: Windows libraries - Added by Mateusz P. almost 8 years ago

Never mind,
I have found the problem.
The expat version I downloaded was slightly different. Now it builds libraries correct.

RE: Windows libraries - Added by Robin Mills almost 8 years ago

I think you have discovered the solution. From the output you've provided, I believe you're using exiv2 0.23 which builds with expat-2.0.1 and zlib-1.2.3.

Since May 2012, the trunk builds with expat-2.1.0 and zlib-1.2.7. It is possible to build the trunk with 2.0.1 and 1.2.3 - there's a python script 'setbuild.py' to modify the Visual Studio projects appropriately.

Robin

RE: Windows libraries - Added by Mateusz P. almost 8 years ago

Yes, indeed I have build all configurations of exiv2 with Visual Studio 2008 properly.
I have the following locations:
exiv2lib\Win32\{Debug|Release|DebugDLL|ReleaseDLL} 32 bit builds
exiv2lib\x64\{Debug|Release|DebugDLL|ReleaseDLL} 64 bit builds

Now on, as it is said in ReadMe I would use them for "foreign" project.
I work with QtCreator and Qt under Windows 7. The tool chain I need to use to build is Visual Studio 2008 (QMAKESPEC, -spec win32-msvc2008).
I would like to be able to in both ways, statically and dynamically. I am mostly interested in the release mode.
Have managed to build dynamically with obtained library files.

The issue I have with static linking. I wasn't able to successfully link with static libs.
In Release folder there is only one file - exiv2s.lib file so I copied libexpat.lib and zlib1.lib from Release directories of each one.
My qmake looks as follows:

win32 {
INCLUDEPATH += ../exiv2/include
INCLUDEPATH += ../exiv2/include/exiv2
LIBS += ../exiv2lib/Win32/Release/exiv2s.lib
LIBS += ../exiv2lib/Win32/Release/libexpat.lib
LIBS += ../exiv2lib/Win32/Release/zlib1.lib
}

However I am getting an error during compilation:
The system cannot find the path specified.
jom: ..\Testproject\Makefile.Release [release\Testproject.exe] Error 1
jom: ..\Testproject\Makefile [release] Error 2
08:35:29: The process "..\jom.exe" exited with code 2.
Error while building/deploying project Testproject (target: )

I am clueless. I miss something definitely. Maybe I should ad something to my qmake so my project can build properly?
I would appreciate your help here.

RE: Windows libraries - Added by Robin Mills almost 8 years ago

Yes, you've discovered that our library file names are "decorated" with s and d for debug/static. I personally don't like this convention because it makes the libraries build specific and you can't simply swap debug/release. However an exiv2 commercial client requested this and we did this for him.

I can't say immediately what's up. I haven't following in project I did a couple of years ago with exiv2/mingw:

LIBS         += $$quote(C:/MinGW/msys/1.0/local/lib/libexiv2.dll.a)

Take a look at the QMake documentation and you'll see what $$quote does. You'll also see that I didn't use relative paths ../exiv2lib because I don't understand MinGW. So I manually copied the library to a fixed location and linked it directly.

As you're using MSVC, the filenames to link are different and the ones you've chosen look about right. You might not have to link libexpat.lib and zlib1.lib when you link the statically. However you will have to link them to use the DLL. Windows links a "stub" library for every DLL. Stubs know how to load and use the DLL at run time - so they are small.

C:\gnu.test>grep zlib1\.lib$ theLot.txt
      171952 .\exiv2\msvc64\zlib\x64\release\zlib1.lib
       14900 .\exiv2\msvc64\zlib\x64\releasedll\zlib1.lib
       14900 .\exiv2\msvc64\exiv2lib\x64\ReleaseDLL\zlib1.lib
       15260 .\exiv2\msvc64\exiv2lib\Win32\ReleaseDLL\zlib1.lib
      120780 .\exiv2\msvc64\zlib\win32\release\zlib1.lib
       15260 .\exiv2\msvc64\zlib\win32\releasedll\zlib1.lib  <--- He's in zlib\win32\releaseDLL not exiv2lib 

C:\gnu.test>grep libexpat\.lib$ theLot.txt
       17238 .\exiv2\msvc64\exiv2lib\Win32\DebugDLL\libexpat.lib
       17238 .\exiv2\msvc64\exiv2lib\Win32\ReleaseDLL\libexpat.lib
       16928 .\exiv2\msvc64\exiv2lib\x64\DebugDLL\libexpat.lib
       16928 .\exiv2\msvc64\exiv2lib\x64\ReleaseDLL\libexpat.lib
      611854 .\exiv2\msvc64\expat\win32\debug\libexpat.lib
       17238 .\exiv2\msvc64\expat\win32\debugdll\libexpat.lib
      233134 .\exiv2\msvc64\expat\win32\release\libexpat.lib
       17238 .\exiv2\msvc64\expat\win32\releasedll\libexpat.lib
      569860 .\exiv2\msvc64\expat\x64\debug\libexpat.lib
       16928 .\exiv2\msvc64\expat\x64\debugdll\libexpat.lib
      394036 .\exiv2\msvc64\expat\x64\release\libexpat.lib 
       16928 .\exiv2\msvc64\expat\x64\releasedll\libexpat.lib
       17238 .\expat-2.0.1\win32\bin\debug\libexpat.lib
       17238 .\expat-2.0.1\win32\bin\release\libexpat.lib <--- He's in expat-2.0.1\win32\bin\release NOT exiv2lib

If you're still stuck, perhaps you can zip your project and send it to me. Please remove all the .ncb .pdb .ilk .obj .exe .dll and other temporary files created by MSVC. And don't send the exiv2 code! Your zip file should be be 500k of less. Email:

RE: Windows libraries - Added by Robin Mills almost 8 years ago

I have my library filenames a little mixed in the previous post For static/release/win32, you should be link.

      120780 .\exiv2\msvc64\zlib\win32\release\zlib1.lib            <<--- He's in zlib NOT exiv2lib
     233134 .\exiv2\msvc64\expat\win32\release\libexpat.lib     <<--- He's in expat NOT exiv2lib

For dynamic/releasedll/win32, you should link:
      120780 .\exiv2\msvc64\zlib\win32\releasedll\zlib1.lib            <<--- He's in zlib NOT exiv2lib
     233134 .\exiv2\msvc64\expat\win32\releasedll\libexpat.lib     <<--- He's in expat NOT exiv2lib

RE: Windows libraries - Added by Robin Mills almost 8 years ago

Good News:

I've been able to build exiv2.exe with the following project using the static binding.

#-------------------------------------------------
#
# Project created by QtCreator 2012-11-15T16:07:07
#
#-------------------------------------------------

TARGET    = exiv2

QT       += core
QT       -= gui

# http://stackoverflow.com/questions/1011197/qt-static-linking-and-deployment
CONFIG   += static
CONFIG   += console
CONFIG   -= app_bundle

TEMPLATE  = app

win32 {
    # http://www.formortals.com/build-qt-static-small-microsoft-intel-gcc-compiler/
    QMAKE_CFLAGS_RELEASE =  /D "WIN32" /D "_NDEBUG" /D "_CONSOLE" /D "BUILD_GETOPT" /D "_MBCS" /FD /EHsc /MD /W3 /WX

    INCLUDEPATH  += $$quote(C:/gnu.test/exiv2/msvc64/include)
    LIBS         += $$quote(C:/gnu.test/exiv2/msvc64/exiv2lib/Win32/release/exiv2s.lib)
    LIBS         += $$quote(C:/gnu.test/exiv2/msvc64/xmpsdk/win32/release/xmpsdk.lib)
    LIBS         += $$quote(C:/gnu.test/exiv2/msvc64/expat/Win32/Release/libexpat.lib)
    LIBS         += $$quote(C:/gnu.test/exiv2/msvc64/zlib/Win32/Release/zlib1.lib)

    #QMAKE_LFLAGS_RELEASE += /NODEFAULTLIB:msvcprt.lib
    #QMAKE_LFLAGS_RELEASE += /NODEFAULTLIB:msvcrt.lib
    #QMAKE_LFLAGS_RELEASE += /SUBSYSTEM:CONSOLE /OPT:REF /OPT:ICF /MACHINE:X86
    #LIBS         += libcmt.lib
}

SOURCES += $$quote(C:/gnu.test/exiv2/src/exiv2.cpp) \
$$quote(C:/gnu.test/exiv2/src/actions.cpp)      \
$$quote(C:/gnu.test/exiv2/src/getopt_win32.c)   \
$$quote(C:/gnu.test/exiv2/src/localtime.c)      \
$$quote(C:/gnu.test/exiv2/src/utils.cpp)

# That's all Folks!
##

When you run exiv2 -v -V (verbose version) it reports:

... bla bla bla ...

exiv2=0.23.0
platform=windows
compiler=MSVC
bits=4
dll=0
debug=0
version=9.00
date=Nov 16 2012
time=09:32:42
executable=C:\Robin\Projects\simple-build-desktop-Qt_4_8_3__vs-2008__Release\release\exiv2.exe
library=C:\Windows\SysWOW64\ntdll.dll
library=C:\Windows\syswow64\kernel32.dll
library=C:\Windows\syswow64\KERNELBASE.dll
library=C:\Windows\WinSxS\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.6161_none_50934f2ebcb7eb57\MSVCP90.dll
library=C:\Windows\WinSxS\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.6161_none_50934f2ebcb7eb57\MSVCR90.dll
library=C:\Windows\syswow64\PSAPI.DLL

C:\Robin\Projects\simple-build-desktop-Qt_4_8_3__vs-2008__Release\release>

I had to modify the exiv2/msvc64 build environment to use /MD (use DLL run-time c library) on projects zlib, expat, xmpsdk and exiv2lib.

I'll update ReadMe.txt about this over the weekend. I'll also review and update the build instructions appropriately on this page:

http://dev.exiv2.org/projects/exiv2/wiki/How_do_I_build_Exiv2_on_the_XYZ_platform

    (1-11/11)