Exiv2 / exiv2

Image metadata library and tools
http://www.exiv2.org/
Other
921 stars 278 forks source link

Exiv2 0.27.1 in msvc 2017 static build #814

Closed Simon-12 closed 5 years ago

Simon-12 commented 5 years ago

Hey, i built successfully exiv 0.27.1 with the given conan step-by-step guide. Also got some examples working in Visual Studio 2017.

Then I tried to build static libraries, also following the given instructions:

Afterwards I repeated the previous guide. After the last step I get 29 Warnings. Something like “LNK4098 defaultlib ‘LIBCMT conflicts with use of other libs’…” (see the attached screenshot).

warning

Then when I try to build my previous test application I get the following linker errors “LNK2001 unresolved external symbol ...”:

LNK2001 unresolved external symbol compress \exiv2.lib(pngimage.obj) LNK2001 unresolved external symbol uncompress \exiv2.lib(pngimage.obj) LNK2001 unresolved external symbol uncompress \exiv2.lib(pngchunk_int.obj) LNK2001 unresolved external symbol crc32 \exiv2.lib(pngimage.obj)
LNK2001 unresolved external symbol crc32 \exiv2.lib(pngchunk_int.obj)
LNK2001 unresolved external symbol compress2 \exiv2.lib(pngchunk_int.obj)
LNK2001 unresolved external symbol libiconv_open \exiv2.lib(convert.obj)
LNK2001 unresolved external symbol libiconv \exiv2.lib(convert.obj)
LNK2001 unresolved external symbol libiconv_close \exiv2.lib(convert.obj)
LNK2001 unresolved external symbol XML_ParserCreateNS \exiv2-xmp.lib(ExpatAdapter.obj) LNK2001 unresolved external symbol XML_SetElementHandler \exiv2-xmp.lib(ExpatAdapter.obj)
LNK2001 unresolved external symbol XML_SetCharacterDataHandler \exiv2-xmp.lib(ExpatAdapter.obj)
LNK2001 unresolved external symbol XML_SetProcessingInstructionHandler \exiv2-xmp.lib(ExpatAdapter.obj)
LNK2001 unresolved external symbol XML_SetCommentHandler \exiv2-xmp.lib(ExpatAdapter.obj)
LNK2001 unresolved external symbol XML_SetCdataSectionHandler \exiv2-xmp.lib(ExpatAdapter.obj) LNK2001 unresolved external symbol XML_SetStartDoctypeDeclHandler \exiv2-xmp.lib(ExpatAdapter.obj) LNK2001 unresolved external symbol XML_SetNamespaceDeclHandler \exiv2-xmp.lib(ExpatAdapter.obj)
LNK2001 unresolved external symbol XML_SetUserData \exiv2-xmp.lib(ExpatAdapter.obj)
LNK2001 unresolved external symbol XML_Parse \exiv2-xmp.lib(ExpatAdapter.obj)
LNK2001 unresolved external symbol XML_StopParser \exiv2-xmp.lib(ExpatAdapter.obj) LNK2001 unresolved external symbol XML_ParserFree \exiv2-xmp.lib(ExpatAdapter.obj) LNK1120 19 unresolved externals \x64\Release\Exiv2Test.exe

What kind of small detail I missed?

D4N commented 5 years ago

Try to follow the steps from appveyor.yml, there it works. My guess is that compiler.runtime = MT is the culprit, but I can't verify that, I'm not a Windows user myself.

clanmills commented 5 years ago

I think the warning about LIBCMT is because you are using different Run Time Libraries in a different parts of the build. We used to support Visual Studio Solution/Project files and I took the decision "All DLLs or No DLLs". So, setting MT for static is exactly what we used to do.

I see the warning unresolved external symbol compress refers to an entry point in ZLIB, so I think that's there something wrong with the build of ZLIB.

Conan either builds from source or downloads a pre-built binary. So, I'm a little surprised that this is causing difficulty.

I think @D4N is correct. Try setting compiler.runtime = MD to use the shared run-time library.

I'm just out of bed this morning (not feeling very well). I'll crawl though some other correspondence then fire up Windows and investigate. If you find the fix before me, please given an update.

Simon-12 commented 5 years ago

Hey, thank you for the very fast response. ZLIB is a good point. I searched for the "zlib.lib" and found it in the conan directory. I copied then the zlib.lib and expat.lib to the exiv2 folder. Afterwards i add both to the MSVC Linker-Input property.

Now the error messages reduced to 3: LNK2001 unresolved external symbol libiconv_open \exiv2.lib(convert.obj)
LNK2001 unresolved external symbol libiconv \exiv2.lib(convert.obj)
LNK2001 unresolved external symbol libiconv_close \exiv2.lib(convert.obj)

I got no clue what libiconv is and do not find it in any directory.

@clanmills hope you get well soon.

clanmills commented 5 years ago

I'm feeling fine now, thank you. Some fruit and cereal for breakfast and about 50 emails have changed the day!

libiconv is used to convert characters set. I think there's a option to say "don't bother with iconv" however I can't see it immediately. Try building without NLS (natural language support). `-DEXIV2_ENABLE_NLS=False'

My understanding of conan is that you shouldn't need to copy anything because that's what Mr Conan does!

There's a note in README.md in 5.4 Cygwin:

Download and build libiconv-1.15: https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.15.tar.gz

You're almost there. I'm going to cut the grass because it's a beautiful summer's day in England. I'll be back in an hour.

Simon-12 commented 5 years ago

Thanks again for the fast response.

With -DEXIV2_ENABLE_NLS=False there is also no success. Maybe conan hides the file somewhere. I think i have to rebuild the libconv. But not today. The sun here in germany shine bright as well!

clanmills commented 5 years ago

@Simon-12 I've got this to build "out of the box" by following the notes in README-CONAN.md. I created a static profile for msvc2017StaticRelease64 and set MT. I get the ugly warnings about LIBCMT, however they are warnings. The build passes the test suite.

I've investigated ICONV. The cmake code searches for libiconv and doesn't find it on Windows. It reports Could not find Iconv (missing Iconv_LIBRARY Iconv_INCLUDE_DIR) and proceeds to build without libiconv. I don't remember exactly what that does, however it's a marginal feature for most users.

I'll investigate the LIBCMT warning and update you this evening. I've forgotten what that's about. It's something such as zlib and expat have been build with a copy of LIBC already linked.

clanmills commented 5 years ago

@Simon-12 I've investigated the LIBCMT warning. I'm not convinced that Conan/CMake is setting the MT linking flag when it builds the exiv2 library. We appear to have a mix of /MT and /MD code. When I run the following command on the built exiv2 command line:

c:\Users\rmills\gnu\github\exiv2\0.27-maintenance\build\bin>exiv2 -vV | grep -e msvc -e dll -e crt -e version -e exiv2
exiv2 0.27.1
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
exiv2=0.27.1
dll=0
version=13.16 (2017/x64)
processpath=C:\Users\rmills\gnu\github\exiv2\0.27-maintenance\build\bin
package_name=exiv2
executable=c:\Users\rmills\gnu\github\exiv2\0.27-maintenance\build\bin\exiv2.exe
library=C:\WINDOWS\SYSTEM32\ntdll.dll
...
library=C:\WINDOWS\System32\msvcp_win.dll
library=C:\WINDOWS\System32\ucrtbase.dll
...
config_path=C:\Users\rmills\exiv2.ini

c:\Users\rmills\gnu\github\exiv2\0.27-maintenance\build\bin>

There's strong evidence that it's using the dynamic run-time. So the warning boils down to "Make up your mind, you can't use both static and dynamic run-time." and proceeds to use dynamic run-time. The fact that it passes the test suite is encouraging. The build is good.

Now we need to decide what to do: Option 1: You reproduce the build. The build is static with dynamic run-time. We close this issue. Option 2: I have to investigate why Conan/CMake/Visual Studio has ignore the MT setting when building libexiv2.

What would you like to happen next?

clanmills commented 5 years ago

I've investigated why the build is using the dynamic runtime. It's because we have to use the option -DEXIV2_ENABLE_DYNAMIC_RUNTIME=False. So, for me, the CMake command is:

cmake .. -G "Visual Studio 15 2017 Win64"  -DBUILD_SHARED_LIBS=Off -DEXIV2_ENABLE_DYNAMIC_RUNTIME=False

And the output of the command is:

-- Selecting Windows SDK version 10.0.17763.0 to target Windows 10.0.17134.                                                                                                                                                                                                                            
-- Conan: Using cmake targets configuration                                                                                                                                                                                                                                                            
-- Library zlib found C:/Users/rmills/.conan/data/zlib/1.2.11/conan/stable/package/7bd6f2c3d5c4e48a75805376b58cde753392f711/lib/zlib.lib                                                                                                                                                               
-- Library gmock_main found C:/Users/rmills/.conan/data/gtest/1.8.1/bincrafters/stable/package/965725edb51e5d857f68b90ab9a327b10174ca55/lib/gmock_main.lib                                                                                                                                             
-- Library gmock found C:/Users/rmills/.conan/data/gtest/1.8.1/bincrafters/stable/package/965725edb51e5d857f68b90ab9a327b10174ca55/lib/gmock.lib                                                                                                                                                       
-- Library gtest found C:/Users/rmills/.conan/data/gtest/1.8.1/bincrafters/stable/package/965725edb51e5d857f68b90ab9a327b10174ca55/lib/gtest.lib                                                                                                                                                       
-- Library expat found C:/Users/rmills/.conan/data/Expat/2.2.6/pix4d/stable/package/67c9d2d36e127fc98ea434a51f318c146435f71d/lib/expat.lib                                                                                                                                                             
-- Conan: Adjusting language standard                                                                                                                                                                                                                                                                  
-- Current conanbuildinfo.cmake directory: C:/Users/rmills/gnu/github/exiv2/0.27-maintenance/build                                                                                                                                                                                                     
-- Found EXPAT: C:/Users/rmills/.conan/data/Expat/2.2.6/pix4d/stable/package/67c9d2d36e127fc98ea434a51f318c146435f71d/lib/expat.lib (found version "2.2.6")                                                                                                                                            
-- Could NOT find Iconv (missing: Iconv_LIBRARY Iconv_INCLUDE_DIR)                                                                                                                                                                                                                                     
-- MSVC -> forcing use of statically-linked runtime. 
...

I'm a little surprised that we have to tell CMake to use Static Run-time, when the MT option is known to conan from the profile. I'll ask @piponazo to comment on this. If he provides a strong reason for this behaviour, I'll add a note in README-CONAN.md to highlight this.

Having done all of this, the run-time DLL is in memory. I suspect this is because it's required by one of the other DLLs in the process space.

c:\Users\rmills\gnu\github\exiv2\0.27-maintenance\build>bin\exiv2.exe --verbose --version --grep library --grep exiv2 --grep version --grep dll                                                                                                                                                        
exiv2 0.27.1                                                                                                                                                                                                                                                                                           
exiv2=0.27.1                                                                                                                                                                                                                                                                                           
dll=0                                                                                                                                                                                                                                                                                                  
version=13.16 (2017/x64)                                                                                                                                                                                                                                                                               
processpath=C:\Users\rmills\gnu\github\exiv2\0.27-maintenance\build\bin                                                                                                                                                                                                                                
package_name=exiv2                                                                                                                                                                                                                                                                                     
executable=c:\Users\rmills\gnu\github\exiv2\0.27-maintenance\build\bin\exiv2.exe                                                                                                                                                                                                                       
library=C:\WINDOWS\SYSTEM32\ntdll.dll                                                                                                                                                                                                                                                                  
library=C:\WINDOWS\System32\KERNEL32.DLL                                                                                                                                                                                                                                                               
library=C:\WINDOWS\System32\KERNELBASE.dll                                                                                                                                                                                                                                                             
library=C:\Program Files\Bitvise SSH Server\totermh64.dll                                                                                                                                                                                                                                              
library=C:\WINDOWS\System32\USER32.dll                                                                                                                                                                                                                                                                 
library=C:\WINDOWS\System32\win32u.dll                                                                                                                                                                                                                                                                 
library=C:\WINDOWS\System32\GDI32.dll                                                                                                                                                                                                                                                                  
library=C:\WINDOWS\System32\gdi32full.dll                                                                                                                                                                                                                                                              
library=C:\WINDOWS\System32\msvcp_win.dll                                                                                                                                                                                                                                                              
library=C:\WINDOWS\System32\ucrtbase.dll                                                                                                                                                                                                                                                               
library=C:\WINDOWS\System32\ADVAPI32.dll                                                                                                                                                                                                                                                               
library=C:\WINDOWS\System32\msvcrt.dll                                                                                                                                                                                                                                                                 
library=C:\WINDOWS\System32\sechost.dll                                                                                                                                                                                                                                                                
library=C:\WINDOWS\System32\RPCRT4.dll                                                                                                                                                                                                                                                                 
library=C:\WINDOWS\System32\PSAPI.DLL                                                                                                                                                                                                                                                                  
library=C:\WINDOWS\System32\WS2_32.dll                                                                                                                                                                                                                                                                 
library=C:\WINDOWS\System32\SHELL32.dll                                                                                                                                                                                                                                                                
library=C:\WINDOWS\System32\cfgmgr32.dll                                                                                                                                                                                                                                                               
library=C:\WINDOWS\System32\shcore.dll                                                                                                                                                                                                                                                                 
library=C:\WINDOWS\System32\combase.dll                                                                                                                                                                                                                                                                
library=C:\WINDOWS\System32\bcryptPrimitives.dll                                                                                                                                                                                                                                                       
library=C:\WINDOWS\System32\windows.storage.dll                                                                                                                                                                                                                                                        
library=C:\WINDOWS\System32\shlwapi.dll                                                                                                                                                                                                                                                                
library=C:\WINDOWS\System32\kernel.appcore.dll                                                                                                                                                                                                                                                         
library=c:\Users\rmills\gnu\github\exiv2\0.27-maintenance\build\bin\exiv2.exe                                                                                                                                                                                                                          
library=c:\Users\rmills\gnu\github\exiv2\0.27-maintenance\build\bin\exiv2.exe                                                                                                                                                                                                                          
library=c:\Users\rmills\gnu\github\exiv2\0.27-maintenance\build\bin\exiv2.exe                                                                                                                                                                                                                          
config_path=C:\Users\rmills\exiv2.ini                                                                                                                                                                                                                                                                  

c:\Users\rmills\gnu\github\exiv2\0.27-maintenance\build>  
piponazo commented 5 years ago

Hi guys. I remember that I spend some time deciding what to do with the SHARED/STATIC builds and with that RUNTIME cmake option that was there before I started touching the CMake code.

The last change I did in that are was this one (See commit message for more info): https://github.com/Exiv2/exiv2/commit/dc086d2ebbb04817458b214708c5038600e96095#diff-a3d2e567cb209e245e5e6bd88320d823

I thought about using the static runtime when passing -DBUILD_SHARED_LIBS=OFF but this originated other issues due to the EXPAT dependency. That's why I left both options (BUILD_SHARED_LIBS and EXIV2_ENABLE_DYNAMIC_RUNTIME), to give more freedom to the consumer of Exiv2.

I'm a little surprised that we have to tell CMake to use Static Run-time, when the MT option is known to conan from the profile. I'll ask @piponazo to comment on this. If he provides a strong reason for this behaviour, I'll add a note in README-CONAN.md to highlight this.

Note that conan is totally independent from CMake in that sense. We just use it to bring the dependencies to our local system, so that CMake can find them with its own mechanisms (find_package , find_library , etc). If we chose MT in conan, we have to match the runtime in CMake by passing -DEXIV2_ENABLE_DYNAMIC_RUNTIME=OFF. If this is not documented, it would be good to add some comments about it 👍

clanmills commented 5 years ago

Thanks @piponazo

I will clarify this in README-CONAN.md and submit a PR. It'll be released in Exiv2 v0.27.2 currently scheduled for 2019-06-30.