c++visual-studioopencvcmakeunresolved-external

How to correctly link OpenCV release and debug libraries in cmake with visual studio generator


I have a project (minimal reproducable example can be found here) which i am building with cmake and use "Visual Studio 17 2022" generator. In this project i include OpenCV *.lib and *.dll files so that users of this project don't have to compile/install OpenCV themeselves. I want to be able to build this project in release and debug modes. Since i am using Visual Studio as my generator, which is a multi configuration generator, i do not want to use the variable CMAKE_BUILD_TYPE since it shouldn't do anything for these types of generators (please correct me if i am wrong here). So instead of using CMAKE_BUILD_TYPE i use the variable CMAKE_CONFIGURATION_TYPES which is set in my toplevel CMakeLists.txt to "Release;Debug".

When i configure the project with cmake i use this line:

cmake.exe -S . -B build -A x64

now when i build this project in Release mode everything works fine. I build it using this command:

cmake.exe --build build --config Release --target install

The trouble begins when i want to build the project in debug mode:

cmake.exe --build build --config Debug --target install

which produces the following error message

main.obj : error LNK2019: unresolved external symbol "void __cdecl cv::imshow(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class cv::debug_build_guard::_InputArray const &)" (?imshow@cv@@YAXAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEBV_InputArray@debug_build_guard@1@@Z) referenced in function main
[D:\Projekte\OpenCVLinkerTest\build\apps\app1\app1.vcxproj]
D:\Projekte\OpenCVLinkerTest\build\apps\app1\bin\Debug\app1.exe : fatal error LNK1120: 1 unresolved externals [D:\Projekte\OpenCVLinkerTest\build\apps\app1\a
pp1.vcxproj]

note the specific class cv::debug_build_guard which is unresolved. My guess at the moment is that i can not link OpenCV release libraries with my debug build. So therefore i included OpenCV debug libraries in the lib folder in the repo i linked above. now i have two folders in lib: lib/opencv/debug and lib/opencv/release which both have OpenCVConfig.cmake files in them.

What i do not understand is how do i correctly pick the right library within my CMakeLists.txt. Currently i do this:

find_package(OpenCV REQUIRED
    PATHS 
    "${CMAKE_SOURCE_DIR}/lib/opencv/release"
    "${CMAKE_SOURCE_DIR}/lib/opencv/debug"
)

which just finds the release OpenCVConfig.cmake file i guess and ignores the debug files.

So, how do i do this correctly? Any tips are appreciated.


Solution

  • I figured it out. Since i had the following cmake files in the debug and release subdirectories:

    |lib/opencv/release
    ||OpenCVConfig-version.cmake
    ||OpenCVConfig.cmake
    ||OpenCVModules-release.cmake
    ||OpenCVModules.cmake
    |lib/opencv/debug
    ||OpenCVConfig-version.cmake
    ||OpenCVConfig.cmake
    ||OpenCVModules-debug.cmake
    ||OpenCVModules.cmake
    

    i first checked these files for differences and the only file that's different are the OpenCVModules-<BUILD_TYPE>.cmake files. so i moved the files into lib/opencv/cmake so it looked like this:

    |lib/opencv/cmake
    ||OpenCVConfig-version.cmake
    ||OpenCVConfig.cmake
    ||OpenCVModules-debug.cmake
    ||OpenCVModules-release.cmake
    ||OpenCVModules.cmake
    

    I did this because in the OpenCVModules.cmake i found this line:

    file(glob CONFIG_FILES "${_DIR}/OpenCVModules-*.cmake")
    

    which searches the specific Modules files. after this i changed the find_package directive to:

    find_package(OpenCV REQUIRED PATHS "${CMAKE_SOURCE_DIR}/lib/opencv/cmake")
    

    and now it works.