4

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

Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182
grisevg
  • 250
  • 3
  • 18
  • 1
    is the lib a static library or is it a lib to a dll? – user1810087 Jul 26 '16 at 14:33
  • @user1810087 how do I check? – grisevg Jul 26 '16 at 14:44
  • 1
    you must link to the static version of opencv. In the prebuild openCV folders there typically are 3 folders, for example in my 32 bit opencv 2.4.11 there are `x86/vc12/bin` `x86/vc12/lib` and `x86/vc12/staticlib` you must choose the libraries in the `staticlib` folder. – Micka Jul 26 '16 at 14:45
  • 1
    so for you it should be `x64/vc14/staticlib/` if that foler isn't existing you'll have to compile static linked opencv yourself. – Micka Jul 26 '16 at 14:47
  • @Micka riiight, so the libs in `lib` folder are just stubs that redirect it to a dll? – grisevg Jul 26 '16 at 14:54
  • 1
    more or less right... read [implicit linking](https://msdn.microsoft.com/en-us/library/d14wsce5.aspx) for more detail. – user1810087 Jul 26 '16 at 14:56
  • 1
    @grisevg for visual c++ it's the typicaly process for shared libaries to have some header, some libs (needed at compiletime) and some dlls (needed at runtime). You'll probably find some information of what exactly the libs are needed/used in that case. – Micka Jul 26 '16 at 14:58
  • Thank guys, that answers it. If you convert comment to an answer, I'll accept it. – grisevg Jul 26 '16 at 15:01
  • @user1810087 feel free to write the answer if you like. Maybe you can add some additional information about WHY there are .lib and .dll s in the dynamic linking. – Micka Jul 26 '16 at 15:31

2 Answers2

3

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.

Community
  • 1
  • 1
user1810087
  • 5,146
  • 1
  • 41
  • 76
0

I linked my Node.js C++ add-on, which is a shared library, against opencv-4.6.0/build/x64/vc15/lib/opencv_world460.lib from OpenCV’s official releases. It turned out it was just an import library, which simply loads the DLL (dynamic library), that is opencv-4.6.0/build/x64/vc15/bin/opencv_world460.dll.

lib /list opencv_world460.lib
Microsoft (R) Library Manager Version 14.16.27044.0
Copyright (C) Microsoft Corporation.  All rights reserved.

opencv_world460.dll
opencv_world460.dll
opencv_world460.dll
opencv_world460.dll
opencv_world460.dll
opencv_world460.dll
opencv_world460.dll
opencv_world460.dll
opencv_world460.dll
opencv_world460.dll
opencv_world460.dll
opencv_world460.dll
opencv_world460.dll
opencv_world460.dll
opencv_world460.dll
opencv_world460.dll
opencv_world460.dll
opencv_world460.dll
opencv_world460.dll
opencv_world460.dll
opencv_world460.dll
opencv_world460.dll
opencv_world460.dll
…

This means that, to get the static library of OpenCV, I need to build my own OpenCV with the BUILD_SHARED_LIBS flag turned off: cmake -DBUILD_SHARED_LIBS=OFF ….

Well, alright….