Issue building opencv using FetchContent cmake command - c++

I really need your help because I really don't understand what I am doing wrong.
Using the very simple attached CMakeLists.txt, I got the following error (a lot of times):
CMake Error in build/_deps/opencv-src/modules/core/CMakeLists.txt:
Target "opencv_core" INTERFACE_INCLUDE_DIRECTORIES property contains path:
"/home/myuser/tmp/build"
which is prefixed in the build directory.
Can you help me fix it ?
Thank you for the help.
The CMakeLists.txt I am using:
cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
project(TEST_PROJECT)
set(CMAKE_CXX_STANDARD 14)
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0")
cmake_policy(SET CMP0135 NEW)
endif ()
include(FetchContent)
FetchContent_Declare(
opencv
GIT_REPOSITORY https://github.com/opencv/opencv.git
GIT_TAG 4.6.0
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(opencv)
set(OpenCV_DIR ${CMAKE_CURRENT_BINARY_DIR})
find_package(OpenCV REQUIRED)

Tried the same on a Windows system - with no success either.
In the end, I installed OpenCV outside of the build and source tree. Then used only find_package in the CMakeList.txt.
I had problems passing varibales to the OpenCV build when using FetchContent too. E.g. for using TBB or CUDA.

As #sweenish guessed, the problem was the OpenCV_DIR variable definition. So I remove this line and add the OVERRIDE_FIND_PACKAGE in the FetchContent_Declare call. And now it works fine on both systems, Linux and Windows.
My CMakeLists.txt now looks like:
cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
project(TEST_PROJECT)
set(CMAKE_CXX_STANDARD 14)
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0")
cmake_policy(SET CMP0135 NEW)
endif ()
include(FetchContent)
FetchContent_Declare(
opencv
GIT_REPOSITORY https://github.com/opencv/opencv.git
GIT_TAG 4.6.0
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
OVERRIDE_FIND_PACKAGE
)
FetchContent_MakeAvailable(opencv)
find_package(OpenCV REQUIRED)

Related

how to setup proprely a cmakefile to build an universal binary (macos M1, linux and windows) including SFML and TGUI llibraries

I'm working on a project where we need to use teh SFML and TGUI libraries, but now that we try to compile the TGUI lib with the CmakeFile, I get an error on my macbook M1 because TGUI uses a member of SFML called "auto_ptr" which has been deprecated.
/SFML/Audio/AudioDevice.cpp:128:10: error: no member named 'auto_ptr' in namespace 'std'
/SFML/Audio/AudioDevice.cpp:128:19: error: 'AudioDevice' does not refer to a value
/SFML/Audio/AudioDevice.cpp:130:9: error: use of undeclared identifier 'device'
I tried to specify other compilers to see if it changes anything but it didn't really work.
Can someone tell what could be changed/added in my CMakeLists.txt file to make it work, and if you see other things that could be improved in it feel free to comment it !
The content of the CMakeLists.txt :
cmake_minimum_required(VERSION 3.19)
project(r-type VERSION 1.0)
# set flags
set(BUILD_SHARED_LIBS OFF)
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED true)
# include dirs
include_directories("includes")
include_directories("includes/external")
include(FetchContent)
#installing SFML
FetchContent_Declare(
SFML
GIT_REPOSITORY https://github.com/SFML/SFML.git
GIT_TAG 2.5.1
)
FetchContent_MakeAvailable(SFML)
FetchContent_Declare(
TGUI
GIT_REPOSITORY https://github.com/texus/TGUI.git
GIT_TAG v0.9.5
)
FetchContent_MakeAvailable(TGUI)
# install enet
message(STATUS "Checking for enet ${PROJECT_SOURCE_DIR}")
if (NOT EXISTS ${PROJECT_SOURCE_DIR}/includes/external/enet.h)
message(STATUS "Downloading external library: enet in ${PROJECT_SOURCE_DIR}")
file(DOWNLOAD
https://github.com/zpl-c/enet/releases/latest/download/enet.h
${PROJECT_SOURCE_DIR}/includes/external/enet.h)
endif()
add_executable(
r-type_client
src/client/Main.cpp
src/client/OtherFiles.cpp
)
target_link_libraries (r-type_client ${SFML_LIBRARIES})
target_link_libraries(
r-type_client
sfml-audio
sfml-graphics
tgui
)
After some research I found this working :
Adding this line :
set_target_properties(sfml-audio PROPERTIES CXX_STANDARD 98 CXX_STANDARD_REQUIRED YES CXX_EXTENSIONS NO)
after the FetchContent SFML block sets the Makefile to compile SFML using c++98
see https://en.sfml-dev.org/forums/index.php?topic=24313.0

GoogleTest gtest_discover_test could not find test

I'm trying to add google test to my project and keep getting
"[build] get_property could not find TARGET testcolor. Perhaps it has not yet been
"
This is my cmake file:
cmake_minimum_required(VERSION 3.13)
project(RAYTRACE)
set(CMAKE_CXX_STANDARD 20)
include(FetchContent)
include(CTest)
enable_testing()#Redundent I know
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lib)
set(INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)
include_directories("<...>/googletest-src/googletest/include")
##GTEST##
FetchContent_Declare(
googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.12.1
)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)
set(SOURCE_FILES
main.cpp
src/Utils/testcolor.cc
src/Utils/testcolor
)
add_executable(RAYTRACE ${SOURCE_FILES})
target_link_libraries(RAYTRACE
PRIVATE
testcolor
GTest::gtest_main
GTest::gtest
)
include(GoogleTest)
gtest_discover_tests(testcolor)
Without the last line gtest is built properly and the gtest.h header is included in "src/Utils/testcolor.cc" and detected.
yet I cant add the test.
I solved the problem by following the This
guide online which made me undersand my many many mistakes configuring CMake and GTest. Thanks!

How to add Eigen library to a cmake c++ project via FetchContent

Adding Eigen via
FetchContent_Declare(
eigen
GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git
GIT_TAG 3.3.9
)
FetchContent_GetProperties(eigen)
if(NOT eigen_POPULATED)
FetchContent_Populate(eigen)
add_subdirectory(${eigen_SOURCE_DIR} ${eigen_BINARY_DIR})
endif()
find_package (Eigen3 3.3 REQUIRED NO_MODULE)
gives me the error
CMake Error at o/b/x64-Debug/_deps/eigen-build/Eigen3Config.cmake:20 (include):
The file
D:/XXX/o/b/x64-Debug/_deps/eigen-build/Eigen3Targets.cmake
was generated by the export() command. It may not be used as the argument
to the include() command. Use ALIAS targets instead to refer to targets by
alternative names. D:\XXX\o/b/x64-Debug/_deps/eigen-build/Eigen3Config.cmake 20
But downloading Eigen manually and adding it works fine
add_subdirectory("${PROJECT_SOURCE_DIR}/extern/eigen")
find_package (Eigen3 3.3 REQUIRED NO_MODULE)
Any ideas ?
In any order:
Eigen only provide ALIAS target on master
ref: https://gitlab.com/libeigen/eigen/-/commit/cf0b5b0344a3bfcf410e95bf22289015a2daf34b#9a2aa4db38d3115ed60da621e012c0efc0172aae_671_599
FetchContent usage could be
include(FetchContent)
FetchContent_Declare(
Eigen
GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git
GIT_TAG master
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE)
set(EIGEN_BUILD_DOC OFF)
# note: To disable eigen tests,
# you should put this code in a add_subdirectory to avoid to change
# BUILD_TESTING for your own project too since variables are directory
# scoped
set(BUILD_TESTING OFF)
set(EIGEN_BUILD_PKGCONFIG OFF)
set( OFF)
FetchContent_MakeAvailable(Eigen)
...
target_link_libraries(YourTarget PRIVATE Eigen3::Eigen)
For find_package() and FetchContent()/add_subdirectory() please see
https://gitlab.kitware.com/cmake/cmake/-/issues/17735
Alright i gave up on FetchContent, i also tried this Local install Eigen in CMAKE not finding target but this didn't work for me either.
I use ExternalProject now (https://github.com/qulacs/qulacs/blob/master/CMakeLists.txt) for fetching and linking eigen
include(ExternalProject)
set(EIGEN_BUILD_DIR ${CMAKE_BINARY_DIR}/eigen)
set(EIGEN_INSTALL_DIR ${CMAKE_SOURCE_DIR}/include/eigen3)
set(EIGEN_INCLUDE_DIR ${EIGEN_INSTALL_DIR})
ExternalProject_Add(
eigen
URL https://gitlab.com/libeigen/eigen/-/archive/3.3.7/eigen-3.3.7.tar.gz
PREFIX ${EIGEN_BUILD_DIR}
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND
${CMAKE_COMMAND} -E copy_directory ${EIGEN_BUILD_DIR}/src/eigen/Eigen ${EIGEN_INCLUDE_DIR}/Eigen
&& ${CMAKE_COMMAND} -E copy_directory ${EIGEN_BUILD_DIR}/src/eigen/unsupported ${EIGEN_INCLUDE_DIR}/unsupported
TEST_COMMAND ""
)
include_directories(SYSTEM ${EIGEN_INCLUDE_DIR})
Additionally add_dependencies has to be used
add_executable(test1 "test1.cpp")
add_dependencies(test1 eigen)
Fetchcontent is great, but it has the unwanted side-effect that your workspace becomes cluttered by all targets of your dependency. If you don't like this then ExternalProject_Add seems to be a reasonable solution. In your case the following should work:
include(ExternalProject)
set(EIGEN_INSTALL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/eigen-install/")
ExternalProject_Add(
eigen
URL https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.tar.gz
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/eigen-src"
BINARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/eigen-build"
INSTALL_DIR "${EIGEN_INSTALL_DIR}"
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
-DCMAKE_BUILD_TYPE=Release
)
file(MAKE_DIRECTORY ${EIGEN_INSTALL_DIR}/include) # avoid race condition
add_library(eigenlib INTERFACE IMPORTED GLOBAL)
add_dependencies(eigenlib eigen)
target_compile_features(eigenlib INTERFACE cxx_std_14)
set_target_properties(eigenlib PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${EIGEN_INSTALL_DIR}/include/eigen3
)
Note that the dependecy is linked to an interface library eigenlib that you can subsequenly link to your own targets as follows:
add_library(linalg INTERFACE)
target_include_directories(linalg
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>)
target_link_libraries(linalg INTERFACE eigenlib)
I would like to expand on #Mizux's answer.
In their comment, there is a set( OFF) statement that does nothing. Also, to remove a CMake warning, you might need to do:
include(FetchContent)
FetchContent_Declare(
Eigen
GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git
GIT_TAG master
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE)
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
set(EIGEN_BUILD_DOC OFF)
set(EIGEN_BUILD_PKGCONFIG OFF)
FetchContent_MakeAvailable(Eigen)
This removes the warning for this policy change.

Including opencv with fetchcontent does not work

I'm trying to include opencv in my c++ project. I want CMake to handle this for me.
Currently I'm at the point where I need to include opencv with the tag: #include <opencv2/opencv.hpp>
The files in the _deps/opencv-src directory throw the following error though:
Scanning dependencies of target VisionC
Building CXX object CMakeFiles/VisionC.dir/main.cpp.o
In file included from /Users/koen/Vakken/MotionVision/VisionC/main.cpp:2:
/Users/koen/Vakken/MotionVision/VisionC/cmake-build-debug/_deps/opencv-src/include/opencv2/opencv.hpp:48:10: fatal error: 'opencv2/opencv_modules.hpp' file not found
#include "opencv2/opencv_modules.hpp"
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
It seems Like the files can't include their own headers
My CMakeLists file is still pretty simple:
cmake_minimum_required(VERSION 3.17)
project(VisionC)
set(CMAKE_CXX_STANDARD 20)
include(FetchContent)
FetchContent_Declare(
opencv
GIT_REPOSITORY https://github.com/opencv/opencv.git
GIT_TAG 4.4.0
)
FetchContent_GetProperties(opencv)
if (NOT opencv_POPULATED)
FetchContent_Populate(opencv)
add_subdirectory(${opencv_SOURCE_DIR} ${opencv_BINARY_DIR})
include_directories(${opencv_SOURCE_DIR}/include) # "/include" should be deleted somehow...
endif ()
FetchContent_MakeAvailable(opencv)
add_executable(VisionC main.cpp)
target_link_libraries(VisionC opencv_lib)
I think the "/include" in the include_directories line hints that the library is included in a directory to "high" or so... I'm not sure how I should change this. If I delete this line I have to include opencv like #include <include/opencv2/opencv.hpp>
I found the solution, this is my cmakelists now:
cmake_minimum_required(VERSION 3.17)
project(VisionC)
set(CMAKE_CXX_STANDARD 20)
# Fetch from git
include(FetchContent)
FetchContent_Declare(
opencv
GIT_REPOSITORY https://github.com/opencv/opencv.git
GIT_TAG 4.4.0
)
FetchContent_GetProperties(opencv)
if (NOT opencv_POPULATED)
FetchContent_Populate(opencv)
endif ()
FetchContent_MakeAvailable(opencv)
# Find on pc
set(OpenCV_DIR ${CMAKE_CURRENT_BINARY_DIR})
include_directories(${OpenCV_INCLUDE_DIRS})
find_package(OpenCV REQUIRED)
# Link
add_executable(VisionC main.cpp)
target_link_libraries(VisionC ${OpenCV_LIBS})
The solution provided by #Typhaon is not a solution at all because it uses find_package alongside FetchContent and only uses the result of the find_package ignoring the fetched content. In, other words if you remove FetchContent usages it will work. If anyone is wondering what is the proper integration of OpenCV with find_package, take a look at the example provided by OpenCV https://github.com/opencv/opencv/blob/4.x/samples/cpp/example_cmake/CMakeLists.txt.
So, what about fetch_content or even using add_subdriectory?
That kind of usage is currently unsupported
https://github.com/opencv/opencv/issues/20548
But, I currently found a workaround that works for me with the current release. So the problem is that the targets of the OpenCV modules do not include in them the header include dir so when you are trying to link with them you can but you also need to specify the include directory manually. Currently, there are OPENCV_MODULE_opencv_{module_name}_LOCATION variables that point to the source directory of the module and they can be used for obtaining the include dir. For example
target_include_directories(my_target PRIVATE
${OPENCV_MODULE_opencv_core_LOCATION}/include
${OPENCV_MODULE_opencv_highgui_LOCATION}/include
)
target_link_libraries(my_target opencv_core opencv_highgui)
After this, there is an error like this
52 | #include "opencv2/opencv_modules.hpp"
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
And this is because for some reason the opencv_modules.hpp is being generated in the root of the build directory. But fortunately, there is a variable that is pointing to that directory OPENCV_CONFIG_FILE_INCLUDE_DIR. So the final CMake list file looks like the following
cmake_minimum_required(VERSION 3.23)
project(my_project)
set(CMAKE_CXX_STANDARD 20)
include(FetchContent)
FetchContent_Declare(
opencv
GIT_REPOSITORY https://github.com/opencv/opencv.git
GIT_TAG 4.6.0
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(opencv)
add_executable(my_target main.cpp)
target_include_directories(my_target PRIVATE
${OPENCV_CONFIG_FILE_INCLUDE_DIR}
${OPENCV_MODULE_opencv_core_LOCATION}/include
${OPENCV_MODULE_opencv_highgui_LOCATION}/include
)
target_link_libraries(my_target opencv_core opencv_highgui)
The downside of this workaround is that the mentioned variables can change over the releases, and this currently works for 4.6.0.

Using OpenCv with CLion

Hey im trying to use the OpenCV Lib on elementary OS (based on Ubuntu).
I followed this tutorial:
https://www.youtube.com/watch?v=i1K9rXiei9I
I added this lines to the CmakeList.txt:
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(myOpenCVTest ${OpenCV_LIBS})
But when i build the project it fails with some errors like:
/usr/bin/ld: cannot find -lopencv_core
...
Can anyone help me???
I solved the problem.
First I deleted all old OpenCV files and installations.
After that I followed this guide to install OpenCV and all required packages.
And now everything is working with this CmakeList.txt:
cmake_minimum_required(VERSION 2.8.4)
project(OpenCVTest)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
find_package( OpenCV REQUIRED )
set(SOURCE_FILES main.cpp)
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries( ${PROJECT_NAME} ${OpenCV_LIBS} )
I had to forcefully declare OpenCV_FOUND 1 in the cmake file, The whole file looks like :
cmake_minimum_required(VERSION 3.3)
project(testing)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(OpenCV_FOUND 1)
find_package( OpenCV REQUIRED )
set(SOURCE_FILES main.cpp)
add_executable(testing ${SOURCE_FILES})
target_link_libraries(testing ${OpenCV_LIBS})
(following our chat in the comments section)
I am not sure what video did you use for the installation, but assuming you used cmake based installation you usually run make followed by sudo make install that copies everything to the right location
Alternatively you can add link_directories(home/Projects/opencv/opencv-3/build/lib/)
and include_directories((home/Projects/opencv/opencv-3/include/) to your CMakeLists.txt