Including opencv with fetchcontent does not work - c++

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.

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

CMake: add a directory prefix to `target_include_directories(...)` file #includes

I am using the Crypto++ library in my C++ project, and have installed it with the following (minimised) CMake code:
cmake_minimum_required(VERSION 3.24)
project(CMakeAddLibraryPrefixIncludes)
set(CMAKE_CXX_STANDARD 23)
include(FetchContent)
FetchContent_Declare(CryptoPP
GIT_REPOSITORY https://github.com/weidai11/cryptopp.git
GIT_TAG master)
FetchContent_MakeAvailable(CryptoPP)
add_executable(${PROJECT_NAME} main.cpp)
add_library(CryptoPP INTERFACE)
target_include_directories(CryptoPP INTERFACE ${CMAKE_BINARY_DIR}/_deps/cryptopp-src)
target_link_libraries(${PROJECT_NAME} CryptoPP)
Because the library has every header file in the top-level directory, all these files are accessible as #include <aes.h> for example. Is there a way that I can make it so that every file from CryptoPP is only accessible through a directory prefix like #include <cryptopp/aes.h>?
You can specify the folder for downloading sources by providing SOURCE_DIR to FetchContent_Declare. You can then use the parent folder of cryptopp_SOURCE_DIR as your include path.
FetchContent_Declare(CryptoPP
SOURCE_DIR ${FETCHCONTENT_BASE_DIR}/cryptopp-src/cryptopp
GIT_REPOSITORY https://github.com/weidai11/cryptopp.git
GIT_TAG master)
FetchContent_MakeAvailable(CryptoPP)
# ...
target_include_directories(CryptoPP INTERFACE "${cryptopp_SOURCE_DIR}/..")

How to include cmake dependencies from source for static use

I'm currently writing an application which will make use of OpenCV and a few other dependencies using cmake. For the sake of the question only one dependency is relevant.
How can I construct a CmakeLists.txt file which downloads the OpenCV source from github and prepares it for static use within my application?
I have tried using ExternalProject_Add which looked promising until I realised the static libraries, etc are not available when they are needed (as far as i understand). I've had similar issues with FetchContent_Declare and related functions.
I understand I can build all my dependencies outside of the single CmakeLists.txt and use them with something like: find_package( OpenCV REQUIRED PATHS "${CMAKE_CURRENT_LIST_DIR}/../build/opencv" ). This works perfectly fine, however I'm hoping to have everything self contained within cmake so anyone that checks out my application wont have to do any special configuration or dependency fetching. Just cmake build and they would be ready to go.
Note:
I've tried many things and followed many blog posts over the past week to try and figure these things out. The post would be excruciatingly long if I were to document them all. At this point im very confused with how it should all work and im hoping someone can point out something obvious im missing.
I'm also aware i can use something like vcpkg instead of compiling these applications from source. Due to the dependencies not listed I am not going down this route.
Environment:
Windows 10
Visual Studio 2019
Cmake
CmakeLists.txt
cmake_minimum_required(VERSION 3.19)
# set the project name
project(test-depends)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
set(CMAKE_DEBUG_POSTFIX d)
# Global settings
set(GLOBAL_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
# dependencies
include(ExternalProject)
## other dependencies are here
# ......
## OpenCV contrib
ExternalProject_Add(opencv_contrib
GIT_REPOSITORY https://github.com/opencv/opencv_contrib.git
GIT_TAG 4.5.0
BUILD_COMMAND ""
CONFIGURE_COMMAND ""
INSTALL_COMMAND ""
)
ExternalProject_Get_Property(opencv_contrib SOURCE_DIR)
set(OPENCV_CONTRIB_SOURCE_DIR ${SOURCE_DIR})
# OpenCV
ExternalProject_Add(opencv
GIT_REPOSITORY https://github.com/opencv/opencv.git
GIT_TAG 4.5.0
DEPENDS opencv_contrib # other dependencies omitted
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${GLOBAL_OUTPUT_PATH}/opencv
-DBUILD_SHARED_LIBS=OFF
-DOPENCV_EXTRA_MODULES_PATH=${OPENCV_CONTRIB_SOURCE_DIR}/modules
-DINSTALL_CREATE_DISTRIB=ON
-DBUILD_EXAMPLES=OFF
-DWITH_CUDA=OFF
-DBUILD_DOCS=OFF
-DDENABLE_CXX11=ON
-DDBUILD_TESTS=OFF
-DBUILD_PERF_TESTS=OFF
)
ExternalProject_Get_Property(opencv SOURCE_DIR BINARY_DIR)
set(OPENCV_SOURCE_DIR ${SOURCE_DIR})
set(OPENCV_BINARY_DIR ${BINARY_DIR})
file(GLOB_RECURSE PROJECT_SOURCES "src/*.h" "src/*.cpp")
add_executable(${PROJECT_NAME} ${PROJECT_SOURCES})
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20)
add_dependencies(${PROJECT_NAME} opencv)
include_directories(${GLOBAL_OUTPUT_PATH}/opencv/include)
target_link_directories( ${PROJECT_NAME}
PRIVATE ${OPENCV_BINARY_DIR}/lib
)
set(OpenCV_LIBS "ade;opencv_aruco450d;opencv_bgsegm450d;opencv_bioinspired450d;opencv_calib3d450d;opencv_ccalib450d;opencv_core450d;opencv_datasets450d;opencv_dnn450d;opencv_dnn_objdetect450d;opencv_dnn_superres450d;opencv_dpm450d;opencv_face450d;opencv_features2d450d;opencv_flann450d;opencv_fuzzy450d;opencv_gapi450d;opencv_hfs450d;opencv_highgui450d;opencv_imgcodecs450d;opencv_imgproc450d;opencv_img_hash450d;opencv_intensity_transform450d;opencv_line_descriptor450d;opencv_mcc450d;opencv_ml450d;opencv_objdetect450d;opencv_optflow450d;opencv_phase_unwrapping450d;opencv_photo450d;opencv_plot450d;opencv_quality450d;opencv_rapid450d;opencv_reg450d;opencv_rgbd450d;opencv_saliency450d;opencv_shape450d;opencv_stereo450d;opencv_stitching450d;opencv_structured_light450d;opencv_superres450d;opencv_surface_matching450d;opencv_text450d;opencv_tracking450d;opencv_video450d;opencv_videoio450d;opencv_videostab450d;opencv_xfeatures2d450d;opencv_ximgproc450d;opencv_xobjdetect450d;opencv_xphoto450d;")
target_link_libraries(
${PROJECT_NAME}
PRIVATE "${OpenCV_LIBS}"
)
src/main.cpp
#include <iostream>
#include "opencv2/opencv.hpp"
void main() {
cv::Mat testing;
std::cout << "hello" << std::endl;
}

CMake header files not being found in include

I have library, AprilTags, that uses cmake top build it.
I have another project AIV, that uses AprilTags. I want to keep the apriltags library inside of ~/aiv/apriltags but have another file, front_back_camera_demo that uses some of the files inside of AprilTags library.
So the file structure looks like
~/aiv/build/
/apriltags/CMakeLists.txt
/apriltags/AprilTags/TagDetector.h
/apriltags/AprilTags/*.h
/front_back_camera_demo.cpp
/CMakeLists.txt
When I run cmake on the top level CMakeLists.txt, it builds the AprilTags library successfully, but then I get a
front_back_camera_demo.cpp:72:35: fatal error: AprilTags/TagDetector.h: No such file or directory
error on the line where I include AprilTags/TagDetector.h
Here are the two relevant CMakeLists.txt:
Top level:
cmake_minimum_required(VERSION 2.6)
project(AIV)
add_subdirectory(apriltags)
add_executable(front_back_camera_demo front_back_camera_demo.cpp
Serial.cpp)
target_link_libraries(front_back_camera_demo apriltags)
Inside apriltags:
cmake_minimum_required(VERSION 2.6)
project(apriltags)
#add_definitions(-pg) #"-fopenmp)
# pull in the pods macros. See cmake/pods.cmake for documentation
set(POD_NAME apriltags)
include(cmake/pods.cmake)
file(GLOB SOURCE_FILES "src/*.cc")
include_directories(AprilTags . /opt/local/include)
add_library(apriltags ${SOURCE_FILES})
find_package(OpenCV)
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(apriltags ${OpenCV_LIBS}) #-pg) #-fopenmp)
pods_use_pkg_config_packages(apriltags eigen3)
if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
target_link_libraries(apriltags -L/opt/local/lib/) # MacPorts
special treatment...
else (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
pods_use_pkg_config_packages(apriltags libv4l2)
endif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
pods_install_libraries(apriltags)
file(GLOB header_files "AprilTags/*.h")
pods_install_headers(${header_files} DESTINATION AprilTags/)
pods_install_pkg_config_file(apriltags
LIBS -lapriltags
REQUIRES eigen3 opencv2
VERSION 1.0.0)
add_subdirectory(example)
What am I doing wrong?
Prefer the target_* commands.
apriltags/CMakeLists.txt:
target_include_directories(apriltags
PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}"
PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/AprilTags"
/opt/local/include)
That says, everything that uses the apriltags target will be able to access any includes in ".", that apriltags can also use "." and only apriltags itself uses content under the "AprilTags" and "/opt/local/include" directories.
If you really know what you are doing, you can get even more fine-grained by using generator expressions, but that is not necessary here to get it working.

Include Eigen library for Xcode project via CMake/CMakeLists.txt

I've got the following CMakeLists.txt (in my "project" folder) file for my project.
# define new project
PROJECT(SETUPMARKERTEST)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.0 FATAL_ERROR)
if(UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif(UNIX)
# Set static build for GLFW
SET(BUILD_SHED_LIBS OFF)
ADD_SUBDIRECTORY(ext/glfw-3.1.1)
# Set shared lib build for the rest
SET(BUILD_SHARED_LIBS ON)
# Find dependencies
SET(EIGEN_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/ext/Eigen-3.1.2")
FIND_PACKAGE(OpenCV REQUIRED)
# Set header and source files
SET(MAR_Test_SOURCES
src/main.cpp
src/MarkerTracker.h src/MarkerTracker.cpp
src/PoseEstimation.h src/PoseEstimation.cpp
)
# define executable
ADD_EXECUTABLE(${PROJECT_NAME} ${MAR_Test_SOURCES})
# define additional include directories and linking targets
INCLUDE_DIRECTORIES("ext/glfw-3.1.1/include" ${EIGEN_INCLUDE_DIR} ${OpenCV_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${OpenCV_LIBS} glfw ${OPENGL_glu_LIBRARY} ${GLFW_LIBRARIES})
And my Eigen folder is in "project/ext/Eigen/3.1.2/Eigen/".
Somehow when I created my project for Xcode (in "project/buildXcode/" with Cmake .. -G "Xcode") and run it, Xcode throws me the error:
So I guess there is some error in my CMakeLists.txt, unfortunately I received that file and I'm new to CMake and thus didn't write it on my own nor am I very skilled with CMake.
Do you know what causes the error and can you fix the CMakeLists.txt that my project runs with the Eigen library?
Unfortunately it looks like windows is having no problem with this, whereas mac is bleating.
You just have to use
#include <Eigen/Dense>
instead of
#include <Eigen\Dense>
...pretty stupid error.