Repository: conan-io/conan-center-index

Issue:
[request] opencv/4.5.0
### Package Details
* Package Name/Version: **opencv/4.5.0**
* Changelog: **https://github.com/opencv/opencv/releases**

Please support this new version! At least in conan-community

The above mentioned version is newly released by the upstream project and not yet available as a recipe. Please add this version.



Discussion:

Resolving patch:
diff --git a/recipes/opencv/4.x/conanfile.py b/recipes/opencv/4.x/conanfile.py
new file mode 100644
--- /dev/null
+++ b/recipes/opencv/4.x/conanfile.py
@@ -0,0 +1,395 @@
+from conans import ConanFile, CMake, tools
+from conans.errors import ConanInvalidConfiguration
+import os
+
+required_conan_version = ">=1.29.1"
+
+
+class OpenCVConan(ConanFile):
+    name = "opencv"
+    license = "Apache-2.0"
+    homepage = "https://opencv.org"
+    description = "OpenCV (Open Source Computer Vision Library)"
+    url = "https://github.com/conan-io/conan-center-index"
+    topics = ("computer-vision", "deep-learning", "image-processing")
+    settings = "os", "compiler", "build_type", "arch"
+    options = {"shared": [True, False],
+               "fPIC": [True, False],
+               "contrib": [True, False],
+               "parallel": [False, "tbb", "openmp"],
+               "with_jpeg": [False, "libjpeg", "libjpeg-turbo"],
+               "with_png": [True, False],
+               "with_tiff": [True, False],
+               "with_jpeg2000": [False, "jasper", "openjpeg"],
+               "with_openexr": [True, False],
+               "with_eigen": [True, False],
+               "with_webp": [True, False],
+               "with_gtk": [True, False]}
+    default_options = {"shared": False,
+                       "fPIC": True,
+                       "parallel": False,
+                       "contrib": False,
+                       "with_jpeg": "libjpeg",
+                       "with_png": True,
+                       "with_tiff": True,
+                       "with_jpeg2000": "jasper",
+                       "with_openexr": True,
+                       "with_eigen": True,
+                       "with_webp": True,
+                       "with_gtk": True}
+    exports_sources = "CMakeLists.txt"
+    generators = "cmake", "cmake_find_package"
+    _cmake = None
+
+    @property
+    def _source_subfolder(self):
+        return "source_subfolder"
+
+    @property
+    def _build_subfolder(self):
+        return "build_subfolder"
+
+    @property
+    def _contrib_folder(self):
+        return "contrib"
+
+    def config_options(self):
+        if self.settings.os == "Windows":
+            del self.options.fPIC
+        if self.settings.os != "Linux":
+            del self.options.gtk
+
+    def configure(self):
+        if self.settings.compiler == "Visual Studio" and \
+           "MT" in str(self.settings.compiler.runtime) and self.options.shared:
+            raise ConanInvalidConfiguration("Visual Studio and Runtime MT is not supported for shared library.")
+        if self.settings.compiler == "clang" and tools.Version(self.settings.compiler.version) < "4":
+            raise ConanInvalidConfiguration("Clang 3.x can build OpenCV 4.x due an internal bug.")
+        if self.options.shared:
+            del self.options.fPIC
+        self.options["libtiff"].jpeg = self.options.with_jpeg
+        self.options["jasper"].with_libjpeg = self.options.with_jpeg
+
+    def requirements(self):
+        self.requires("zlib/1.2.11")
+        if self.options.with_jpeg == "libjpeg":
+            self.requires("libjpeg/9d")
+        elif self.options.with_jpeg == "libjpeg-turbo":
+            self.requires("libjpeg-turbo/2.0.5")
+        if self.options.with_jpeg2000 == "jasper":
+            self.requires("jasper/2.0.21")
+        elif self.options.with_jpeg2000 == "openjpeg":
+            self.requires("openjpeg/2.3.1")
+        if self.options.with_png:
+            self.requires("libpng/1.6.37")
+        if self.options.with_openexr:
+            self.requires("openexr/2.5.3")
+        if self.options.with_tiff:
+            self.requires("libtiff/4.1.0")
+        if self.options.with_eigen:
+            self.requires("eigen/3.3.8")
+        if self.options.parallel == "tbb":
+            self.requires("tbb/2020.2")
+        if self.options.with_webp:
+            self.requires("libwebp/1.1.0")
+        if self.options.contrib:
+            self.requires("freetype/2.10.4")
+            self.requires("harfbuzz/2.7.2")
+            self.requires("gflags/2.2.2")
+            self.requires("glog/0.4.0")
+        if self.options.get_safe("with_gtk"):
+            self.requires("gtk/system")
+
+    def source(self):
+        tools.get(**self.conan_data["sources"][self.version][0])
+        os.rename("opencv-{}".format(self.version), self._source_subfolder)
+
+        tools.get(**self.conan_data["sources"][self.version][1])
+        os.rename("opencv_contrib-{}".format(self.version), self._contrib_folder)
+
+    def _patch_opencv(self):
+        for directory in ['libjasper', 'libjpeg-turbo', 'libjpeg', 'libpng', 'libtiff', 'libwebp', 'openexr', 'protobuf', 'zlib']:
+            tools.rmdir(os.path.join(self._source_subfolder, '3rdparty', directory))
+        if self.options.with_openexr:
+            find_openexr = os.path.join(self._source_subfolder, "cmake", "OpenCVFindOpenEXR.cmake")
+            tools.replace_in_file(find_openexr,
+                                  r'SET(OPENEXR_ROOT "C:/Deploy" CACHE STRING "Path to the OpenEXR \"Deploy\" folder")',
+                                  "")
+            tools.replace_in_file(find_openexr, "SET(OPENEXR_LIBSEARCH_SUFFIXES x64/Release x64 x64/Debug)", "")
+            tools.replace_in_file(find_openexr, "SET(OPENEXR_LIBSEARCH_SUFFIXES Win32/Release Win32 Win32/Debug)", "")
+
+        tools.replace_in_file(os.path.join(self._source_subfolder, "CMakeLists.txt"), "ANDROID OR NOT UNIX", "FALSE")
+        tools.replace_in_file(os.path.join(self._source_subfolder, "modules", "imgcodecs", "CMakeLists.txt"), "JASPER_", "Jasper_")
+
+    def _configure_cmake(self):
+        if self._cmake:
+            return self._cmake
+        self._cmake = CMake(self)
+        self._cmake.definitions["OPENCV_CONFIG_INSTALL_PATH"] = "cmake"
+        self._cmake.definitions["OPENCV_BIN_INSTALL_PATH"] = "bin"
+        self._cmake.definitions["OPENCV_LIB_INSTALL_PATH"] = "lib"
+        self._cmake.definitions["OPENCV_3P_LIB_INSTALL_PATH"] = "lib"
+        self._cmake.definitions["OPENCV_OTHER_INSTALL_PATH"] = "res"
+        self._cmake.definitions["OPENCV_LICENSES_INSTALL_PATH"] = "licenses"
+
+        self._cmake.definitions["BUILD_CUDA_STUBS"] = False
+        self._cmake.definitions["BUILD_DOCS"] = False
+        self._cmake.definitions["BUILD_EXAMPLES"] = False
+        self._cmake.definitions["BUILD_FAT_JAVA_LIB"] = False
+        self._cmake.definitions["BUILD_IPP_IW"] = False
+        self._cmake.definitions["BUILD_ITT"] = False
+        self._cmake.definitions["BUILD_JASPER"] = False
+        self._cmake.definitions["BUILD_JAVA"] = False
+        self._cmake.definitions["BUILD_JPEG"] = False
+        self._cmake.definitions["BUILD_OPENEXR"] = False
+        self._cmake.definitions["BUILD_OPENJPEG"] = False
+        self._cmake.definitions["BUILD_TESTS"] = False
+        self._cmake.definitions["BUILD_PROTOBUF"] = False
+        self._cmake.definitions["BUILD_PACKAGE"] = False
+        self._cmake.definitions["BUILD_PERF_TESTS"] = False
+        self._cmake.definitions["BUILD_USE_SYMLINKS"] = False
+        self._cmake.definitions["BUILD_opencv_apps"] = False
+        self._cmake.definitions["BUILD_opencv_java"] = False
+        self._cmake.definitions["BUILD_opencv_java_bindings_gen"] = False
+        self._cmake.definitions["BUILD_opencv_js"] = False
+        self._cmake.definitions["BUILD_ZLIB"] = False
+        self._cmake.definitions["BUILD_PNG"] = False
+        self._cmake.definitions["BUILD_TIFF"] = False
+        self._cmake.definitions["BUILD_WEBP"] = False
+        self._cmake.definitions["BUILD_TBB"] = False
+        self._cmake.definitions["OPENCV_FORCE_3RDPARTY_BUILD"] = False
+        self._cmake.definitions["BUILD_opencv_python2"] = False
+        self._cmake.definitions["BUILD_opencv_python3"] = False
+        self._cmake.definitions["BUILD_opencv_python_bindings_g"] = False
+        self._cmake.definitions["BUILD_opencv_python_tests"] = False
+        self._cmake.definitions["BUILD_opencv_ts"] = False
+
+        self._cmake.definitions["WITH_1394"] = False
+        self._cmake.definitions["WITH_ADE"] = False
+        self._cmake.definitions["WITH_ARAVIS"] = False
+        self._cmake.definitions["WITH_CLP"] = False
+        self._cmake.definitions["WITH_CUDA"] = False
+        self._cmake.definitions["WITH_CUFFT"] = False
+        self._cmake.definitions["WITH_CUBLAS"] = False
+        self._cmake.definitions["WITH_NVCUVID"] = False
+        self._cmake.definitions["WITH_FFMPEG"] = False
+        self._cmake.definitions["WITH_GSTREAMER"] = False
+        self._cmake.definitions["WITH_HALIDE"] = False
+        self._cmake.definitions["WITH_HPX"] = False
+        self._cmake.definitions["WITH_IMGCODEC_HDR"] = False
+        self._cmake.definitions["WITH_IMGCODEC_PFM"] = False
+        self._cmake.definitions["WITH_IMGCODEC_PXM"] = False
+        self._cmake.definitions["WITH_IMGCODEC_SUNRASTER"] = False
+        self._cmake.definitions["WITH_INF_ENGINE"] = False
+        self._cmake.definitions["WITH_IPP"] = False
+        self._cmake.definitions["WITH_ITT"] = False
+        self._cmake.definitions["WITH_LIBREALSENSE"] = False
+        self._cmake.definitions["WITH_MFX"] = False
+        self._cmake.definitions["WITH_NGRAPH"] = False
+        self._cmake.definitions["WITH_OPENCL"] = False
+        self._cmake.definitions["WITH_OPENCLAMDBLAS"] = False
+        self._cmake.definitions["WITH_OPENCLAMDFFT"] = False
+        self._cmake.definitions["WITH_OPENCL_SVM"] = False
+        self._cmake.definitions["WITH_OPENGL"] = False
+        self._cmake.definitions["WITH_OPENJPEG"] = False
+        self._cmake.definitions["WITH_OPENMP"] = False
+        self._cmake.definitions["WITH_OPENNI"] = False
+        self._cmake.definitions["WITH_OPENNI2"] = False
+        self._cmake.definitions["WITH_OPENVX"] = False
+        self._cmake.definitions["WITH_PLAIDML"] = False
+        self._cmake.definitions["WITH_PROTOBUF"] = False
+        self._cmake.definitions["WITH_PTHREADS_PF"] = False
+        self._cmake.definitions["WITH_PVAPI"] = False
+        self._cmake.definitions["WITH_QT"] = False
+        self._cmake.definitions["WITH_QUIRC"] = False
+        self._cmake.definitions["WITH_V4L"] = False
+        self._cmake.definitions["WITH_VA"] = False
+        self._cmake.definitions["WITH_VA_INTEL"] = False
+        self._cmake.definitions["WITH_VTK"] = False
+        self._cmake.definitions["WITH_VULKAN"] = False
+        self._cmake.definitions["WITH_XIMEA"] = False
+        self._cmake.definitions["WITH_XINE"] = False
+        self._cmake.definitions["WITH_LAPACK"] = False
+
+        self._cmake.definitions["WITH_GTK"] = self.options.get_safe("with_gtk", False)
+        self._cmake.definitions["WITH_GTK_2_X"] = self.options.get_safe("with_gtk", False)
+        self._cmake.definitions["WITH_WEBP"] = self.options.with_webp
+        self._cmake.definitions["WITH_JPEG"] = self.options.with_jpeg != False
+        self._cmake.definitions["WITH_PNG"] = self.options.with_png
+        self._cmake.definitions["WITH_TIFF"] = self.options.with_tiff
+        self._cmake.definitions["WITH_JASPER"] = self.options.with_jpeg2000 == "jasper"
+        self._cmake.definitions["WITH_OPENJPEG"] = self.options.with_jpeg2000 == "openjpeg"
+        self._cmake.definitions["WITH_OPENEXR"] = self.options.with_openexr
+        self._cmake.definitions["WITH_EIGEN"] = self.options.with_eigen
+        self._cmake.definitions["WITH_DSHOW"] = self.settings.compiler == "Visual Studio"
+        self._cmake.definitions["WITH_MSMF"] = self.settings.compiler == "Visual Studio"
+        self._cmake.definitions["WITH_MSMF_DXVA"] = self.settings.compiler == "Visual Studio"
+        self._cmake.definitions["OPENCV_MODULES_PUBLIC"] = "opencv"
+        if self.options.contrib:
+            self._cmake.definitions['OPENCV_EXTRA_MODULES_PATH'] = os.path.join(self.build_folder, self._contrib_folder, 'modules')
+        if self.options.with_openexr:
+            self._cmake.definitions["OPENEXR_ROOT"] = self.deps_cpp_info["openexr"].rootpath
+        if self.options.with_jpeg2000 == "openjpeg":
+            openjpeg_version = tools.Version(self.deps_cpp_info["openjpeg"].version)
+            self._cmake.definitions["OPENJPEG_MAJOR_VERSION"] = openjpeg_version.major
+            self._cmake.definitions["OPENJPEG_MINOR_VERSION"] = openjpeg_version.minor
+            self._cmake.definitions["OPENJPEG_BUILD_VERSION"] = openjpeg_version.patch
+        if self.options.parallel:
+            self._cmake.definitions["WITH_TBB"] = self.options.parallel == "tbb"
+            self._cmake.definitions["WITH_OPENMP"] = self.options.parallel == "openmp"
+
+        self._cmake.definitions["ENABLE_PIC"] = self.options.get_safe("fPIC", True)
+
+        if self.settings.compiler == "Visual Studio":
+            self._cmake.definitions["BUILD_WITH_STATIC_CRT"] = "MT" in str(self.settings.compiler.runtime)
+        self._cmake.configure(build_folder=self._build_subfolder)
+
+        return self._cmake
+
+    def build(self):
+        self._patch_opencv()
+        cmake = self._configure_cmake()
+        cmake.build()
+
+    def package(self):
+        self.copy("LICENSE", dst="licenses", src=self._source_subfolder)
+        cmake = self._configure_cmake()
+        cmake.install()
+        tools.rmdir(os.path.join(self.package_folder, "cmake"))
+
+    def package_info(self):
+        version = self.version.split(".")[:-1]  # last version number is not used
+        version = "".join(version) if self.settings.os == "Windows" else ""
+        debug = "d" if self.settings.build_type == "Debug" and self.settings.compiler == "Visual Studio" else ""
+
+        def get_lib_name(module):
+            prefix = "" if module in ("correspondence", "multiview", "numeric") else "opencv_"
+            return "%s%s%s%s" % (prefix, module, version, debug)
+
+        def add_components(components):
+            # TODO: OpenCV doesn't use cmake target namespace
+            for component in components:
+                conan_component = component["target"]
+                cmake_target = component["target"]
+                lib_name = get_lib_name(component["lib"])
+                requires = component["requires"]
+                self.cpp_info.components[conan_component].names["cmake_find_package"] = cmake_target
+                self.cpp_info.components[conan_component].names["cmake_find_package_multi"] = cmake_target
+                self.cpp_info.components[conan_component].libs = [lib_name]
+                self.cpp_info.components[conan_component].includedirs.append(os.path.join("include", "opencv4"))
+                self.cpp_info.components[conan_component].requires = requires
+                if self.settings.os == "Linux":
+                    self.cpp_info.components[conan_component].system_libs = ["dl", "m", "pthread", "rt"]
+
+                # CMake components names
+                conan_component_alias = conan_component + "_alias"
+                cmake_component = component["lib"]
+                self.cpp_info.components[conan_component_alias].names["cmake_find_package"] = cmake_component
+                self.cpp_info.components[conan_component_alias].names["cmake_find_package_multi"] = cmake_component
+                self.cpp_info.components[conan_component_alias].requires = [conan_component]
+                self.cpp_info.components[conan_component_alias].includedirs.append(os.path.join("include", "opencv4"))
+                self.cpp_info.components[conan_component_alias].libdirs = []
+                self.cpp_info.components[conan_component_alias].resdirs = []
+                self.cpp_info.components[conan_component_alias].bindirs = []
+                self.cpp_info.components[conan_component_alias].frameworkdirs = []
+
+        def imageformats_deps():
+            components = []
+            if self.options.with_jpeg2000:
+                components.append("{0}::{0}".format(self.options.with_jpeg2000))
+            if self.options.with_png:
+                components.append("libpng::libpng")
+            if self.options.with_jpeg:
+                components.append("{0}::{0}".format(self.options.with_jpeg))
+            if self.options.with_tiff:
+                components.append("libtiff::libtiff")
+            if self.options.with_openexr:
+                components.append("openexr::openexr")
+            if self.options.with_webp:
+                components.append("libwebp::libwebp")
+            return components
+
+        def eigen():
+            return ["eigen::eigen"] if self.options.with_eigen else []
+
+        def parallel():
+            if self.options.parallel:
+                return ["tbb::tbb"] if self.options.parallel == "tbb" else ["openmp"]
+            return []
+
+        def gtk():
+            return ["gtk::gtk"] if self.options.get_safe("with_gtk") else []
+
+        def freetype():
+            return ["freetype::freetype"] if self.options.contrib else []
+
+        def xfeatures2d():
+            return ["opencv_xfeatures2d"] if self.options.contrib else []
+
+        self.cpp_info.filenames["cmake_find_package"] = "OpenCV"
+        self.cpp_info.filenames["cmake_find_package_multi"] = "OpenCV"
+
+        add_components([
+            {"target": "opencv_core",       "lib": "core",       "requires": ["zlib::zlib"] + parallel() + eigen()},
+            {"target": "opencv_flann",      "lib": "flann",      "requires": ["opencv_core"] + eigen()},
+            {"target": "opencv_imgproc",    "lib": "imgproc",    "requires": ["opencv_core"] + eigen()},
+            {"target": "opencv_ml",         "lib": "ml",         "requires": ["opencv_core"] + eigen()},
+            {"target": "opencv_photo",      "lib": "photo",      "requires": ["opencv_core", "opencv_imgproc"] + eigen()},
+            {"target": "opencv_features2d", "lib": "features2d", "requires": ["opencv_core", "opencv_flann", "opencv_imgproc"] + eigen()},
+            {"target": "opencv_imgcodecs",  "lib": "imgcodecs",  "requires": ["opencv_core", "opencv_imgproc", "zlib::zlib"] + eigen() + imageformats_deps()},
+            {"target": "opencv_videoio",    "lib": "videoio",    "requires": ["opencv_core", "opencv_imgproc", "opencv_imgcodecs"] + eigen()},
+            {"target": "opencv_calib3d",    "lib": "calib3d",    "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_features2d"]+ eigen()},
+            {"target": "opencv_highgui",    "lib": "highgui",    "requires": ["opencv_core", "opencv_imgproc", "opencv_imgcodecs", "opencv_videoio"] + freetype() + eigen() + gtk()},
+            {"target": "opencv_objdetect",  "lib": "objdetect",  "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_features2d", "opencv_calib3d"] + eigen()},
+            {"target": "opencv_stitching",  "lib": "stitching",  "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_features2d", "opencv_calib3d"] + xfeatures2d() + eigen()},
+            {"target": "opencv_video",      "lib": "video",      "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_features2d", "opencv_calib3d"] + eigen()},
+        ])
+
+        if self.options.contrib:
+            add_components([
+                {"target": "opencv_intensity_transform", "lib": "intensity_transform", "requires": ["opencv_core", "opencv_imgproc"] + eigen()},
+                {"target": "opencv_phase_unwrapping",    "lib": "phase_unwrapping",    "requires": ["opencv_core", "opencv_imgproc"] + eigen()},
+                {"target": "opencv_plot",                "lib": "plot",                "requires": ["opencv_core", "opencv_imgproc"] + eigen()},
+                {"target": "opencv_quality",             "lib": "quality",             "requires": ["opencv_core", "opencv_imgproc", "opencv_ml"] + eigen()},
+                {"target": "opencv_reg",                 "lib": "reg",                 "requires": ["opencv_core", "opencv_imgproc"] + eigen()},
+                {"target": "opencv_surface_matching",    "lib": "surface_matching",    "requires": ["opencv_core", "opencv_flann"] + eigen()},
+                {"target": "opencv_xphoto",              "lib": "xphoto",              "requires": ["opencv_core", "opencv_imgproc", "opencv_photo"] + eigen()},
+                {"target": "opencv_alphamat",            "lib": "alphamat",            "requires": ["opencv_core", "opencv_imgproc"] + eigen()},
+                {"target": "opencv_freetype",            "lib": "freetype",            "requires": ["opencv_core", "opencv_imgproc", "freetype::freetype", "harfbuzz::harfbuzz"] + eigen()},
+                {"target": "opencv_fuzzy",               "lib": "fuzzy",               "requires": ["opencv_core", "opencv_imgproc"] + eigen()},
+                {"target": "opencv_hfs",                 "lib": "hfs",                 "requires": ["opencv_core", "opencv_imgproc"] + eigen()},
+                {"target": "opencv_img_hash",            "lib": "img_hash",            "requires": ["opencv_core", "opencv_imgproc"] + eigen()},
+                {"target": "opencv_line_descriptor",     "lib": "line_descriptor",     "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_features2d"] + eigen()},
+                {"target": "opencv_saliency",            "lib": "saliency",            "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_features2d"] + eigen()},
+                {"target": "opencv_datasets",            "lib": "datasets",            "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_ml", "opencv_imgcodecs"] + eigen()},
+                {"target": "opencv_rapid",               "lib": "rapid",               "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_features2d", "opencv_calib3d"] + eigen()},
+                {"target": "opencv_rgbd",                "lib": "rgbd",                "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_features2d", "opencv_calib3d"] + eigen()},
+                {"target": "opencv_shape",               "lib": "shape",               "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_features2d", "opencv_calib3d"] + eigen()},
+                {"target": "opencv_structured_light",    "lib": "structured_light",    "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_phase_unwrapping", "opencv_features2d", "opencv_calib3d"] + eigen()},
+                {"target": "opencv_videostab",           "lib": "videostab",           "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_photo", "opencv_features2d", "opencv_imgcodecs", "opencv_videoio", "opencv_calib3d", "opencv_video"] + eigen()},
+                {"target": "opencv_xfeatures2d",         "lib": "xfeatures2d",         "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_ml", "opencv_features2d", "opencv_calib3d", "opencv_shape", ] + eigen()},
+                {"target": "opencv_ximgproc",            "lib": "ximgproc",            "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_features2d", "opencv_imgcodecs", "opencv_calib3d", "opencv_video"] + eigen()},
+                {"target": "opencv_xobjdetect",          "lib": "xobjdetect",          "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_features2d", "opencv_imgcodecs", "opencv_calib3d", "opencv_objdetect"] + eigen()},
+                {"target": "opencv_aruco",               "lib": "aruco",               "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_features2d", "opencv_imgcodecs", "opencv_calib3d"] + eigen()},
+                {"target": "opencv_bgsegm",              "lib": "bgsegm",              "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_features2d", "opencv_calib3d", "opencv_video"] + eigen()},
+                {"target": "opencv_bioinspired",         "lib": "bioinspired",         "requires": ["opencv_core", "opencv_imgproc", "opencv_imgcodecs", "opencv_videoio", "opencv_highgui"] + eigen()},
+                {"target": "opencv_ccalib",              "lib": "ccalib",              "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_features2d", "opencv_imgcodecs", "opencv_videoio", "opencv_calib3d", "opencv_highgui"] + eigen()},
+                {"target": "opencv_dpm",                 "lib": "dpm",                 "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_features2d", "opencv_imgcodecs", "opencv_videoio", "opencv_calib3d", "opencv_highgui", "opencv_objdetect"] + eigen()},
+                {"target": "opencv_face",                "lib": "face",                "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_photo", "opencv_features2d", "opencv_calib3d", "opencv_objdetect"] + eigen()},
+                {"target": "opencv_optflow",             "lib": "optflow",             "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_video", "opencv_features2d", "opencv_imgcodecs", "opencv_calib3d", "opencv_video", "opencv_ximgproc"] + eigen()},
+                {"target": "opencv_sfm",                 "lib": "sfm",                 "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_ml", "opencv_features2d", "opencv_imgcodecs", "opencv_calib3d", "opencv_shape", "opencv_xfeatures2d", "correspondence", "multiview", "numeric", "glog::glog", "gflags::gflags"] + eigen()},
+                {"target": "correspondence",             "lib": "correspondence",      "requires": ["glog::glog", "multiview"] + eigen()},
+                {"target": "multiview",                  "lib": "multiview",           "requires": ["glog::glog", "numeric"] + eigen()},
+                {"target": "numeric",                    "lib": "numeric",             "requires": eigen()},
+                {"target": "opencv_superres",            "lib": "superres",            "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_features2d", "opencv_imgcodecs", "opencv_videoio", "opencv_calib3d", "opencv_video", "opencv_ximgproc", "opencv_optflow"] + eigen()},
+                {"target": "opencv_tracking",            "lib": "tracking",            "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_ml", "opencv_plot", "opencv_features2d", "opencv_imgcodecs", "opencv_calib3d", "opencv_datasets", "opencv_video"] + eigen()},
+                {"target": "opencv_stereo",              "lib": "stereo",              "requires": ["opencv_core", "opencv_flann", "opencv_imgproc", "opencv_ml", "opencv_plot", "opencv_features2d", "opencv_imgcodecs", "opencv_calib3d", "opencv_datasets", "opencv_video", "opencv_tracking"] + eigen()},
+            ])
+
+        if self.settings.os == "Windows":
+            self.cpp_info.components["opencv_highgui"].system_libs = ["comctl32", "gdi32", "ole32", "setupapi", "ws2_32", "vfw32"]
+        elif self.settings.os == "Macos":
+            self.cpp_info.components["opencv_highgui"].frameworks = ["Cocoa"]
+            self.cpp_info.components["opencv_videoio"].frameworks = ["Cocoa", "Accelerate", "AVFoundation", "CoreGraphics", "CoreMedia", "CoreVideo", "QuartzCore"]
+        elif self.settings.os == "iOS":
+            self.cpp_info.components["opencv_videoio"].frameworks = ["AVFoundation", "QuartzCore"]


Test patch:
diff --git a/recipes/opencv/4.x/test_package/CMakeLists.txt b/recipes/opencv/4.x/test_package/CMakeLists.txt
new file mode 100644
--- /dev/null
+++ b/recipes/opencv/4.x/test_package/CMakeLists.txt
@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 3.1)
+project(test_package)
+
+include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
+conan_basic_setup()
+
+find_package(OpenCV REQUIRED imgcodecs highgui objdetect CONFIG)
+
+add_executable(test_package test_package.cpp)
+target_link_libraries(test_package opencv::opencv_imgcodecs opencv::opencv_highgui opencv::opencv_objdetect)
+set_property(TARGET test_package PROPERTY CXX_STANDARD 11)
diff --git a/recipes/opencv/4.x/test_package/conanfile.py b/recipes/opencv/4.x/test_package/conanfile.py
new file mode 100644
--- /dev/null
+++ b/recipes/opencv/4.x/test_package/conanfile.py
@@ -0,0 +1,17 @@
+from conans import ConanFile, CMake, tools
+import os
+
+
+class OpenCVTestConan(ConanFile):
+    settings = "os", "compiler", "build_type", "arch"
+    generators = "cmake", "cmake_find_package_multi"
+
+    def build(self):
+        cmake = CMake(self)
+        cmake.configure()
+        cmake.build()
+
+    def test(self):
+        if not tools.cross_building(self.settings):
+            bin_path = os.path.join("bin", "test_package")
+            self.run(bin_path, run_environment=True)
diff --git a/recipes/opencv/4.x/test_package/test_package.cpp b/recipes/opencv/4.x/test_package/test_package.cpp
new file mode 100644
--- /dev/null
+++ b/recipes/opencv/4.x/test_package/test_package.cpp
@@ -0,0 +1,179 @@
+// Test file borrowed from OpenCV tutorial: https://docs.opencv.org/master/d3/d96/tutorial_basic_geometric_drawing.html
+
+/**
+ * @file Drawing_1.cpp
+ * @brief Simple geometric drawing
+ * @author OpenCV team
+ */
+#include <opencv2/core.hpp>
+#include <opencv2/imgproc.hpp>
+
+#define w 400
+
+using namespace cv;
+
+/// Function headers
+void MyEllipse( Mat img, double angle );
+void MyFilledCircle( Mat img, Point center );
+void MyPolygon( Mat img );
+void MyLine( Mat img, Point start, Point end );
+
+/**
+ * @function main
+ * @brief Main function
+ */
+int main( void ){
+
+  //![create_images]
+  /// Windows names
+  char atom_window[] = "Drawing 1: Atom";
+  char rook_window[] = "Drawing 2: Rook";
+
+  /// Create black empty images
+  Mat atom_image = Mat::zeros( w, w, CV_8UC3 );
+  Mat rook_image = Mat::zeros( w, w, CV_8UC3 );
+  //![create_images]
+
+  /// 1. Draw a simple atom:
+  /// -----------------------
+
+  //![draw_atom]
+  /// 1.a. Creating ellipses
+  MyEllipse( atom_image, 90 );
+  MyEllipse( atom_image, 0 );
+  MyEllipse( atom_image, 45 );
+  MyEllipse( atom_image, -45 );
+
+  /// 1.b. Creating circles
+  MyFilledCircle( atom_image, Point( w/2, w/2) );
+  //![draw_atom]
+
+  /// 2. Draw a rook
+  /// ------------------
+
+  //![draw_rook]
+  /// 2.a. Create a convex polygon
+  MyPolygon( rook_image );
+
+  //![rectangle]
+  /// 2.b. Creating rectangles
+  rectangle( rook_image,
+         Point( 0, 7*w/8 ),
+         Point( w, w),
+         Scalar( 0, 255, 255 ),
+         FILLED,
+         LINE_8 );
+  //![rectangle]
+
+  /// 2.c. Create a few lines
+  MyLine( rook_image, Point( 0, 15*w/16 ), Point( w, 15*w/16 ) );
+  MyLine( rook_image, Point( w/4, 7*w/8 ), Point( w/4, w ) );
+  MyLine( rook_image, Point( w/2, 7*w/8 ), Point( w/2, w ) );
+  MyLine( rook_image, Point( 3*w/4, 7*w/8 ), Point( 3*w/4, w ) );
+  //![draw_rook]
+
+  return(0);
+}
+
+/// Function Declaration
+
+/**
+ * @function MyEllipse
+ * @brief Draw a fixed-size ellipse with different angles
+ */
+//![my_ellipse]
+void MyEllipse( Mat img, double angle )
+{
+  int thickness = 2;
+  int lineType = 8;
+
+  ellipse( img,
+       Point( w/2, w/2 ),
+       Size( w/4, w/16 ),
+       angle,
+       0,
+       360,
+       Scalar( 255, 0, 0 ),
+       thickness,
+       lineType );
+}
+//![my_ellipse]
+
+/**
+ * @function MyFilledCircle
+ * @brief Draw a fixed-size filled circle
+ */
+//![my_filled_circle]
+void MyFilledCircle( Mat img, Point center )
+{
+  circle( img,
+      center,
+      w/32,
+      Scalar( 0, 0, 255 ),
+      FILLED,
+      LINE_8 );
+}
+//![my_filled_circle]
+
+/**
+ * @function MyPolygon
+ * @brief Draw a simple concave polygon (rook)
+ */
+//![my_polygon]
+void MyPolygon( Mat img )
+{
+  int lineType = LINE_8;
+
+  /** Create some points */
+  Point rook_points[1][20];
+  rook_points[0][0]  = Point(    w/4,   7*w/8 );
+  rook_points[0][1]  = Point(  3*w/4,   7*w/8 );
+  rook_points[0][2]  = Point(  3*w/4,  13*w/16 );
+  rook_points[0][3]  = Point( 11*w/16, 13*w/16 );
+  rook_points[0][4]  = Point( 19*w/32,  3*w/8 );
+  rook_points[0][5]  = Point(  3*w/4,   3*w/8 );
+  rook_points[0][6]  = Point(  3*w/4,     w/8 );
+  rook_points[0][7]  = Point( 26*w/40,    w/8 );
+  rook_points[0][8]  = Point( 26*w/40,    w/4 );
+  rook_points[0][9]  = Point( 22*w/40,    w/4 );
+  rook_points[0][10] = Point( 22*w/40,    w/8 );
+  rook_points[0][11] = Point( 18*w/40,    w/8 );
+  rook_points[0][12] = Point( 18*w/40,    w/4 );
+  rook_points[0][13] = Point( 14*w/40,    w/4 );
+  rook_points[0][14] = Point( 14*w/40,    w/8 );
+  rook_points[0][15] = Point(    w/4,     w/8 );
+  rook_points[0][16] = Point(    w/4,   3*w/8 );
+  rook_points[0][17] = Point( 13*w/32,  3*w/8 );
+  rook_points[0][18] = Point(  5*w/16, 13*w/16 );
+  rook_points[0][19] = Point(    w/4,  13*w/16 );
+
+  const Point* ppt[1] = { rook_points[0] };
+  int npt[] = { 20 };
+
+  fillPoly( img,
+        ppt,
+        npt,
+        1,
+        Scalar( 255, 255, 255 ),
+        lineType );
+}
+//![my_polygon]
+
+/**
+ * @function MyLine
+ * @brief Draw a simple line
+ */
+//![my_line]
+void MyLine( Mat img, Point start, Point end )
+{
+  int thickness = 2;
+  int lineType = LINE_8;
+
+  line( img,
+    start,
+    end,
+    Scalar( 0, 0, 0 ),
+    thickness,
+    lineType );
+}
+//![my_line]