Problem to compile and link opencv cmake VS community

Hello,

I know it’s probably a common problem sorry for that. Also it’s my first cmake project so probably i did something wrong in my cmake.

My problem is, i try to compile and use opencv 4.6 on a cmake project with QT. the compiler used is msvc 19 but i get link error:

 Error LNK2019	External symbole unsolved "public: __cdecl cv::Mat::~Mat(void)" (??1Mat@cv@@QEAA@XZ)

Error   LNK2019	External symbole unsolved "public: class cv::Mat & __cdecl cv::Mat::operator=(class cv::Mat &&)" (??4Mat@cv@@QEAAAEAV01@$$QEAV01@@Z) 	

Error  LNK2019	External symbole unsolved "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl cv::samples::findFile(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,bool,bool)" (?findFile@samples@cv@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEBV34@_N1@Z) 	

Error  LNK2019	External symbole unsolved "class cv::Mat __cdecl cv::imread(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,int)" (?imread@cv@@YA?AVMat@1@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@Z) 

Error  LNK2019	External symbole unsolved  "int __cdecl cv::waitKey(int)" (?waitKey@cv@@YAHH@Z) 	

Error  LNK2019	External symbole unsolved "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) 



To get this, i followed this procedure:

I firstly downloaded the source code of opencv. then i unzip it into C:/opencv/ then i created a folder build at C:/opencv/opencv-4.6.0/build

I used the gui-cmake app to generate the build with the with_QT selected.

when the generation was done, i just go into the build folder, open OpenCV.sln then generate the ALL_BUILD for release and debug. Finally i generate the INSTALL.

i set the environment variable OpenCV_DIR to C:/opencv/opencv-4.6.0/build

and i made my cmake:

cmake_minimum_required(VERSION 3.5)

project(AstroBase VERSION 0.1 LANGUAGES CXX)

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(FORMS_DIR "${CMAKE_SOURCE_DIR}/AstroBase/forms")
set(INCLUDE_DIR "${CMAKE_SOURCE_DIR}/AstroBase/include")
set(SOURCE_DIR "${CMAKE_SOURCE_DIR}/AstroBase/src")
set(TS_DIR "${CMAKE_SOURCE_DIR}/AstroBase/TS")

set(OpenCV_DIR "C:/opencv/opencv-4.6.0/build")

find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )


include_directories(${FORMS_DIR})
include_directories(${INCLUDE_DIR})
include_directories(${SOURCE_DIR})
include_directories(${TS_DIR})

file(GLOB_RECURSE SOURCES
    "${FORMS_DIR}/*.ui"
    "${FORMS_DIR}/*.qrc"
    "${INCLUDE_DIR}/*.h"
    "${SOURCE_DIR}/*.cpp"
    "${TS_DIR}/*.ts")

find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets LinguistTools)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets LinguistTools)

set(TS_FILES "${TS_DIR}/AstroBase_fr_FR.ts")

set(PROJECT_SOURCES
        "${SOURCE_DIR}/main.cpp"
        "${SOURCE_DIR}/mainwindow.cpp"
        "${INCLUDE_DIR}/mainwindow.h"
        "${FORMS_DIR}/mainwindow.ui"
        
)

if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
    qt_add_executable(AstroBase
        MANUAL_FINALIZATION
        ${PROJECT_SOURCES}
    )
# Define target properties for Android with Qt 6 as:
#    set_property(TARGET AstroBase APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
#                 ${CMAKE_CURRENT_SOURCE_DIR}/android)
# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation

    qt_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
else()
    if(ANDROID)
        add_library(AstroBase SHARED
            ${PROJECT_SOURCES}
        )
# Define properties for Android with Qt 5 after find_package() calls as:
#    set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
    else()
        add_executable(AstroBase
            ${PROJECT_SOURCES}
        )
    endif()

    qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${TS_FILES})
endif()

target_link_libraries(AstroBase PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)

target_link_directories(AstroBase PRIVATE ${OpenCV_LIBS})

set_target_properties(AstroBase PROPERTIES
    MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
    MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
    MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
    MACOSX_BUNDLE TRUE
    WIN32_EXECUTABLE TRUE
)


install(TARGETS AstroBase
    BUNDLE DESTINATION .
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})

if(QT_VERSION_MAJOR EQUAL 6)
    qt_finalize_executable(AstroBase)
endif()

first of all, yes, i set OpenCV_DIR because same if i set this variable as environnement variable, cmake was not able to find it… why? i don’t know.

then i get an error about FindOpenCV.cmake.

to solve this, i just created this file into C:\opencv\opencv-4.6.0\cmake and i just past this code frome internet:


find_path(OpenCV_DIR "OpenCVConfig.cmake" DOC "Root directory of OpenCV")

##====================================================
## Find OpenCV libraries
##----------------------------------------------------
if(EXISTS "${OpenCV_DIR}")

        #When its possible to use the Config script use it.
        if(EXISTS "${OpenCV_DIR}/OpenCVConfig.cmake")

                ## Include the standard CMake script
                include("${OpenCV_DIR}/OpenCVConfig.cmake")

                ## Search for a specific version
                set(CVLIB_SUFFIX "${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}")

        #Otherwise it try to guess it.
        else(EXISTS "${OpenCV_DIR}/OpenCVConfig.cmake")

                set(OPENCV_LIB_COMPONENTS cxcore cv ml highgui cvaux)
                find_path(OpenCV_INCLUDE_DIR "cv.h" PATHS "${OpenCV_DIR}" PATH_SUFFIXES "include" "include/opencv" DOC "")
                if(EXISTS  ${OpenCV_INCLUDE_DIR})
                    include_directories(${OpenCV_INCLUDE_DIR})
                endif(EXISTS  ${OpenCV_INCLUDE_DIR})

                #Find OpenCV version by looking at cvver.h
                file(STRINGS ${OpenCV_INCLUDE_DIR}/cvver.h OpenCV_VERSIONS_TMP REGEX "^#define CV_[A-Z]+_VERSION[ \t]+[0-9]+$")
                string(REGEX REPLACE ".*#define CV_MAJOR_VERSION[ \t]+([0-9]+).*" "\\1" OpenCV_VERSION_MAJOR ${OpenCV_VERSIONS_TMP})
                string(REGEX REPLACE ".*#define CV_MINOR_VERSION[ \t]+([0-9]+).*" "\\1" OpenCV_VERSION_MINOR ${OpenCV_VERSIONS_TMP})
                string(REGEX REPLACE ".*#define CV_SUBMINOR_VERSION[ \t]+([0-9]+).*" "\\1" OpenCV_VERSION_PATCH ${OpenCV_VERSIONS_TMP})
                set(OpenCV_VERSION ${OpenCV_VERSION_MAJOR}.${OpenCV_VERSION_MINOR}.${OpenCV_VERSION_PATCH} CACHE STRING "" FORCE)
                set(CVLIB_SUFFIX "${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}")
                
        endif(EXISTS "${OpenCV_DIR}/OpenCVConfig.cmake")

        
        

        ## Initiate the variable before the loop
        set(OpenCV_LIBS "")
        set(OpenCV_FOUND_TMP true)

        ## Loop over each components
        foreach(__CVLIB ${OPENCV_LIB_COMPONENTS})

                find_library(OpenCV_${__CVLIB}_LIBRARY_DEBUG NAMES "${__CVLIB}${CVLIB_SUFFIX}d" "lib${__CVLIB}${CVLIB_SUFFIX}d" PATHS "${OpenCV_DIR}/lib" NO_DEFAULT_PATH)
                find_library(OpenCV_${__CVLIB}_LIBRARY_RELEASE NAMES "${__CVLIB}${CVLIB_SUFFIX}" "lib${__CVLIB}${CVLIB_SUFFIX}" PATHS "${OpenCV_DIR}/lib" NO_DEFAULT_PATH)
                
                #Remove the cache value
                set(OpenCV_${__CVLIB}_LIBRARY "" CACHE STRING "" FORCE)
        
                #both debug/release
                if(OpenCV_${__CVLIB}_LIBRARY_DEBUG AND OpenCV_${__CVLIB}_LIBRARY_RELEASE)
                        set(OpenCV_${__CVLIB}_LIBRARY debug ${OpenCV_${__CVLIB}_LIBRARY_DEBUG} optimized ${OpenCV_${__CVLIB}_LIBRARY_RELEASE}  CACHE STRING "" FORCE)
                #only debug
                elseif(OpenCV_${__CVLIB}_LIBRARY_DEBUG)
                        set(OpenCV_${__CVLIB}_LIBRARY ${OpenCV_${__CVLIB}_LIBRARY_DEBUG}  CACHE STRING "" FORCE)
                #only release
                elseif(OpenCV_${__CVLIB}_LIBRARY_RELEASE)
                        set(OpenCV_${__CVLIB}_LIBRARY ${OpenCV_${__CVLIB}_LIBRARY_RELEASE}  CACHE STRING "" FORCE)
                #no library found
                else()
                        set(OpenCV_FOUND_TMP false)
                endif()
                
                #Add to the general list
                if(OpenCV_${__CVLIB}_LIBRARY)
                        set(OpenCV_LIBS ${OpenCV_LIBS} ${OpenCV_${__CVLIB}_LIBRARY})
                endif(OpenCV_${__CVLIB}_LIBRARY)
                
        endforeach(__CVLIB)


        set(OpenCV_FOUND ${OpenCV_FOUND_TMP} CACHE BOOL "" FORCE)


else(EXISTS "${OpenCV_DIR}")
        set(ERR_MSG "Please specify OpenCV directory using OpenCV_DIR env. variable")
endif(EXISTS "${OpenCV_DIR}")
##====================================================


##====================================================
## Print message
##----------------------------------------------------
if(NOT OpenCV_FOUND)
  # make FIND_PACKAGE friendly
  if(NOT OpenCV_FIND_QUIETLY)
        if(OpenCV_FIND_REQUIRED)
          message(FATAL_ERROR "OpenCV required but some headers or libs not found. ${ERR_MSG}")
        else(OpenCV_FIND_REQUIRED)
          message(STATUS "WARNING: OpenCV was not found. ${ERR_MSG}")
        endif(OpenCV_FIND_REQUIRED)
  endif(NOT OpenCV_FIND_QUIETLY)
endif(NOT OpenCV_FOUND)
##====================================================


##====================================================
## Backward compatibility
##----------------------------------------------------
if(OpenCV_FOUND)
option(OpenCV_BACKWARD_COMPA "Add some variable to make this script compatible with the other version of FindOpenCV.cmake" false)
if(OpenCV_BACKWARD_COMPA)
        find_path(OpenCV_INCLUDE_DIRS "cv.h" PATHS "${OpenCV_DIR}" PATH_SUFFIXES "include" "include/opencv" DOC "Include directory") 
        find_path(OpenCV_INCLUDE_DIR "cv.h" PATHS "${OpenCV_DIR}" PATH_SUFFIXES "include" "include/opencv" DOC "Include directory")
        set(OpenCV_LIBRARIES "${OpenCV_LIBS}" CACHE STRING "" FORCE)
endif(OpenCV_BACKWARD_COMPA)
endif(OpenCV_FOUND)
##====================================================

here the main that i used as hello word also took on internet.

int main(int argc, char *argv[])
{
    std::string image_path = cv::samples::findFile("image.png"); // this file must exist

    cv::Mat bpMatrix = cv::imread(image_path, cv::IMREAD_GRAYSCALE); // first init

    while (1337) {
        int key = cv::waitKey(0);

        if ('g' == key) {
            bpMatrix = cv::imread(image_path, cv::IMREAD_GRAYSCALE);
        }

        else if ('c' == key) {
            bpMatrix = cv::imread(image_path, cv::IMREAD_COLOR);
        }

        else if (27 == key) {
            break;
        }

        cv::imshow("Badprog: Hello world :D", bpMatrix);
    }
}

Thank you for your help.

that should be C:/opencv/opencv-4.6.0/build/install instead