Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does my program ask for OpencV's .dll even though I link statically against its .lib

I'm building a small program that's using OpenCV 3.1 with CMake 3.5 and Visual Studio 2015 x64.

I link against OpenCV's .lib file, but when I try to run the program I get an error about a missing DLL:

MyApp.exe: error while loading shared libraries: opencv_world310d.dll: cannot open shared object file: No such file or directory

Here's my CMakeLists.txt:

cmake_minimum_required(VERSION 3.5)
project (MyProj)

set(CMAKE_FIND_LIBRARY_SUFFIXES, ".lib")

#Boost
set(Boost_USE_STATIC_LIBS        ON)
set(Boost_USE_MULTITHREADED      ON)
set(Boost_USE_STATIC_RUNTIME    OFF)
find_package(Boost REQUIRED system thread serialization filesystem)

#OpenCV
find_package(OpenCV REQUIRED)

add_executable(
        MyApp
        main.cpp
)

target_include_directories(MyApp PRIVATE
        ${OpenCV_INCLUDE_DIRS}
        ${Boost_INCLUDE_DIRS}
)

target_link_libraries(MyApp
        ${OpenCV_LIBRARIES}
        ${Boost_LIBRARIES}
)

OpenCV_DIR is set to C:\tools\opencv3\build\x64\vc14\lib which has include/ opencv_world310.lib opencv_world310d.lib OpenCVConfig.cmake OpenCVModules.cmake OpenCVModules-debug.cmake OpenCVModules-release.cmake and is extracted from official Windows binaries of OpenCV v3.1

Then I generate VS solution with cmake . -G "Visual Studio 14 Win64"

As you can see, OpenCV lib was added to dependencies: enter image description here

And is used in the linking step:

Link:
  C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\x86_amd64\link.exe /ERRORREPORT:QUEUE /OUT:"C:\...\Debug\MyApp.exe" /
  INCREMENTAL /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib 
  advapi32.lib C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib 
  C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib 
  C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib 
  C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib 
  C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib 
  C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib 
  C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib 
  C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib 
  C:\tools\opencv3\build\x64\vc14\lib\opencv_world310d.lib "C:\tools\boost_1_61_0\stage\lib\libboost_system-vc140-mt-gd-1_61.lib" 
  "C:\tools\boost_1_61_0\stage\lib\libboost_thread-vc140-mt-gd-1_61.lib" 
  "C:\tools\boost_1_61_0\stage\lib\libboost_serialization-vc140-mt-gd-1_61.lib" 
  "C:\tools\boost_1_61_0\stage\lib\libboost_filesystem-vc140-mt-gd-1_61.lib" 
  "C:\tools\boost_1_61_0\stage\lib\libboost_chrono-vc140-mt-gd-1_61.lib" 
  "C:\tools\boost_1_61_0\stage\lib\libboost_date_time-vc140-mt-gd-1_61.lib" 
  "C:\tools\boost_1_61_0\stage\lib\libboost_atomic-vc140-mt-gd-1_61.lib" /MANIFEST /MANIFESTUAC:"level='asInvoker' 
  uiAccess='false'" /manifest:embed /DEBUG /PDB:"C:/Users/.../Debug/MyApp.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /
  IMPLIB:"C:/Users/.../Debug/MyApp.lib" /MACHINE:X64  /machine:x64 MyApp.dir\Debug\sheepface.obj MyApp.dir\Debug\source.obj
  MyApp.vcxproj -> C:\Users\...\Debug\MyApp.exe
  MyApp.vcxproj -> C:/Users/.../Debug/MyApp.pdb (Full PDB)

I already tried setting magical variables

set(OpenCV_STATIC ON)
set(BUILD_SHARED_LIBS     OFF)

but they made no difference

like image 896
grisevg Avatar asked Oct 17 '25 11:10

grisevg


1 Answers

You have three different alternatives to create and use a library; static, dynamic implicit and dynamic explicit. A library.lib is not necessarily a static library which will contain the compiled code as you expected. It either contains the code or (simply said) contains the name of the required *.dll, which is loaded by the OS, and the entry points to the functions inside this dll. If you don't know what kind of lib the particular library is, you can use

lib /list foo.lib

(see here) to determine the type of the lib. If it is a static lib it will show you some .obj files used while creating the lib. If it is an import lib, it will show you the required .dll you should provide. The dll itself should in one of the search paths. It can become quite complex if you want to use some special path, but the simplest is to put it into the same folder as the executable which is using it or the system folder. Read Dynamic-Link Library Search Order for more detail. Both, the static lib and the implicit dynamic you will need a header file and a .lib file.

The third way (dynamic explicit) you have to use LoadLibrary[AW], GetProcAddress and FreeLibrary. Here you specify the path to the dll and use the dll "directly". You don't have any headers or .lib files but have to know exactly how the functions are named and how they are declared (return and parameter value types) otherwise your program won't work as expected.

You can find more information on dll's on MSDN.

like image 143
user1810087 Avatar answered Oct 19 '25 02:10

user1810087



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!