Включение opencv с fetchcontent не работает

#c #opencv #cmake

#c #opencv #cmake

Вопрос:

Я пытаюсь включить opencv в свой проект на c . Я хочу, чтобы CMake справился с этим за меня.

В настоящее время я нахожусь на том этапе, когда мне нужно включить opencv с тегом: #include <opencv2/opencv.hpp>

Однако файлы в каталоге _deps / opencv-src выдают следующую ошибку:

 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.
  

Похоже, что файлы не могут содержать свои собственные заголовки

Мой файл CMakeLists по-прежнему довольно прост:

 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)
  

Я думаю, что «/ include» в строке include_directories намекает на то, что библиотека включена в каталог с «высоким» или около того… Я не уверен, как мне следует это изменить. Если я удалю эту строку, я должен включить opencv, например #include <include/opencv2/opencv.hpp>

Ответ №1:

Я нашел решение, теперь это мои cmakelists:

 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})
  

Комментарии:

1. Поскольку FetchContent_MakeAvailable(opencv) вы следуете каноническому шаблону, вы можете удалить FetchContent_GetProperties / FetchContent_Populate , т.е. Все делается с помощью FetchContent_MakeAvailable … ссылка: cmake.org/cmake/help/latest/module /…

2. вы правы, я include_directories(${OpenCV_INCLUDE_DIRS}) тоже так думаю

3. Я пытался сделать то же самое, что и вы, но у меня есть список ошибок, подобных следующему: Target "opencv_core" INTERFACE_INCLUDE_DIRECTORIES property contains path: "~/CLionProjects/vision/cmake-build-debug" which is prefixed in the build directory. Вы знаете, почему?

4. Честно говоря, это было для школьного проекта. Я только что запустил его. Прошу прощения. Возможно, вы могли бы просто изменить значение INTERFACE_INCLUDE_DIRECTORIES, чтобы исключить этот путь и посмотреть, что произойдет. Честно говоря, если бы вы могли это исправить, я думаю, что многие люди были бы очень счастливы в будущем!

5. кажется, сборка происходит очень медленно

Ответ №2:

Решение, предоставленное @Typhaon, вообще не является решением, потому что оно использует find_package наряду с fetchContent и использует только результат find_package, игнорируя извлеченное содержимое. Другими словами, если вы удалите обычаи fetchContent, это будет работать. Если кому-то интересно, какова правильная интеграция OpenCV с find_package, взгляните на пример, предоставленный OpenCV https://github.com/opencv/opencv/blob/4.x/samples/cpp/example_cmake/CMakeLists.txt .

Итак, как насчет fetch_content или даже использования add_subdriectory? Такое использование в настоящее время не поддерживается https://github.com/opencv/opencv/issues/20548

Но в настоящее время я нашел обходной путь, который работает для меня с текущей версией. Итак, проблема в том, что целевые объекты модулей OpenCV не включают в себя заголовок include dir, поэтому, когда вы пытаетесь связать с ними, вы можете, но вам также необходимо указать каталог включения вручную. В настоящее время существуют переменные OPENCV_MODULE_opencv_{module_name}_LOCATION, которые указывают на исходный каталог модуля, и их можно использовать для получения каталога include . Например

 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)
  

После этого возникает ошибка, подобная этой

    52 | #include "opencv2/opencv_modules.hpp"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
  

И это потому, что по какой-то причине opencv_modules.hpp генерируется в корне каталога сборки. Но, к счастью, есть переменная, которая указывает на этот каталог OPENCV_CONFIG_FILE_INCLUDE_DIR . Итак, окончательный файл списка CMake выглядит следующим образом

 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)
  

Недостатком этого обходного пути является то, что упомянутые переменные могут меняться с выпусками, и в настоящее время это работает для 4.6.0.