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.